From ec9771d57f94cc204491b3174e88069d08cdd684 Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Sun, 8 Feb 2009 09:22:19 +0000 Subject: [PATCH] Wire up break and continue processing to the new stack depth adjuster. If people could beat on it and let me know if there are any new semantics required by newer language standards or DRs or any little details I goofed on, I'd be happy to fix any issues found. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64079 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGStmt.cpp | 88 +++++++++++++++++++---------------- lib/CodeGen/CodeGenFunction.h | 22 +++++++-- 2 files changed, 68 insertions(+), 42 deletions(-) diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 19977ec380..5072d63593 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -198,20 +198,7 @@ void CodeGenFunction::EmitBlock(llvm::BasicBlock *BB, bool IsFinished) { Builder.SetInsertPoint(BB); } -void CodeGenFunction::EmitStackUpdate(const LabelStmt &S) { - if (StackDepthMap.find(&S) == StackDepthMap.end()) { - // If we can't find it, just remember the depth now, - // so we can validate it later. - // FIXME: We need to save a place to insert the adjustment, - // if needed, here, sa that later in EmitLabel, we can - // backpatch the adjustment into that place, instead of - // saying unsupported. - StackDepthMap[&S] = StackDepth; - return; - } - - // Find applicable stack depth, if any... - llvm::Value *V = StackDepthMap[&S]; +bool CodeGenFunction::EmitStackUpdate(llvm::Value *V) { // V can be 0 here, if it is, be sure to start searching from the // top of the function, as we want the next save after that point. for (unsigned int i = 0; i < StackSaveValues.size(); ++i) @@ -227,10 +214,25 @@ void CodeGenFunction::EmitStackUpdate(const LabelStmt &S) { llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stackrestore); Builder.CreateCall(F, V); } - } else - // FIXME: Move to semq and assert here, codegen isn't the right - // time to be checking. - CGM.ErrorUnsupported(&S, "invalid goto to VLA scope that has finished"); + } else return true; + return false; +} + +bool CodeGenFunction::EmitStackUpdate(const void *S) { + if (StackDepthMap.find(S) == StackDepthMap.end()) { + // If we can't find it, just remember the depth now, + // so we can validate it later. + // FIXME: We need to save a place to insert the adjustment, + // if needed, here, sa that later in EmitLabel, we can + // backpatch the adjustment into that place, instead of + // saying unsupported. + StackDepthMap[S] = StackDepth; + return false; + } + + // Find applicable stack depth, if any... + llvm::Value *V = StackDepthMap[S]; + return EmitStackUpdate(V); } void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) { @@ -250,24 +252,30 @@ void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) { Builder.ClearInsertionPoint(); } -void CodeGenFunction::EmitLabel(const LabelStmt &S) { - llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S); - if (StackDepthMap.find(&S) == StackDepthMap.end()) { +bool CodeGenFunction::StackFixupAtLabel(const void *S) { + if (StackDepthMap.find(S) == StackDepthMap.end()) { // We need to remember the stack depth so that we can readjust the // stack back to the right depth for this label if we want to // transfer here from a different depth. - StackDepthMap[&S] = StackDepth; + StackDepthMap[S] = StackDepth; } else { - if (StackDepthMap[&S] != StackDepth) { + if (StackDepthMap[S] != StackDepth) { // FIXME: Sema needs to ckeck for jumps that cross decls with // initializations for C++, and all VLAs, not just the first in // a block that does a stacksave. // FIXME: We need to save a place to insert the adjustment // when we do a EmitStackUpdate on a forward jump, and then // backpatch the adjustment into that place. - CGM.ErrorUnsupported(&S, "forward goto inside scope with VLA"); + return true; } } + return false; +} + +void CodeGenFunction::EmitLabel(const LabelStmt &S) { + llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S); + if (StackFixupAtLabel(&S)) + CGM.ErrorUnsupported(&S, "forward goto inside scope with VLA"); EmitBlock(NextBB); } @@ -292,7 +300,11 @@ void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) { // We need to adjust the stack, if the destination was (will be) at // a different depth. - EmitStackUpdate(*S.getLabel()); + if (EmitStackUpdate(S.getLabel())) + // FIXME: Move to semq and assert here, codegen isn't the right + // time to be checking. + CGM.ErrorUnsupported(S.getLabel(), + "invalid goto to VLA scope that has finished"); EmitBranch(getBasicBlockForLabel(S.getLabel())); } @@ -595,18 +607,17 @@ void CodeGenFunction::EmitBreakStmt(const BreakStmt &S) { return; } - for (unsigned i = 0; i < StackSaveValues.size(); i++) { - if (StackSaveValues[i]) { - CGM.ErrorUnsupported(&S, "break inside scope with VLA"); - return; - } - } - // If this code is reachable then emit a stop point (if generating // debug info). We have to do this ourselves because we are on the // "simple" statement path. if (HaveInsertPoint()) EmitStopPoint(&S); + + // We need to adjust the stack, if the destination was (will be) at + // a different depth. + if (EmitStackUpdate(BreakContinueStack.back().SaveBreakStackDepth)) + assert (0 && "break vla botch"); + llvm::BasicBlock *Block = BreakContinueStack.back().BreakBlock; EmitBranch(Block); } @@ -620,18 +631,17 @@ void CodeGenFunction::EmitContinueStmt(const ContinueStmt &S) { return; } - for (unsigned i = 0; i < StackSaveValues.size(); i++) { - if (StackSaveValues[i]) { - CGM.ErrorUnsupported(&S, "continue inside scope with VLA"); - return; - } - } - // If this code is reachable then emit a stop point (if generating // debug info). We have to do this ourselves because we are on the // "simple" statement path. if (HaveInsertPoint()) EmitStopPoint(&S); + + // We need to adjust the stack, if the destination was (will be) at + // a different depth. + if (EmitStackUpdate(BreakContinueStack.back().SaveContinueStackDepth)) + assert (0 && "continue vla botch"); + llvm::BasicBlock *Block = BreakContinueStack.back().ContinueBlock; EmitBranch(Block); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 836a36f952..320e26b82d 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -264,12 +264,28 @@ private: /// the return value of llvm.stacksave() is stored at the top of this stack. llvm::SmallVector StackSaveValues; - llvm::DenseMap StackDepthMap; + llvm::DenseMap StackDepthMap; + + /// StackFixupAtLabel - Routine to adjust the stack to the depth the + /// stack should be at by the time we transfer control flow to the + /// label. This is called as we emit destinations for control flow, + /// such as user labels for goto statements and compiler generated + /// labels for break and continue processsing. We return true, if + /// for any reason we can't generate code for the construct yet. + /// See EmitStackUpdate for the paired routine to mark the branch. + bool StackFixupAtLabel(const void *); /// EmitStackUpdate - Routine to adjust the stack to the depth the /// stack should be at by the time we transfer control flow to the - /// label. - void EmitStackUpdate(const LabelStmt &S); + /// label. This is called just before emitting branches for user + /// level goto processing, branhes for break or continue processing. + /// The llvm::value overload is used when handling break and + /// continue, as we know the stack depth directly. We return true, + /// if for any reason we can't generate code for the construct yet. + /// See StackFixupAtLabel for the paired routine to mark the + /// destinations. + bool EmitStackUpdate(llvm::Value *V); + bool EmitStackUpdate(const void *S); struct CleanupEntry { /// CleanupBlock - The block of code that does the actual cleanup. -- 2.40.0