Index: CodeGen/CodeGenFunction.h =================================================================== --- CodeGen/CodeGenFunction.h (revision 39889) +++ CodeGen/CodeGenFunction.h (arbetskopia) @@ -15,6 +15,7 @@ #define CODEGEN_CODEGENFUNCTION_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/LLVMBuilder.h" #include @@ -175,6 +176,9 @@ /// LabelMap - This keeps track of the LLVM basic block for each C label. llvm::DenseMap LabelMap; + + llvm::SmallVector BreakStack; + llvm::SmallVector ContinueStack; public: CodeGenFunction(CodeGenModule &cgm); @@ -254,7 +258,9 @@ void EmitForStmt(const ForStmt &S); void EmitReturnStmt(const ReturnStmt &S); void EmitDeclStmt(const DeclStmt &S); - + void EmitBreakStmt(); + void EmitContinueStmt(); + //===--------------------------------------------------------------------===// // LValue Expression Emission //===--------------------------------------------------------------------===// Index: CodeGen/CGStmt.cpp =================================================================== --- CodeGen/CGStmt.cpp (revision 39889) +++ CodeGen/CGStmt.cpp (arbetskopia) @@ -49,6 +49,9 @@ case Stmt::ReturnStmtClass: EmitReturnStmt(cast(*S)); break; case Stmt::DeclStmtClass: EmitDeclStmt(cast(*S)); break; + + case Stmt::BreakStmtClass: EmitBreakStmt(); break; + case Stmt::ContinueStmtClass: EmitContinueStmt(); break; } } @@ -126,8 +129,6 @@ } void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) { - // FIXME: Handle continue/break. - // Emit the header for the loop, insert it, which will create an uncond br to // it. llvm::BasicBlock *LoopHeader = new llvm::BasicBlock("whilecond"); @@ -148,11 +149,18 @@ // As long as the condition is true, go to the loop body. Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock); + + // Store the blocks to use for break and continue. + BreakStack.push_back(ExitBlock); + ContinueStack.push_back(LoopHeader); // Emit the loop body. EmitBlock(LoopBody); EmitStmt(S.getBody()); + BreakStack.pop_back(); + ContinueStack.pop_back(); + // Cycle to the condition. Builder.CreateBr(LoopHeader); @@ -161,7 +169,6 @@ } void CodeGenFunction::EmitDoStmt(const DoStmt &S) { - // FIXME: Handle continue/break. // TODO: "do {} while (0)" is common in macros, avoid extra blocks. Be sure // to correctly handle break/continue though. @@ -170,10 +177,21 @@ llvm::BasicBlock *LoopBody = new llvm::BasicBlock("dobody"); llvm::BasicBlock *AfterDo = new llvm::BasicBlock("afterdo"); EmitBlock(LoopBody); + + llvm::BasicBlock *DoCond = new llvm::BasicBlock("docond"); + // Store the blocks to use for break and continue. + BreakStack.push_back(AfterDo); + ContinueStack.push_back(DoCond); + // Emit the body of the loop into the block. EmitStmt(S.getBody()); + BreakStack.pop_back(); + ContinueStack.pop_back(); + + EmitBlock(DoCond); + // C99 6.8.5.2: "The evaluation of the controlling expression takes place // after each execution of the loop body." @@ -190,17 +208,20 @@ } void CodeGenFunction::EmitForStmt(const ForStmt &S) { - // FIXME: Handle continue/break. // FIXME: What do we do if the increment (f.e.) contains a stmt expression, // which contains a continue/break? - + // TODO: We could keep track of whether the loop body contains any break/continue + // statements and not create unnecessary blocks (like "afterfor" for a condless loop) + // if it doesn't. + // Evaluate the first part before the loop. if (S.getInit()) EmitStmt(S.getInit()); // Start the loop with a block that tests the condition. llvm::BasicBlock *CondBlock = new llvm::BasicBlock("forcond"); - llvm::BasicBlock *AfterFor = 0; + llvm::BasicBlock *AfterFor = new llvm::BasicBlock("afterfor"); + EmitBlock(CondBlock); // Evaluate the condition if present. If not, treat it as a non-zero-constant @@ -212,7 +233,6 @@ // As long as the condition is true, iterate the loop. llvm::BasicBlock *ForBody = new llvm::BasicBlock("forbody"); - AfterFor = new llvm::BasicBlock("afterfor"); Builder.CreateCondBr(BoolCondVal, ForBody, AfterFor); EmitBlock(ForBody); } else { @@ -220,9 +240,27 @@ // body, just fall into it. } + // If the foor loop doesn't have an increment we can just use the + // condition as the continue block + llvm::BasicBlock *ContinueBlock; + if (S.getInc()) + ContinueBlock = new llvm::BasicBlock("forinc"); + else + ContinueBlock = CondBlock; + + // Store the blocks to use for break and continue. + BreakStack.push_back(AfterFor); + ContinueStack.push_back(ContinueBlock); + // If the condition is true, execute the body of the for stmt. EmitStmt(S.getBody()); + + BreakStack.pop_back(); + ContinueStack.pop_back(); + if (S.getInc()) + EmitBlock(ContinueBlock); + // If there is an increment, emit it next. if (S.getInc()) EmitExpr(S.getInc()); @@ -230,11 +268,8 @@ // Finally, branch back up to the condition for the next iteration. Builder.CreateBr(CondBlock); - // Emit the fall-through block if there is any. - if (AfterFor) - EmitBlock(AfterFor); - else - EmitBlock(new llvm::BasicBlock()); + // Emit the fall-through block + EmitBlock(AfterFor); } /// EmitReturnStmt - Note that due to GCC extensions, this can have an operand @@ -284,3 +319,22 @@ for (const Decl *Decl = S.getDecl(); Decl; Decl = Decl->getNextDeclarator()) EmitDecl(*Decl); } + +void CodeGenFunction::EmitBreakStmt() +{ + assert(!BreakStack.empty()); + llvm::BasicBlock *Block = BreakStack.back(); + + Builder.CreateBr(Block); + EmitBlock(new llvm::BasicBlock()); +} + +void CodeGenFunction::EmitContinueStmt() +{ + assert(!ContinueStack.empty()); + + llvm::BasicBlock *Block = ContinueStack.back(); + Builder.CreateBr(Block); + EmitBlock(new llvm::BasicBlock()); +} +