Implement clang support for indirect branch and address of label
using the new LLVM support for this. This is temporarily hiding behind horrible and ugly #ifdefs until the time when the optimizer is stable (hopefully a week or so). Until then, lets make it "opt in" :) llvm-svn: 85446
This commit is contained in:
@@ -58,7 +58,12 @@ struct EvalInfo {
|
||||
static bool EvaluateLValue(const Expr *E, APValue &Result, EvalInfo &Info);
|
||||
static bool EvaluatePointer(const Expr *E, APValue &Result, EvalInfo &Info);
|
||||
static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info);
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result, EvalInfo &Info);
|
||||
#else
|
||||
static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result,
|
||||
EvalInfo &Info);
|
||||
#endif
|
||||
static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info);
|
||||
static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info);
|
||||
|
||||
|
||||
@@ -776,11 +776,17 @@ public:
|
||||
}
|
||||
case Expr::AddrLabelExprClass: {
|
||||
assert(CGF && "Invalid address of label expression outside function.");
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
unsigned id =
|
||||
CGF->GetIDForAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel());
|
||||
llvm::Constant *C =
|
||||
llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), id);
|
||||
return llvm::ConstantExpr::getIntToPtr(C, ConvertType(E->getType()));
|
||||
#else
|
||||
llvm::Constant *Ptr =
|
||||
CGF->GetAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel());
|
||||
return llvm::ConstantExpr::getBitCast(Ptr, ConvertType(E->getType()));
|
||||
#endif
|
||||
}
|
||||
case Expr::CallExprClass: {
|
||||
CallExpr* CE = cast<CallExpr>(E);
|
||||
|
||||
@@ -135,11 +135,16 @@ public:
|
||||
}
|
||||
Value *VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E);
|
||||
Value *VisitAddrLabelExpr(const AddrLabelExpr *E) {
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
llvm::Value *V =
|
||||
llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()),
|
||||
CGF.GetIDForAddrOfLabel(E->getLabel()));
|
||||
|
||||
return Builder.CreateIntToPtr(V, ConvertType(E->getType()));
|
||||
#else
|
||||
llvm::Value *V = CGF.GetAddrOfLabel(E->getLabel());
|
||||
return Builder.CreateBitCast(V, ConvertType(E->getType()));
|
||||
#endif
|
||||
}
|
||||
|
||||
// l-values.
|
||||
|
||||
@@ -287,8 +287,13 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
|
||||
// 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.
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
llvm::Value *V = Builder.CreatePtrToInt(EmitScalarExpr(S.getTarget()),
|
||||
llvm::Type::getInt32Ty(VMContext),
|
||||
#else
|
||||
llvm::Value *V = Builder.CreateBitCast(EmitScalarExpr(S.getTarget()),
|
||||
llvm::Type::getInt8PtrTy(VMContext),
|
||||
#endif
|
||||
"addr");
|
||||
llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
|
||||
|
||||
|
||||
@@ -27,7 +27,11 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
|
||||
: BlockFunction(cgm, *this, Builder), CGM(cgm),
|
||||
Target(CGM.getContext().Target),
|
||||
Builder(cgm.getModule().getContext()),
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
DebugInfo(0), IndirectGotoSwitch(0),
|
||||
#else
|
||||
DebugInfo(0), IndirectBranch(0),
|
||||
#endif
|
||||
SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0),
|
||||
CXXThisDecl(0) {
|
||||
LLVMIntTy = ConvertType(getContext().IntTy);
|
||||
@@ -130,10 +134,33 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
|
||||
|
||||
EmitFunctionEpilog(*CurFnInfo, ReturnValue);
|
||||
|
||||
#ifdef USEINDIRECTBRANCH
|
||||
// If someone did an indirect goto, emit the indirect goto block at the end of
|
||||
// the function.
|
||||
if (IndirectBranch) {
|
||||
EmitBlock(IndirectBranch->getParent());
|
||||
Builder.ClearInsertionPoint();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
// Remove the AllocaInsertPt instruction, which is just a convenience for us.
|
||||
llvm::Instruction *Ptr = AllocaInsertPt;
|
||||
AllocaInsertPt = 0;
|
||||
Ptr->eraseFromParent();
|
||||
#ifdef USEINDIRECTBRANCH
|
||||
|
||||
// If someone took the address of a label but never did an indirect goto, we
|
||||
// made a zero entry PHI node, which is illegal, zap it now.
|
||||
if (IndirectBranch) {
|
||||
llvm::PHINode *PN = cast<llvm::PHINode>(IndirectBranch->getAddress());
|
||||
if (PN->getNumIncomingValues() == 0) {
|
||||
PN->replaceAllUsesWith(llvm::UndefValue::get(PN->getType()));
|
||||
PN->eraseFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
|
||||
@@ -466,13 +493,26 @@ void CodeGenFunction::EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty) {
|
||||
TypeInfo.second/8));
|
||||
}
|
||||
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
unsigned CodeGenFunction::GetIDForAddrOfLabel(const LabelStmt *L) {
|
||||
// Use LabelIDs.size()+1 as the new ID if one hasn't been assigned.
|
||||
unsigned &Entry = LabelIDs[L];
|
||||
if (Entry) return Entry;
|
||||
#else
|
||||
|
||||
llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelStmt *L) {
|
||||
// Make sure that there is a block for the indirect goto.
|
||||
if (IndirectBranch == 0)
|
||||
GetIndirectGotoBlock();
|
||||
#endif
|
||||
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
Entry = LabelIDs.size();
|
||||
#else
|
||||
llvm::BasicBlock *BB = getBasicBlockForLabel(L);
|
||||
#endif
|
||||
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
// If this is the first "address taken" of a label and the indirect goto has
|
||||
// already been seen, add this to it.
|
||||
if (IndirectGotoSwitch) {
|
||||
@@ -488,19 +528,42 @@ unsigned CodeGenFunction::GetIDForAddrOfLabel(const LabelStmt *L) {
|
||||
}
|
||||
|
||||
return Entry;
|
||||
#else
|
||||
// Make sure the indirect branch includes all of the address-taken blocks.
|
||||
IndirectBranch->addDestination(BB);
|
||||
return llvm::BlockAddress::get(CurFn, BB);
|
||||
#endif
|
||||
}
|
||||
|
||||
llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
// If we already made the switch stmt for indirect goto, return its block.
|
||||
if (IndirectGotoSwitch) return IndirectGotoSwitch->getParent();
|
||||
#else
|
||||
// If we already made the indirect branch for indirect goto, return its block.
|
||||
if (IndirectBranch) return IndirectBranch->getParent();
|
||||
#endif
|
||||
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
EmitBlock(createBasicBlock("indirectgoto"));
|
||||
#else
|
||||
CGBuilderTy TmpBuilder(createBasicBlock("indirectgoto"));
|
||||
#endif
|
||||
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
const llvm::IntegerType *Int32Ty = llvm::Type::getInt32Ty(VMContext);
|
||||
#else
|
||||
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
|
||||
#endif
|
||||
|
||||
// Create the PHI node that indirect gotos will add entries to.
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
llvm::Value *DestVal = Builder.CreatePHI(Int32Ty, "indirect.goto.dest");
|
||||
#else
|
||||
llvm::Value *DestVal = TmpBuilder.CreatePHI(Int8PtrTy, "indirect.goto.dest");
|
||||
#endif
|
||||
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
// Create the switch instruction. For now, set the insert block to this block
|
||||
// which will be fixed as labels are added.
|
||||
IndirectGotoSwitch = Builder.CreateSwitch(DestVal, Builder.GetInsertBlock());
|
||||
@@ -540,6 +603,11 @@ llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() {
|
||||
}
|
||||
|
||||
return IndirectGotoSwitch->getParent();
|
||||
#else
|
||||
// Create the indirect branch instruction.
|
||||
IndirectBranch = TmpBuilder.CreateIndirectBr(DestVal);
|
||||
return IndirectBranch->getParent();
|
||||
#endif
|
||||
}
|
||||
|
||||
llvm::Value *CodeGenFunction::GetVLASize(const VariableArrayType *VAT) {
|
||||
|
||||
@@ -183,13 +183,26 @@ public:
|
||||
void PopConditionalTempDestruction();
|
||||
|
||||
private:
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
CGDebugInfo* DebugInfo;
|
||||
#else
|
||||
CGDebugInfo *DebugInfo;
|
||||
#endif
|
||||
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
/// LabelIDs - Track arbitrary ids assigned to labels for use in implementing
|
||||
/// the GCC address-of-label extension and indirect goto. IDs are assigned to
|
||||
/// labels inside getIDForAddrOfLabel().
|
||||
std::map<const LabelStmt*, unsigned> LabelIDs;
|
||||
#else
|
||||
/// IndirectBranch - The first time an indirect goto is seen we create a
|
||||
/// block with an indirect branch. Every time we see the address of a label
|
||||
/// taken, we add the label to the indirect goto. Every subsequent indirect
|
||||
/// goto is codegen'd as a jump to the IndirectBranch's basic block.
|
||||
llvm::IndirectBrInst *IndirectBranch;
|
||||
#endif
|
||||
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
/// IndirectGotoSwitch - The first time an indirect goto is seen we create a
|
||||
/// block with the switch for the indirect gotos. Every time we see the
|
||||
/// address of a label taken, we add the label to the indirect goto. Every
|
||||
@@ -197,6 +210,7 @@ private:
|
||||
/// IndirectGotoSwitch's basic block.
|
||||
llvm::SwitchInst *IndirectGotoSwitch;
|
||||
|
||||
#endif
|
||||
/// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C
|
||||
/// decls.
|
||||
llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
|
||||
@@ -558,7 +572,11 @@ public:
|
||||
/// the input field number being accessed.
|
||||
static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts);
|
||||
|
||||
#ifndef USEINDIRECTBRANCH
|
||||
unsigned GetIDForAddrOfLabel(const LabelStmt *L);
|
||||
#else
|
||||
llvm::BlockAddress *GetAddrOfLabel(const LabelStmt *L);
|
||||
#endif
|
||||
llvm::BasicBlock *GetIndirectGotoBlock();
|
||||
|
||||
/// EmitMemSetToZero - Generate code to memset a value of the given type to 0.
|
||||
|
||||
Reference in New Issue
Block a user