diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 109ff74c1b6..0a4d9bd7da7 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -345,9 +345,11 @@ namespace llvm { /// GetBlockAddressSymbol - Return the MCSymbol used to satisfy BlockAddress /// uses of the specified basic block. - MCSymbol *GetBlockAddressSymbol(const BlockAddress *BA) const; + MCSymbol *GetBlockAddressSymbol(const BlockAddress *BA, + const char *Suffix = "") const; MCSymbol *GetBlockAddressSymbol(const Function *F, - const BasicBlock *BB) const; + const BasicBlock *BB, + const char *Suffix = "") const; /// EmitBasicBlockStart - This method prints the label for the specified /// MachineBasicBlock, an alignment (if present) and a comment describing diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index eede2cc50ce..8748afcba92 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -435,10 +435,12 @@ public: Op.setTargetFlags(TargetFlags); return Op; } - static MachineOperand CreateBA(BlockAddress *BA) { + static MachineOperand CreateBA(BlockAddress *BA, + unsigned char TargetFlags = 0) { MachineOperand Op(MachineOperand::MO_BlockAddress); Op.Contents.OffsetedInfo.Val.BA = BA; Op.setOffset(0); // Offset is always 0. + Op.setTargetFlags(TargetFlags); return Op; } diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 8400e86e7ea..bb1dc3fd17b 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -326,8 +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 getBlockAddress(BlockAddress *BA, EVT VT, + bool isTarget = false, unsigned char TargetFlags = 0); 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 d4d40b13e45..01942d7f06d 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -2029,12 +2029,16 @@ public: class BlockAddressSDNode : public SDNode { BlockAddress *BA; + unsigned char TargetFlags; friend class SelectionDAG; - BlockAddressSDNode(unsigned NodeTy, DebugLoc dl, EVT VT, BlockAddress *ba) - : SDNode(NodeTy, dl, getSDVTList(VT)), BA(ba) { + BlockAddressSDNode(unsigned NodeTy, EVT VT, BlockAddress *ba, + unsigned char Flags) + : SDNode(NodeTy, DebugLoc::getUnknownLoc(), getSDVTList(VT)), + BA(ba), TargetFlags(Flags) { } public: BlockAddress *getBlockAddress() const { return BA; } + unsigned char getTargetFlags() const { return TargetFlags; } static bool classof(const BlockAddressSDNode *) { return true; } static bool classof(const SDNode *N) { diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 08e0eae16c3..8eae7b23a02 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1630,12 +1630,14 @@ 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 BlockAddress *BA, + const char *Suffix) const { + return GetBlockAddressSymbol(BA->getFunction(), BA->getBasicBlock(), Suffix); } MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F, - const BasicBlock *BB) const { + const BasicBlock *BB, + const char *Suffix) const { assert(BB->hasName() && "Address of anonymous basic block not supported yet!"); @@ -1647,7 +1649,8 @@ MCSymbol *AsmPrinter::GetBlockAddressSymbol(const Function *F, SmallString<60> Name; raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "BA" << FuncName.size() << '_' << FuncName << '_' - << Mang->makeNameProper(BB->getName()); + << Mang->makeNameProper(BB->getName()) + << Suffix; return OutContext.GetOrCreateSymbol(Name.str()); } diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index 52b0832b061..669d414cefa 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -350,7 +350,8 @@ void InstrEmitter::AddOperand(MachineInstr *MI, SDValue Op, MI->addOperand(MachineOperand::CreateES(ES->getSymbol(), ES->getTargetFlags())); } else if (BlockAddressSDNode *BA = dyn_cast(Op)) { - MI->addOperand(MachineOperand::CreateBA(BA->getBlockAddress())); + MI->addOperand(MachineOperand::CreateBA(BA->getBlockAddress(), + BA->getTargetFlags())); } else { assert(Op.getValueType() != MVT::Other && Op.getValueType() != MVT::Flag && diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 4530ffc4a2d..f0837d2b10b 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -462,7 +462,8 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) { } case ISD::TargetBlockAddress: case ISD::BlockAddress: { - ID.AddPointer(cast(N)); + ID.AddPointer(cast(N)->getBlockAddress()); + ID.AddInteger(cast(N)->getTargetFlags()); break; } } // end switch (N->getOpcode()) @@ -1323,18 +1324,20 @@ SDValue SelectionDAG::getLabel(unsigned Opcode, DebugLoc dl, return SDValue(N, 0); } -SDValue SelectionDAG::getBlockAddress(BlockAddress *BA, DebugLoc DL, - bool isTarget) { +SDValue SelectionDAG::getBlockAddress(BlockAddress *BA, EVT VT, + bool isTarget, + unsigned char TargetFlags) { unsigned Opc = isTarget ? ISD::TargetBlockAddress : ISD::BlockAddress; FoldingSetNodeID ID; - AddNodeIDNode(ID, Opc, getVTList(TLI.getPointerTy()), 0, 0); + AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); ID.AddPointer(BA); + ID.AddInteger(TargetFlags); 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); + new (N) BlockAddressSDNode(Opc, VT, BA, TargetFlags); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); return SDValue(N, 0); @@ -5810,6 +5813,8 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const { OS << ", "; WriteAsOperand(OS, BA->getBlockAddress()->getBasicBlock(), false); OS << ">"; + if (unsigned int TF = BA->getTargetFlags()) + OS << " [TF=" << TF << ']'; } } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index 90fd95eb635..f953a74d9d2 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -884,7 +884,7 @@ SDValue SelectionDAGLowering::getValue(const Value *V) { } if (BlockAddress *BA = dyn_cast(C)) - return DAG.getBlockAddress(BA, getCurDebugLoc()); + return DAG.getBlockAddress(BA, VT); const VectorType *VecTy = cast(V->getType()); unsigned NumElements = VecTy->getNumElements(); diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 099fcb5e8a9..d24f483f9be 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1174,7 +1174,7 @@ SDValue PPCTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) { DebugLoc DL = Op.getDebugLoc(); BlockAddress *BA = cast(Op)->getBlockAddress(); - SDValue TgtBA = DAG.getBlockAddress(BA, DL, /*isTarget=*/true); + SDValue TgtBA = DAG.getBlockAddress(BA, PtrVT, /*isTarget=*/true); SDValue Zero = DAG.getConstant(0, PtrVT); SDValue Hi = DAG.getNode(PPCISD::Hi, DL, PtrVT, TgtBA, Zero); SDValue Lo = DAG.getNode(PPCISD::Lo, DL, PtrVT, TgtBA, Zero); diff --git a/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp b/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp index be9f4b265f6..49fbd460722 100644 --- a/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp +++ b/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp @@ -43,7 +43,6 @@ MCSymbol *X86MCInstLower::GetPICBaseSymbol() const { Twine(AsmPrinter.getFunctionNumber())+"$pb"); } - /// LowerGlobalAddressOperand - Lower an MO_GlobalAddress operand to an /// MCOperand. MCSymbol *X86MCInstLower:: @@ -231,6 +230,19 @@ GetConstantPoolIndexSymbol(const MachineOperand &MO) const { return Ctx.GetOrCreateSymbol(Name.str()); } +MCSymbol *X86MCInstLower:: +GetBlockAddressSymbol(const MachineOperand &MO) const { + const char *Suffix = ""; + switch (MO.getTargetFlags()) { + default: llvm_unreachable("Unknown target flag on BA operand"); + case X86II::MO_NO_FLAG: // No flag. + case X86II::MO_PIC_BASE_OFFSET: // Doesn't modify symbol name. + case X86II::MO_GOTOFF: Suffix = "@GOTOFF"; break; + } + + return AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress(), Suffix); +} + MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const { // FIXME: We would like an efficient form for this, so we don't have to do a @@ -331,8 +343,7 @@ void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO)); break; case MachineOperand::MO_BlockAddress: - MCOp = LowerSymbolOperand(MO, AsmPrinter.GetBlockAddressSymbol( - MO.getBlockAddress())); + MCOp = LowerSymbolOperand(MO, GetBlockAddressSymbol(MO)); break; } diff --git a/lib/Target/X86/AsmPrinter/X86MCInstLower.h b/lib/Target/X86/AsmPrinter/X86MCInstLower.h index fa25b906d54..94f8bfcc91a 100644 --- a/lib/Target/X86/AsmPrinter/X86MCInstLower.h +++ b/lib/Target/X86/AsmPrinter/X86MCInstLower.h @@ -43,6 +43,7 @@ public: MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const; MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const; MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const; + MCSymbol *GetBlockAddressSymbol(const MachineOperand &MO) const; MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const; private: diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 6a3577aaaf1..a9a78be3e31 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -252,8 +252,8 @@ namespace { else if (AM.JT != -1) Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags); else if (AM.BlockAddr) - Disp = CurDAG->getBlockAddress(AM.BlockAddr, DebugLoc()/*MVT::i32*/, - true /*AM.SymbolFlags*/); + Disp = CurDAG->getBlockAddress(AM.BlockAddr, MVT::i32, + true, AM.SymbolFlags); else Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i32); @@ -777,7 +777,7 @@ bool X86DAGToDAGISel::MatchWrapper(SDValue N, X86ISelAddressMode &AM) { AM.SymbolFlags = J->getTargetFlags(); } else { AM.BlockAddr = cast(N0)->getBlockAddress(); - //AM.SymbolFlags = cast(N0)->getTargetFlags(); + AM.SymbolFlags = cast(N0)->getTargetFlags(); } if (N.getOpcode() == X86ISD::WrapperRIP) @@ -808,7 +808,7 @@ bool X86DAGToDAGISel::MatchWrapper(SDValue N, X86ISelAddressMode &AM) { AM.SymbolFlags = J->getTargetFlags(); } else { AM.BlockAddr = cast(N0)->getBlockAddress(); - //AM.SymbolFlags = cast(N0)->getTargetFlags(); + AM.SymbolFlags = cast(N0)->getTargetFlags(); } return false; } diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 6018cf5ef7f..a149ca4e2e1 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -4722,18 +4722,27 @@ X86TargetLowering::LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) { SDValue X86TargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) { - unsigned WrapperKind = X86ISD::Wrapper; + // Create the TargetBlockAddressAddress node. + unsigned char OpFlags = + Subtarget->ClassifyBlockAddressReference(); CodeModel::Model M = getTargetMachine().getCodeModel(); + BlockAddress *BA = cast(Op)->getBlockAddress(); + DebugLoc dl = Op.getDebugLoc(); + SDValue Result = DAG.getBlockAddress(BA, getPointerTy(), + /*isTarget=*/true, OpFlags); + if (Subtarget->isPICStyleRIPRel() && (M == CodeModel::Small || M == CodeModel::Kernel)) - WrapperKind = X86ISD::WrapperRIP; + Result = DAG.getNode(X86ISD::WrapperRIP, dl, getPointerTy(), Result); + else + Result = DAG.getNode(X86ISD::Wrapper, dl, getPointerTy(), Result); - DebugLoc DL = Op.getDebugLoc(); - - BlockAddress *BA = cast(Op)->getBlockAddress(); - SDValue Result = DAG.getBlockAddress(BA, DL, /*isTarget=*/true); - - Result = DAG.getNode(WrapperKind, DL, getPointerTy(), Result); + // With PIC, the address is actually $g + Offset. + if (isGlobalRelativeToPICBase(OpFlags)) { + Result = DAG.getNode(ISD::ADD, dl, getPointerTy(), + DAG.getNode(X86ISD::GlobalBaseReg, dl, getPointerTy()), + Result); + } return Result; } diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index b901c1483b8..661f56046d0 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -28,6 +28,21 @@ using namespace llvm; #include #endif +/// ClassifyBlockAddressReference - Classify a blockaddress reference for the +/// current subtarget according to how we should reference it in a non-pcrel +/// context. +unsigned char X86Subtarget:: +ClassifyBlockAddressReference() const { + if (isPICStyleGOT()) // 32-bit ELF targets. + return X86II::MO_GOTOFF; + + if (isPICStyleStubPIC()) // Darwin/32 in PIC mode. + return X86II::MO_PIC_BASE_OFFSET; + + // Direct static reference to label. + return X86II::MO_NO_FLAG; +} + /// ClassifyGlobalReference - Classify a global variable reference for the /// current subtarget according to how we should reference it in a non-pcrel /// context. diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h index 23f2841a8c2..fb457ddd880 100644 --- a/lib/Target/X86/X86Subtarget.h +++ b/lib/Target/X86/X86Subtarget.h @@ -199,6 +199,11 @@ public: unsigned char ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM)const; + /// ClassifyBlockAddressReference - Classify a blockaddress reference for the + /// current subtarget according to how we should reference it in a non-pcrel + /// context. + unsigned char ClassifyBlockAddressReference() const; + /// IsLegalToCallImmediateAddr - Return true if the subtarget allows calls /// to immediate address. bool IsLegalToCallImmediateAddr(const TargetMachine &TM) const; diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index 00dcce653ee..8f4886cb3f0 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -295,7 +295,7 @@ LowerBlockAddress(SDValue Op, SelectionDAG &DAG) DebugLoc DL = Op.getDebugLoc(); BlockAddress *BA = cast(Op)->getBlockAddress(); - SDValue Result = DAG.getBlockAddress(BA, DL, /*isTarget=*/true); + SDValue Result = DAG.getBlockAddress(BA, getPointerTy(), /*isTarget=*/true); return DAG.getNode(XCoreISD::PCRelativeWrapper, DL, getPointerTy(), Result); }