From 8c2b52552c90f39e4b2fed43e309e599e742b6ac Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 30 Oct 2009 01:27:03 +0000 Subject: [PATCH] Initial target-independent CodeGen support for BlockAddresses. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85556 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/AsmPrinter.h | 7 +++++ include/llvm/CodeGen/MachineBasicBlock.h | 12 +++++++ include/llvm/CodeGen/SelectionDAG.h | 2 ++ include/llvm/CodeGen/SelectionDAGNodes.h | 21 +++++++++++-- include/llvm/Target/TargetSelectionDAG.td | 4 +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 27 ++++++++++++++++ lib/CodeGen/MachineBasicBlock.cpp | 3 +- lib/CodeGen/MachineInstr.cpp | 10 ++++++ lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 2 ++ lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h | 1 + lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 31 +++++++++++++++++++ .../SelectionDAG/SelectionDAGBuild.cpp | 12 +++++-- utils/TableGen/DAGISelEmitter.cpp | 1 + 13 files changed, 128 insertions(+), 5 deletions(-) diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 62d0679fb73..a0bd330052b 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -22,6 +22,7 @@ #include "llvm/ADT/DenseMap.h" namespace llvm { + class BlockAddress; class GCStrategy; class Constant; class ConstantArray; @@ -334,6 +335,12 @@ namespace llvm { /// block label. MCSymbol *GetMBBSymbol(unsigned MBBID) const; + /// GetBlockAddressSymbol - Return the MCSymbol used to satisfy BlockAddress + /// uses of the specified basic block. + MCSymbol *GetBlockAddressSymbol(const BlockAddress *BA) const; + MCSymbol *GetBlockAddressSymbol(const Function *F, + const BasicBlock *BB) const; + /// EmitBasicBlockStart - This method prints the label for the specified /// MachineBasicBlock, an alignment (if present) and a comment describing /// it if appropriate. diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 2a9e86a04c0..585ee147a1a 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -76,6 +76,10 @@ class MachineBasicBlock : public ilist_node { /// exception handler. bool IsLandingPad; + /// AddressTaken - Indicate that this basic block is potentially the + /// target of an indirect branch. + bool AddressTaken; + // Intrusive list support MachineBasicBlock() {} @@ -92,6 +96,14 @@ public: /// const BasicBlock *getBasicBlock() const { return BB; } + /// hasAddressTaken - Test whether this block is potentially the target + /// of an indirect branch. + bool hasAddressTaken() const { return AddressTaken; } + + /// setHasAddressTaken - Set this block to reflect that it potentially + /// is the target of an indirect branch. + void setHasAddressTaken() { AddressTaken = true; } + /// getParent - Return the MachineFunction containing this basic block. /// const MachineFunction *getParent() const { return xParent; } diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index e0198ef2e3f..8400e86e7ea 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -326,6 +326,8 @@ public: unsigned Line, unsigned Col, MDNode *CU); SDValue getLabel(unsigned Opcode, DebugLoc dl, SDValue Root, unsigned LabelID); + SDValue getBlockAddress(BlockAddress *BA, DebugLoc dl, + bool isTarget = false); SDValue getCopyToReg(SDValue Chain, DebugLoc dl, unsigned Reg, SDValue N) { return getNode(ISD::CopyToReg, dl, MVT::Other, Chain, diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index d9e9cf7e44b..f9608514c51 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -97,7 +97,7 @@ namespace ISD { BasicBlock, VALUETYPE, CONDCODE, Register, Constant, ConstantFP, GlobalAddress, GlobalTLSAddress, FrameIndex, - JumpTable, ConstantPool, ExternalSymbol, + JumpTable, ConstantPool, ExternalSymbol, BlockAddress, // The address of the GOT GLOBAL_OFFSET_TABLE, @@ -146,6 +146,7 @@ namespace ISD { TargetJumpTable, TargetConstantPool, TargetExternalSymbol, + TargetBlockAddress, /// RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) /// This node represents a target intrinsic function with no side effects. @@ -2026,11 +2027,27 @@ public: } }; +class BlockAddressSDNode : public SDNode { + BlockAddress *BA; + friend class SelectionDAG; + BlockAddressSDNode(unsigned NodeTy, DebugLoc dl, EVT VT, BlockAddress *ba) + : SDNode(NodeTy, dl, getSDVTList(VT)), BA(ba) { + } +public: + BlockAddress *getBlockAddress() const { return BA; } + + static bool classof(const BlockAddressSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::BlockAddress || + N->getOpcode() == ISD::TargetBlockAddress; + } +}; + class LabelSDNode : public SDNode { SDUse Chain; unsigned LabelID; friend class SelectionDAG; -LabelSDNode(unsigned NodeTy, DebugLoc dl, SDValue ch, unsigned id) + LabelSDNode(unsigned NodeTy, DebugLoc dl, SDValue ch, unsigned id) : SDNode(NodeTy, dl, getSDVTList(MVT::Other)), LabelID(id) { InitOperands(&Chain, ch); } diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 700c64c8ca5..8d910dd836a 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -269,6 +269,10 @@ def externalsym : SDNode<"ISD::ExternalSymbol", SDTPtrLeaf, [], "ExternalSymbolSDNode">; def texternalsym: SDNode<"ISD::TargetExternalSymbol", SDTPtrLeaf, [], "ExternalSymbolSDNode">; +def blockaddress : SDNode<"ISD::BlockAddress", SDTPtrLeaf, [], + "BlockAddressSDNode">; +def tblockaddress: SDNode<"ISD::TargetBlockAddress", SDTPtrLeaf, [], + "BlockAddressSDNode">; def add : SDNode<"ISD::ADD" , SDTIntBinOp , [SDNPCommutative, SDNPAssociative]>; diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 8bc5ef91cdf..257b963f9b4 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1613,6 +1613,22 @@ bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, return true; } +MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA) const { + return GetBlockAddressSymbol(BA->getFunction(), BA->getBasicBlock()); +} + +MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F, + const BasicBlock *BB) const { + assert(BB->hasName() && + "Address of anonymous basic block not supported yet!"); + + std::string Mangled = + Mang->getMangledName(F, Mang->makeNameProper(BB->getName()).c_str(), + /*ForcePrivate=*/true); + + return OutContext.GetOrCreateSymbol(StringRef(Mangled)); +} + MCSymbol *AsmPrinter::GetMBBSymbol(unsigned MBBID) const { SmallString<60> Name; raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "BB" @@ -1629,6 +1645,17 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { if (unsigned Align = MBB->getAlignment()) EmitAlignment(Log2_32(Align)); + if (MBB->hasAddressTaken()) { + GetBlockAddressSymbol(MBB->getBasicBlock()->getParent(), + MBB->getBasicBlock())->print(O, MAI); + O << ':'; + if (VerboseAsm) { + O.PadToColumn(MAI->getCommentColumn()); + O << MAI->getCommentString() << " Address Taken"; + } + O << '\n'; + } + if (MBB->pred_empty() || MBB->isOnlyReachableByFallthrough()) { if (VerboseAsm) O << MAI->getCommentString() << " BB#" << MBB->getNumber() << ':'; diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp index b3eb2da7628..46b169a7138 100644 --- a/lib/CodeGen/MachineBasicBlock.cpp +++ b/lib/CodeGen/MachineBasicBlock.cpp @@ -24,7 +24,8 @@ using namespace llvm; MachineBasicBlock::MachineBasicBlock(MachineFunction &mf, const BasicBlock *bb) - : BB(bb), Number(-1), xParent(&mf), Alignment(0), IsLandingPad(false) { + : BB(bb), Number(-1), xParent(&mf), Alignment(0), IsLandingPad(false), + AddressTaken(false) { Insts.Parent = this; } diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 1f85e922590..c27ecff72d2 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -13,6 +13,7 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/Constants.h" +#include "llvm/Function.h" #include "llvm/InlineAsm.h" #include "llvm/Value.h" #include "llvm/Assembly/Writer.h" @@ -180,6 +181,8 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const { case MachineOperand::MO_ExternalSymbol: return !strcmp(getSymbolName(), Other.getSymbolName()) && getOffset() == Other.getOffset(); + case MachineOperand::MO_BlockAddress: + return getBlockAddress() == Other.getBlockAddress(); } } @@ -273,6 +276,13 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const { if (getOffset()) OS << "+" << getOffset(); OS << '>'; break; + case MachineOperand::MO_BlockAddress: + OS << "getFunction(), /*PrintType=*/false); + OS << ", "; + WriteAsOperand(OS, getBlockAddress()->getBasicBlock(), /*PrintType=*/false); + OS << '>'; + break; default: llvm_unreachable("Unrecognized operand type"); } diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index 53bebbb44c1..e727bc9f33b 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -349,6 +349,8 @@ void InstrEmitter::AddOperand(MachineInstr *MI, SDValue Op, } else if (ExternalSymbolSDNode *ES = dyn_cast(Op)) { MI->addOperand(MachineOperand::CreateES(ES->getSymbol(), ES->getTargetFlags())); + } else if (BlockAddressSDNode *BA = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateBA(BA->getBlockAddress())); } else { assert(Op.getValueType() != MVT::Other && Op.getValueType() != MVT::Flag && diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h index c9c36f7e42e..ebb31ac4756 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h @@ -58,6 +58,7 @@ namespace llvm { if (isa(Node)) return true; if (isa(Node)) return true; if (isa(Node)) return true; + if (isa(Node)) return true; if (Node->getOpcode() == ISD::EntryToken) return true; return false; } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index a5345c8928d..0af0746017f 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -460,6 +460,11 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) { ID.AddInteger(SVN->getMaskElt(i)); break; } + case ISD::TargetBlockAddress: + case ISD::BlockAddress: { + ID.AddPointer(cast(N)); + break; + } } // end switch (N->getOpcode()) } @@ -1317,6 +1322,23 @@ SDValue SelectionDAG::getLabel(unsigned Opcode, DebugLoc dl, return SDValue(N, 0); } +SDValue SelectionDAG::getBlockAddress(BlockAddress *BA, DebugLoc DL, + bool isTarget) { + unsigned Opc = isTarget ? ISD::TargetBlockAddress : ISD::BlockAddress; + + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(TLI.getPointerTy()), 0, 0); + ID.AddPointer(BA); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate(); + new (N) BlockAddressSDNode(Opc, DL, TLI.getPointerTy(), BA); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + SDValue SelectionDAG::getSrcValue(const Value *V) { assert((!V || isa(V->getType())) && "SrcValue is not a pointer?"); @@ -5400,6 +5422,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::EH_RETURN: return "EH_RETURN"; case ISD::ConstantPool: return "ConstantPool"; case ISD::ExternalSymbol: return "ExternalSymbol"; + case ISD::BlockAddress: return "BlockAddress"; case ISD::INTRINSIC_WO_CHAIN: case ISD::INTRINSIC_VOID: case ISD::INTRINSIC_W_CHAIN: { @@ -5421,6 +5444,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::TargetJumpTable: return "TargetJumpTable"; case ISD::TargetConstantPool: return "TargetConstantPool"; case ISD::TargetExternalSymbol: return "TargetExternalSymbol"; + case ISD::TargetBlockAddress: return "TargetBlockAddress"; case ISD::CopyToReg: return "CopyToReg"; case ISD::CopyFromReg: return "CopyFromReg"; @@ -5778,6 +5802,13 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const { OS << ">"; } else if (const MemSDNode* M = dyn_cast(this)) { OS << "<" << *M->getMemOperand() << ">"; + } else if (const BlockAddressSDNode *BA = + dyn_cast(this)) { + OS << "<"; + WriteAsOperand(OS, BA->getBlockAddress()->getFunction(), false); + OS << ", "; + WriteAsOperand(OS, BA->getBlockAddress()->getBasicBlock(), false); + OS << ">"; } } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index dfe24ae4993..7243c33de12 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -322,6 +322,12 @@ void FunctionLoweringInfo::set(Function &fn, MachineFunction &mf, MBBMap[BB] = MBB; MF->push_back(MBB); + // Transfer the address-taken flag. This is necessary because there could + // be multiple MachineBasicBlocks corresponding to one BasicBlock, and only + // the first one should be marked. + if (BB->hasAddressTaken()) + MBB->setHasAddressTaken(); + // Create Machine PHI nodes for LLVM PHI nodes, lowering them as // appropriate. PHINode *PN; @@ -895,6 +901,9 @@ SDValue SelectionDAGLowering::getValue(const Value *V) { return DAG.getMergeValues(&Constants[0], NumElts, getCurDebugLoc()); } + if (BlockAddress *BA = dyn_cast(C)) + return DAG.getBlockAddress(BA, getCurDebugLoc()); + const VectorType *VecTy = cast(V->getType()); unsigned NumElements = VecTy->getNumElements(); @@ -5741,8 +5750,7 @@ void SelectionDAGLowering::CopyValueToVirtualRegister(Value *V, unsigned Reg) { #include "llvm/CodeGen/SelectionDAGISel.h" -void SelectionDAGISel:: -LowerArguments(BasicBlock *LLVMBB) { +void SelectionDAGISel::LowerArguments(BasicBlock *LLVMBB) { // If this is the entry block, emit arguments. Function &F = *LLVMBB->getParent(); SelectionDAG &DAG = SDL->DAG; diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index c12ae87769e..c3520c1c6c7 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -1933,6 +1933,7 @@ void DAGISelEmitter::EmitInstructionSelector(raw_ostream &OS) { << " case ISD::TargetConstantPool:\n" << " case ISD::TargetFrameIndex:\n" << " case ISD::TargetExternalSymbol:\n" + << " case ISD::TargetBlockAddress:\n" << " case ISD::TargetJumpTable:\n" << " case ISD::TargetGlobalTLSAddress:\n" << " case ISD::TargetGlobalAddress:\n" -- 2.34.1