Remove the last remnants of the Obj-C EH stack code.
llvm-svn: 64205
This commit is contained in:
parent
9b6c1d6313
commit
33c1b6528f
|
@ -2086,36 +2086,6 @@ void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
|
|||
CGF.Builder.ClearInsertionPoint();
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitJumpThroughFinally(llvm::BasicBlock *Dest) {
|
||||
EmitJumpThroughFinally(ObjCEHStack.back(), Dest);
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitJumpThroughFinally(ObjCEHEntry *E,
|
||||
llvm::BasicBlock *Dst) {
|
||||
if (!HaveInsertPoint())
|
||||
return;
|
||||
|
||||
// Find the destination code for this block. We always use 0 for the
|
||||
// fallthrough block (default destination).
|
||||
llvm::SwitchInst *SI = E->FinallySwitch;
|
||||
llvm::ConstantInt *ID;
|
||||
if (Dst == SI->getDefaultDest()) {
|
||||
ID = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
|
||||
} else {
|
||||
ID = SI->findCaseDest(Dst);
|
||||
if (!ID) {
|
||||
// No code found, get a new unique one by just using the number
|
||||
// of switch successors.
|
||||
ID = llvm::ConstantInt::get(llvm::Type::Int32Ty, SI->getNumSuccessors());
|
||||
SI->addCase(ID, Dst);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the destination code and branch.
|
||||
Builder.CreateStore(ID, E->DestCode);
|
||||
EmitBranch(E->FinallyBlock);
|
||||
}
|
||||
|
||||
/// EmitObjCWeakRead - Code gen for loading value of a __weak
|
||||
/// object: objc_read_weak (id *src)
|
||||
///
|
||||
|
|
|
@ -133,12 +133,8 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
|
|||
|
||||
// Keep track of the current cleanup stack depth.
|
||||
size_t CleanupStackDepth = CleanupEntries.size();
|
||||
|
||||
bool OldDidCallStackSave = DidCallStackSave;
|
||||
|
||||
// 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);
|
||||
|
@ -168,14 +164,6 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
|
|||
RV = EmitAnyExpr(cast<Expr>(LastStmt), AggLoc);
|
||||
}
|
||||
|
||||
if (llvm::Value *V = StackSaveValues.pop_back_val()) {
|
||||
StackDepth = V;
|
||||
V = Builder.CreateLoad(V, "tmp");
|
||||
|
||||
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stackrestore);
|
||||
Builder.CreateCall(F, V);
|
||||
}
|
||||
|
||||
DidCallStackSave = OldDidCallStackSave;
|
||||
|
||||
EmitCleanupBlocks(CleanupStackDepth);
|
||||
|
@ -202,47 +190,6 @@ void CodeGenFunction::EmitBlock(llvm::BasicBlock *BB, bool IsFinished) {
|
|||
Builder.SetInsertPoint(BB);
|
||||
}
|
||||
|
||||
bool CodeGenFunction::EmitStackUpdate(llvm::Value *V) {
|
||||
// If we're already at the depth we want...
|
||||
if (StackDepth == V)
|
||||
return false;
|
||||
|
||||
// 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)
|
||||
if (StackSaveValues[i] == V) {
|
||||
// The actual depth is actually in the next used slot, if any.
|
||||
while (++i < StackSaveValues.size()
|
||||
&& (V = StackSaveValues[i]) == 0) ;
|
||||
// If there were no other depth changes, we don't need any
|
||||
// adjustments.
|
||||
if (V) {
|
||||
V = Builder.CreateLoad(V, "tmp");
|
||||
// and restore it.
|
||||
llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stackrestore);
|
||||
Builder.CreateCall(F, V);
|
||||
}
|
||||
} 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) {
|
||||
// Emit a branch from the current block to the target one if this
|
||||
// was a real block. If this was just a fall-through block after a
|
||||
|
@ -260,31 +207,8 @@ void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) {
|
|||
Builder.ClearInsertionPoint();
|
||||
}
|
||||
|
||||
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;
|
||||
} else {
|
||||
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.
|
||||
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);
|
||||
EmitBlock(getBasicBlockForLabel(&S));
|
||||
}
|
||||
|
||||
|
||||
|
@ -294,36 +218,16 @@ void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
|
|||
}
|
||||
|
||||
void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
|
||||
// FIXME: Implement goto out in @try or @catch blocks.
|
||||
if (!ObjCEHStack.empty()) {
|
||||
CGM.ErrorUnsupported(&S, "goto inside an Obj-C exception block");
|
||||
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(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");
|
||||
|
||||
EmitBranchThroughCleanup(getBasicBlockForLabel(S.getLabel()));
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
|
||||
// FIXME: Implement indirect goto in @try or @catch blocks.
|
||||
if (!ObjCEHStack.empty()) {
|
||||
CGM.ErrorUnsupported(&S, "goto inside an Obj-C exception block");
|
||||
return;
|
||||
}
|
||||
|
||||
// Emit initial switch which will be patched up later by
|
||||
// EmitIndirectSwitches(). We need a default dest, so we use the
|
||||
// current BB, but this is overwritten.
|
||||
|
@ -557,13 +461,6 @@ void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
|
|||
/// if the function returns void, or may be missing one if the function returns
|
||||
/// non-void. Fun stuff :).
|
||||
void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
|
||||
for (unsigned i = 0; i < StackSaveValues.size(); i++) {
|
||||
if (StackSaveValues[i]) {
|
||||
CGM.ErrorUnsupported(&S, "return inside scope with VLA");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the result value, even if unused, to evalute the side effects.
|
||||
const Expr *RV = S.getRetValue();
|
||||
|
||||
|
@ -584,15 +481,6 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
|
|||
EmitAggExpr(RV, ReturnValue, false);
|
||||
}
|
||||
|
||||
if (!ObjCEHStack.empty()) {
|
||||
for (ObjCEHStackType::reverse_iterator i = ObjCEHStack.rbegin(),
|
||||
e = ObjCEHStack.rend(); i != e; ++i) {
|
||||
llvm::BasicBlock *ReturnPad = createBasicBlock("return.pad");
|
||||
EmitJumpThroughFinally(*i, ReturnPad);
|
||||
EmitBlock(ReturnPad);
|
||||
}
|
||||
}
|
||||
|
||||
EmitBranchThroughCleanup(ReturnBlock);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ using namespace CodeGen;
|
|||
|
||||
CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
|
||||
: CGM(cgm), Target(CGM.getContext().Target), SwitchInsn(NULL),
|
||||
CaseRangeBlock(NULL), StackDepth(0) {
|
||||
CaseRangeBlock(NULL) {
|
||||
LLVMIntTy = ConvertType(getContext().IntTy);
|
||||
LLVMPointerWidth = Target.getPointerWidth(0);
|
||||
}
|
||||
|
|
|
@ -88,47 +88,10 @@ public:
|
|||
uint32_t LLVMPointerWidth;
|
||||
|
||||
public:
|
||||
// FIXME: The following should be private once EH code is moved out of NeXT
|
||||
// runtime.
|
||||
|
||||
// ObjCEHStack - This keeps track of which object to rethrow from inside
|
||||
// @catch blocks and which @finally block exits from an EH scope should be
|
||||
// chained through.
|
||||
struct ObjCEHEntry {
|
||||
ObjCEHEntry(llvm::BasicBlock *fb, llvm::SwitchInst *fs, llvm::Value *dc)
|
||||
: FinallyBlock(fb), FinallySwitch(fs),
|
||||
DestCode(dc) {}
|
||||
|
||||
/// Entry point to the finally block.
|
||||
llvm::BasicBlock *FinallyBlock;
|
||||
|
||||
/// Switch instruction which runs at the end of the finally block to forward
|
||||
/// jumps through the finally block.
|
||||
llvm::SwitchInst *FinallySwitch;
|
||||
|
||||
/// Variable holding the code for the destination of a jump through the
|
||||
/// @finally block.
|
||||
llvm::Value *DestCode;
|
||||
};
|
||||
|
||||
/// ObjCEHValueStack - Stack of exception objects being handled, during IR
|
||||
/// generation for a @catch block.
|
||||
/// ObjCEHValueStack - Stack of Objective-C exception values, used for
|
||||
/// rethrows.
|
||||
llvm::SmallVector<llvm::Value*, 8> ObjCEHValueStack;
|
||||
|
||||
typedef llvm::SmallVector<ObjCEHEntry*, 8> ObjCEHStackType;
|
||||
ObjCEHStackType ObjCEHStack;
|
||||
|
||||
/// EmitJumpThroughFinally - Emit a branch from the current insert point
|
||||
/// through the finally handling code for \arg Entry and then on to \arg
|
||||
/// Dest. It is legal to call this function even if there is no current
|
||||
/// insertion point.
|
||||
///
|
||||
/// \param ExecuteTryExit - When true, the try_exit runtime function should be
|
||||
/// called prior to executing the finally code.
|
||||
void EmitJumpThroughFinally(ObjCEHEntry *Entry, llvm::BasicBlock *Dest);
|
||||
|
||||
void EmitJumpThroughFinally(llvm::BasicBlock *Dest);
|
||||
|
||||
/// PushCleanupBlock - Push a new cleanup entry on the stack and set the
|
||||
/// passed in block as the cleanup block.
|
||||
void PushCleanupBlock(llvm::BasicBlock *CleanupBlock);
|
||||
|
@ -229,47 +192,10 @@ private:
|
|||
// enter/leave scopes.
|
||||
llvm::DenseMap<const VariableArrayType*, llvm::Value*> VLASizeMap;
|
||||
|
||||
/// StackDepth - This keeps track of the stack depth. It is used to notice
|
||||
/// when control flow results in a change in stack depth and to arrange for
|
||||
/// the appropriate stack depth to be restored. VLAs are the primary means by
|
||||
/// which the stack depth changes.
|
||||
llvm::Value *StackDepth;
|
||||
|
||||
/// DidCallStackSave - Whether llvm.stacksave has been called. Used to avoid
|
||||
/// calling llvm.stacksave for multiple VLAs in the same scope.
|
||||
bool DidCallStackSave;
|
||||
|
||||
/// 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;
|
||||
|
||||
/// StackDepthMap - A association of stack depth that will be in effect for
|
||||
/// each label. If control flow is transferred to a label, we have to restore
|
||||
/// the desired stack depth at the destination label, beore we transfer to
|
||||
/// that label.
|
||||
llvm::DenseMap<const void*, llvm::Value *> 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. 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.
|
||||
llvm::BasicBlock *CleanupBlock;
|
||||
|
|
Loading…
Reference in New Issue