From 2bb5cb490cc34084d74c85b0bfdd39899bea1e97 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 13 Oct 2009 06:55:33 +0000 Subject: reimplement codegen for indirect goto with the following advantages: 1. CGF now has fewer bytes of state (one pointer instead of a vector). 2. The generated code is determinstic, instead of getting labels in 'map order' based on pointer addresses. 3. Clang now emits one 'indirect goto switch' for each function, instead of one for each indirect goto. This fixes an M*N = N^2 IR size issue when there are lots of address-taken labels and lots of indirect gotos. 4. This also makes the default cause do something useful, reducing the size of the jump table needed (by one). llvm-svn: 83952 --- clang/lib/CodeGen/CGStmt.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'clang/lib/CodeGen/CGStmt.cpp') diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 62e465d7028..f58b5792678 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -282,6 +282,7 @@ void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) { EmitBranchThroughCleanup(getBasicBlockForLabel(S.getLabel())); } + void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) { // Emit initial switch which will be patched up later by // EmitIndirectSwitches(). We need a default dest, so we use the @@ -289,11 +290,17 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) { llvm::Value *V = Builder.CreatePtrToInt(EmitScalarExpr(S.getTarget()), llvm::Type::getInt32Ty(VMContext), "addr"); - llvm::SwitchInst *I = Builder.CreateSwitch(V, Builder.GetInsertBlock()); - IndirectSwitches.push_back(I); - - // Clear the insertion point to indicate we are in unreachable code. - Builder.ClearInsertionPoint(); + llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); + + + // Get the basic block for the indirect goto. + llvm::BasicBlock *IndGotoBB = GetIndirectGotoBlock(); + + // The first instruction in the block has to be the PHI for the switch dest, + // add an entry for this branch. + cast(IndGotoBB->begin())->addIncoming(V, CurBB); + + EmitBranch(IndGotoBB); } void CodeGenFunction::EmitIfStmt(const IfStmt &S) { -- cgit v1.2.3