diff options
author | Daniel Dunbar <daniel@zuster.org> | 2008-08-04 16:51:22 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2008-08-04 16:51:22 +0000 |
commit | 0ffb125996336fc7602b162c0a9e392f1a93060f (patch) | |
tree | 69ebef4f15bf86bc743f22e598ae9d6a9b87cd39 /lib/CodeGen/CodeGenFunction.cpp | |
parent | c63a1f276f7b324fd9a4be82098b1c8f7bf30733 (diff) |
Add CodeGen support for indirect goto.
- Follows emission scheme used by llvm-gcc, i.e. invent an id for
each label whose address is taken and replace each indirect goto by
a switch to each possible target.
- Currently we emit a switch for each indirect goto instead of
merging them as llvm-gcc does.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54318 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index e153ad9fd8..9814ae7137 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -68,7 +68,10 @@ bool CodeGenFunction::hasAggregateLLVMType(QualType T) { void CodeGenFunction::GenerateFunction(const Stmt *Body) { // Emit the function body. EmitStmt(Body); - + + // Finish emission of indirect switches. + EmitIndirectSwitches(); + // Emit debug descriptor for function end. CGDebugInfo *DI = CGM.getDebugInfo(); if (DI) { @@ -179,3 +182,33 @@ void CodeGenFunction::WarnUnsupported(const Stmt *S, const char *Type) { CGM.WarnUnsupported(S, Type); } +unsigned CodeGenFunction::GetIDForAddrOfLabel(const LabelStmt *L) { + // Use LabelIDs.size() as the new ID if one hasn't been assigned. + return LabelIDs.insert(std::make_pair(L, LabelIDs.size())).first->second; +} + +void CodeGenFunction::EmitIndirectSwitches() { + llvm::BasicBlock *Default; + + if (!LabelIDs.empty()) { + Default = getBasicBlockForLabel(LabelIDs.begin()->first); + } else { + // No possible targets for indirect goto, just emit an infinite + // loop. + Default = llvm::BasicBlock::Create("indirectgoto.loop", CurFn); + llvm::BranchInst::Create(Default, Default); + } + + for (std::vector<llvm::SwitchInst*>::iterator i = IndirectSwitches.begin(), + e = IndirectSwitches.end(); i != e; ++i) { + llvm::SwitchInst *I = *i; + + I->setSuccessor(0, Default); + for (std::map<const LabelStmt*,unsigned>::iterator LI = LabelIDs.begin(), + LE = LabelIDs.end(); LI != LE; ++LI) { + I->addCase(llvm::ConstantInt::get(llvm::Type::Int32Ty, + LI->second), + getBasicBlockForLabel(LI->first)); + } + } +} |