diff options
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 43 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 5 |
2 files changed, 34 insertions, 14 deletions
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 0a67e57e34..1c5cb90cbe 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -16,8 +16,9 @@ #include "CodeGenFunction.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/InlineAsm.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/InlineAsm.h" +#include "llvm/Intrinsics.h" using namespace clang; using namespace CodeGen; @@ -129,6 +130,9 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, DI->EmitRegionStart(CurFn, Builder); } + // Push a null stack save value. + StackSaveValues.push_back(0); + for (CompoundStmt::const_body_iterator I = S.body_begin(), E = S.body_end()-GetLast; I != E; ++I) EmitStmt(*I); @@ -139,22 +143,33 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, DI->EmitRegionEnd(CurFn, Builder); } - if (!GetLast) - return RValue::get(0); + RValue RV; + if (!GetLast) + RV = RValue::get(0); + else { + // We have to special case labels here. They are statements, but when put + // at the end of a statement expression, they yield the value of their + // subexpression. Handle this by walking through all labels we encounter, + // emitting them before we evaluate the subexpr. + const Stmt *LastStmt = S.body_back(); + while (const LabelStmt *LS = dyn_cast<LabelStmt>(LastStmt)) { + EmitLabel(*LS); + LastStmt = LS->getSubStmt(); + } - // We have to special case labels here. They are statements, but when put at - // the end of a statement expression, they yield the value of their - // subexpression. Handle this by walking through all labels we encounter, - // emitting them before we evaluate the subexpr. - const Stmt *LastStmt = S.body_back(); - while (const LabelStmt *LS = dyn_cast<LabelStmt>(LastStmt)) { - EmitLabel(*LS); - LastStmt = LS->getSubStmt(); + EnsureInsertPoint(); + + RV = EmitAnyExpr(cast<Expr>(LastStmt), AggLoc); } - - EnsureInsertPoint(); - return EmitAnyExpr(cast<Expr>(LastStmt), AggLoc); + if (llvm::Value *V = StackSaveValues.pop_back_val()) { + V = Builder.CreateLoad(V, "tmp"); + + llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stackrestore); + Builder.CreateCall(F, V); + } + + return RV; } void CodeGenFunction::EmitBlock(llvm::BasicBlock *BB, bool IsFinished) { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 600582c96e..952c3b3c1c 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -166,6 +166,11 @@ private: /// statement range in current switch instruction. llvm::BasicBlock *CaseRangeBlock; + /// StackSaveValues - A stack(!) of stack save values. When a new scope is + /// entered, a null is pushed on this stack. If a VLA is emitted, then + /// the return value of llvm.stacksave() is stored at the top of this stack. + llvm::SmallVector<llvm::Value*, 8> StackSaveValues; + public: CodeGenFunction(CodeGenModule &cgm); |