From ac24820fa54483b7d1943a57af0bece0f5dc5996 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 30 May 2007 00:13:02 +0000 Subject: Implement codegen support for labels and gotos. We now compile: void test1() { foo: goto foo; goto foo; goto foo; } void test() { goto l; l: ; } into: define void @test1() { entry: br label %foo foo: ; preds = %0, %foo, %entry br label %foo ; No predecessors! br label %foo ; No predecessors! } define void @test() { entry: br label %l l: ; preds = %entry } llvm-svn: 39524 --- clang/CodeGen/CodeGenFunction.cpp | 45 +++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) (limited to 'clang/CodeGen/CodeGenFunction.cpp') diff --git a/clang/CodeGen/CodeGenFunction.cpp b/clang/CodeGen/CodeGenFunction.cpp index ff31a835ce9..4061b417f7e 100644 --- a/clang/CodeGen/CodeGenFunction.cpp +++ b/clang/CodeGen/CodeGenFunction.cpp @@ -25,6 +25,15 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) : CGM(cgm), Target(CGM.getContext().Target) {} +llvm::BasicBlock *CodeGenFunction::getBasicBlockForLabel(const LabelStmt *S) { + BasicBlock *&BB = LabelMap[S]; + if (BB) return BB; + + // Create, but don't insert, the new block. + return BB = new BasicBlock(S->getName()); +} + + /// ConvertType - Convert the specified type to its LLVM form. const llvm::Type *CodeGenFunction::ConvertType(QualType T, SourceLocation Loc) { // FIXME: Cache these, move the CodeGenModule, expand, etc. @@ -104,11 +113,11 @@ const llvm::Type *CodeGenFunction::ConvertType(QualType T, SourceLocation Loc) { void CodeGenFunction::GenerateCode(const FunctionDecl *FD) { const llvm::Type *Ty = ConvertType(FD->getType(), FD->getLocation()); - llvm::Function *F = new Function(cast(Ty), - Function::ExternalLinkage, - FD->getName(), &CGM.getModule()); + CurFn = new Function(cast(Ty), + Function::ExternalLinkage, + FD->getName(), &CGM.getModule()); - BasicBlock *EntryBB = new BasicBlock("entry", F); + BasicBlock *EntryBB = new BasicBlock("entry", CurFn); // TODO: Walk the decls, creating allocas etc. @@ -132,6 +141,8 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { break; case Stmt::NullStmtClass: break; case Stmt::CompoundStmtClass: EmitCompoundStmt(cast(*S)); break; + case Stmt::LabelStmtClass: EmitLabelStmt(cast(*S)); break; + case Stmt::GotoStmtClass: EmitGotoStmt(cast(*S)); break; } } @@ -143,3 +154,29 @@ void CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S) { EmitStmt(*I); } +void CodeGenFunction::EmitBlock(BasicBlock *BB) { + // Emit a branch from this block to the next one if this was a real block. If + // this was just a fall-through block after a terminator, don't emit it. + if (!Builder.GetInsertBlock()->empty() || + Builder.GetInsertBlock()->getValueName()) { + Builder.CreateBr(BB); + } else { + // TODO: cache and reuse these. + Builder.GetInsertBlock()->eraseFromParent(); + } + CurFn->getBasicBlockList().push_back(BB); + Builder.SetInsertPoint(BB); +} + +void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) { + llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S); + + EmitBlock(NextBB); +} + +void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) { + Builder.CreateBr(getBasicBlockForLabel(S.getLabel())); + + Builder.SetInsertPoint(new BasicBlock("", CurFn)); +} + -- cgit v1.2.3