Initial target-independent CodeGen support for BlockAddresses.

llvm-svn: 85556
This commit is contained in:
Dan Gohman 2009-10-30 01:27:03 +00:00
parent 430046321b
commit 6c9388011b
13 changed files with 128 additions and 5 deletions

View File

@ -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.

View File

@ -76,6 +76,10 @@ class MachineBasicBlock : public ilist_node<MachineBasicBlock> {
/// 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; }

View File

@ -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,

View File

@ -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);
}

View File

@ -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]>;

View File

@ -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() << ':';

View File

@ -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;
}

View File

@ -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 << "<blockaddress: ";
WriteAsOperand(OS, getBlockAddress()->getFunction(), /*PrintType=*/false);
OS << ", ";
WriteAsOperand(OS, getBlockAddress()->getBasicBlock(), /*PrintType=*/false);
OS << '>';
break;
default:
llvm_unreachable("Unrecognized operand type");
}

View File

@ -349,6 +349,8 @@ void InstrEmitter::AddOperand(MachineInstr *MI, SDValue Op,
} else if (ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) {
MI->addOperand(MachineOperand::CreateES(ES->getSymbol(),
ES->getTargetFlags()));
} else if (BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) {
MI->addOperand(MachineOperand::CreateBA(BA->getBlockAddress()));
} else {
assert(Op.getValueType() != MVT::Other &&
Op.getValueType() != MVT::Flag &&

View File

@ -58,6 +58,7 @@ namespace llvm {
if (isa<ConstantPoolSDNode>(Node)) return true;
if (isa<JumpTableSDNode>(Node)) return true;
if (isa<ExternalSymbolSDNode>(Node)) return true;
if (isa<BlockAddressSDNode>(Node)) return true;
if (Node->getOpcode() == ISD::EntryToken) return true;
return false;
}

View File

@ -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<BlockAddressSDNode>(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<BlockAddressSDNode>();
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<PointerType>(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<MemSDNode>(this)) {
OS << "<" << *M->getMemOperand() << ">";
} else if (const BlockAddressSDNode *BA =
dyn_cast<BlockAddressSDNode>(this)) {
OS << "<";
WriteAsOperand(OS, BA->getBlockAddress()->getFunction(), false);
OS << ", ";
WriteAsOperand(OS, BA->getBlockAddress()->getBasicBlock(), false);
OS << ">";
}
}

View File

@ -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<BlockAddress>(C))
return DAG.getBlockAddress(BA, getCurDebugLoc());
const VectorType *VecTy = cast<VectorType>(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;

View File

@ -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"