Let Darwin linker auto-synthesize stubs and lazy-pointers. This deletes a bunch of nasty code in ARM asm printer.
llvm-svn: 80404
This commit is contained in:
parent
90820ee62a
commit
43b9ca6f42
|
@ -417,16 +417,9 @@ void Emitter<CodeEmitter>::emitConstPoolInstruction(const MachineInstr &MI) {
|
||||||
|
|
||||||
GlobalValue *GV = ACPV->getGV();
|
GlobalValue *GV = ACPV->getGV();
|
||||||
if (GV) {
|
if (GV) {
|
||||||
assert(!ACPV->isStub() && "Don't know how to deal this yet!");
|
emitGlobalAddress(GV, ARM::reloc_arm_machine_cp_entry,
|
||||||
if (ACPV->isNonLazyPointer())
|
isa<Function>(GV), (intptr_t)ACPV);
|
||||||
MCE.addRelocation(MachineRelocation::getIndirectSymbol(
|
|
||||||
MCE.getCurrentPCOffset(), ARM::reloc_arm_machine_cp_entry, GV,
|
|
||||||
(intptr_t)ACPV, false));
|
|
||||||
else
|
|
||||||
emitGlobalAddress(GV, ARM::reloc_arm_machine_cp_entry,
|
|
||||||
ACPV->isStub() || isa<Function>(GV), (intptr_t)ACPV);
|
|
||||||
} else {
|
} else {
|
||||||
assert(!ACPV->isNonLazyPointer() && "Don't know how to deal this yet!");
|
|
||||||
emitExternalSymbolAddress(ACPV->getSymbol(), ARM::reloc_arm_absolute);
|
emitExternalSymbolAddress(ACPV->getSymbol(), ARM::reloc_arm_absolute);
|
||||||
}
|
}
|
||||||
emitWordLE(0);
|
emitWordLE(0);
|
||||||
|
|
|
@ -20,29 +20,25 @@
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, unsigned id,
|
ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, unsigned id,
|
||||||
ARMCP::ARMCPKind k,
|
|
||||||
unsigned char PCAdj,
|
unsigned char PCAdj,
|
||||||
const char *Modif,
|
const char *Modif,
|
||||||
bool AddCA)
|
bool AddCA)
|
||||||
: MachineConstantPoolValue((const Type*)gv->getType()),
|
: MachineConstantPoolValue((const Type*)gv->getType()),
|
||||||
GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj),
|
GV(gv), S(NULL), LabelId(id), PCAdjust(PCAdj),
|
||||||
Modifier(Modif), AddCurrentAddress(AddCA) {}
|
Modifier(Modif), AddCurrentAddress(AddCA) {}
|
||||||
|
|
||||||
ARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C,
|
ARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C,
|
||||||
const char *s, unsigned id,
|
const char *s, unsigned id,
|
||||||
ARMCP::ARMCPKind k,
|
|
||||||
unsigned char PCAdj,
|
unsigned char PCAdj,
|
||||||
const char *Modif,
|
const char *Modif,
|
||||||
bool AddCA)
|
bool AddCA)
|
||||||
: MachineConstantPoolValue((const Type*)Type::getInt32Ty(C)),
|
: MachineConstantPoolValue((const Type*)Type::getInt32Ty(C)),
|
||||||
GV(NULL), S(strdup(s)), LabelId(id), Kind(k), PCAdjust(PCAdj),
|
GV(NULL), S(strdup(s)), LabelId(id), PCAdjust(PCAdj),
|
||||||
Modifier(Modif), AddCurrentAddress(AddCA) {}
|
Modifier(Modif), AddCurrentAddress(AddCA) {}
|
||||||
|
|
||||||
ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv,
|
ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, const char *Modif)
|
||||||
ARMCP::ARMCPKind k,
|
|
||||||
const char *Modif)
|
|
||||||
: MachineConstantPoolValue((const Type*)Type::getInt32Ty(gv->getContext())),
|
: MachineConstantPoolValue((const Type*)Type::getInt32Ty(gv->getContext())),
|
||||||
GV(gv), S(NULL), LabelId(0), Kind(k), PCAdjust(0),
|
GV(gv), S(NULL), LabelId(0), PCAdjust(0),
|
||||||
Modifier(Modif) {}
|
Modifier(Modif) {}
|
||||||
|
|
||||||
int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
|
int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
|
||||||
|
@ -57,7 +53,6 @@ int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
|
||||||
if (CPV->GV == GV &&
|
if (CPV->GV == GV &&
|
||||||
CPV->S == S &&
|
CPV->S == S &&
|
||||||
CPV->LabelId == LabelId &&
|
CPV->LabelId == LabelId &&
|
||||||
CPV->Kind == Kind &&
|
|
||||||
CPV->PCAdjust == PCAdjust)
|
CPV->PCAdjust == PCAdjust)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +70,6 @@ ARMConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) {
|
||||||
ID.AddPointer(GV);
|
ID.AddPointer(GV);
|
||||||
ID.AddPointer(S);
|
ID.AddPointer(S);
|
||||||
ID.AddInteger(LabelId);
|
ID.AddInteger(LabelId);
|
||||||
ID.AddInteger((unsigned)Kind);
|
|
||||||
ID.AddInteger(PCAdjust);
|
ID.AddInteger(PCAdjust);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,8 +83,6 @@ void ARMConstantPoolValue::print(raw_ostream &O) const {
|
||||||
O << GV->getName();
|
O << GV->getName();
|
||||||
else
|
else
|
||||||
O << S;
|
O << S;
|
||||||
if (isNonLazyPointer()) O << "$non_lazy_ptr";
|
|
||||||
else if (isStub()) O << "$stub";
|
|
||||||
if (Modifier) O << "(" << Modifier << ")";
|
if (Modifier) O << "(" << Modifier << ")";
|
||||||
if (PCAdjust != 0) {
|
if (PCAdjust != 0) {
|
||||||
O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust;
|
O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust;
|
||||||
|
|
|
@ -21,14 +21,6 @@ namespace llvm {
|
||||||
class GlobalValue;
|
class GlobalValue;
|
||||||
class LLVMContext;
|
class LLVMContext;
|
||||||
|
|
||||||
namespace ARMCP {
|
|
||||||
enum ARMCPKind {
|
|
||||||
CPValue,
|
|
||||||
CPNonLazyPtr,
|
|
||||||
CPStub
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ARMConstantPoolValue - ARM specific constantpool value. This is used to
|
/// ARMConstantPoolValue - ARM specific constantpool value. This is used to
|
||||||
/// represent PC relative displacement between the address of the load
|
/// represent PC relative displacement between the address of the load
|
||||||
/// instruction and the global value being loaded, i.e. (&GV-(LPIC+8)).
|
/// instruction and the global value being loaded, i.e. (&GV-(LPIC+8)).
|
||||||
|
@ -36,7 +28,6 @@ class ARMConstantPoolValue : public MachineConstantPoolValue {
|
||||||
GlobalValue *GV; // GlobalValue being loaded.
|
GlobalValue *GV; // GlobalValue being loaded.
|
||||||
const char *S; // ExtSymbol being loaded.
|
const char *S; // ExtSymbol being loaded.
|
||||||
unsigned LabelId; // Label id of the load.
|
unsigned LabelId; // Label id of the load.
|
||||||
ARMCP::ARMCPKind Kind; // non_lazy_ptr or stub?
|
|
||||||
unsigned char PCAdjust; // Extra adjustment if constantpool is pc relative.
|
unsigned char PCAdjust; // Extra adjustment if constantpool is pc relative.
|
||||||
// 8 for ARM, 4 for Thumb.
|
// 8 for ARM, 4 for Thumb.
|
||||||
const char *Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8))
|
const char *Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8))
|
||||||
|
@ -44,15 +35,12 @@ class ARMConstantPoolValue : public MachineConstantPoolValue {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ARMConstantPoolValue(GlobalValue *gv, unsigned id,
|
ARMConstantPoolValue(GlobalValue *gv, unsigned id,
|
||||||
ARMCP::ARMCPKind Kind = ARMCP::CPValue,
|
|
||||||
unsigned char PCAdj = 0, const char *Modifier = NULL,
|
unsigned char PCAdj = 0, const char *Modifier = NULL,
|
||||||
bool AddCurrentAddress = false);
|
bool AddCurrentAddress = false);
|
||||||
ARMConstantPoolValue(LLVMContext &C, const char *s, unsigned id,
|
ARMConstantPoolValue(LLVMContext &C, const char *s, unsigned id,
|
||||||
ARMCP::ARMCPKind Kind = ARMCP::CPValue,
|
|
||||||
unsigned char PCAdj = 0, const char *Modifier = NULL,
|
unsigned char PCAdj = 0, const char *Modifier = NULL,
|
||||||
bool AddCurrentAddress = false);
|
bool AddCurrentAddress = false);
|
||||||
ARMConstantPoolValue(GlobalValue *GV, ARMCP::ARMCPKind Kind,
|
ARMConstantPoolValue(GlobalValue *GV, const char *Modifier);
|
||||||
const char *Modifier);
|
|
||||||
ARMConstantPoolValue();
|
ARMConstantPoolValue();
|
||||||
~ARMConstantPoolValue();
|
~ARMConstantPoolValue();
|
||||||
|
|
||||||
|
@ -63,8 +51,6 @@ public:
|
||||||
bool hasModifier() const { return Modifier != NULL; }
|
bool hasModifier() const { return Modifier != NULL; }
|
||||||
bool mustAddCurrentAddress() const { return AddCurrentAddress; }
|
bool mustAddCurrentAddress() const { return AddCurrentAddress; }
|
||||||
unsigned getLabelId() const { return LabelId; }
|
unsigned getLabelId() const { return LabelId; }
|
||||||
bool isNonLazyPointer() const { return Kind == ARMCP::CPNonLazyPtr; }
|
|
||||||
bool isStub() const { return Kind == ARMCP::CPStub; }
|
|
||||||
unsigned char getPCAdjustment() const { return PCAdjust; }
|
unsigned char getPCAdjustment() const { return PCAdjust; }
|
||||||
|
|
||||||
virtual unsigned getRelocationInfo() const {
|
virtual unsigned getRelocationInfo() const {
|
||||||
|
|
|
@ -968,8 +968,8 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
|
||||||
isLocalARMFunc = !Subtarget->isThumb() && !isExt;
|
isLocalARMFunc = !Subtarget->isThumb() && !isExt;
|
||||||
// tBX takes a register source operand.
|
// tBX takes a register source operand.
|
||||||
if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
|
if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
|
||||||
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, ARMPCLabelIndex,
|
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV,
|
||||||
ARMCP::CPStub, 4);
|
ARMPCLabelIndex, 4);
|
||||||
SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4);
|
SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4);
|
||||||
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
|
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
|
||||||
Callee = DAG.getLoad(getPointerTy(), dl,
|
Callee = DAG.getLoad(getPointerTy(), dl,
|
||||||
|
@ -988,8 +988,7 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
|
||||||
const char *Sym = S->getSymbol();
|
const char *Sym = S->getSymbol();
|
||||||
if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
|
if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
|
||||||
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(),
|
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(),
|
||||||
Sym, ARMPCLabelIndex,
|
Sym, ARMPCLabelIndex, 4);
|
||||||
ARMCP::CPStub, 4);
|
|
||||||
SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4);
|
SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4);
|
||||||
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
|
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
|
||||||
Callee = DAG.getLoad(getPointerTy(), dl,
|
Callee = DAG.getLoad(getPointerTy(), dl,
|
||||||
|
@ -1166,7 +1165,7 @@ ARMTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA,
|
||||||
EVT PtrVT = getPointerTy();
|
EVT PtrVT = getPointerTy();
|
||||||
unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
|
unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
|
||||||
ARMConstantPoolValue *CPV =
|
ARMConstantPoolValue *CPV =
|
||||||
new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex, ARMCP::CPValue,
|
new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex,
|
||||||
PCAdj, "tlsgd", true);
|
PCAdj, "tlsgd", true);
|
||||||
SDValue Argument = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
SDValue Argument = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
||||||
Argument = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Argument);
|
Argument = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Argument);
|
||||||
|
@ -1208,7 +1207,7 @@ ARMTargetLowering::LowerToTLSExecModels(GlobalAddressSDNode *GA,
|
||||||
// initial exec model
|
// initial exec model
|
||||||
unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
|
unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
|
||||||
ARMConstantPoolValue *CPV =
|
ARMConstantPoolValue *CPV =
|
||||||
new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex, ARMCP::CPValue,
|
new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex,
|
||||||
PCAdj, "gottpoff", true);
|
PCAdj, "gottpoff", true);
|
||||||
Offset = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
Offset = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
||||||
Offset = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Offset);
|
Offset = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Offset);
|
||||||
|
@ -1221,8 +1220,7 @@ ARMTargetLowering::LowerToTLSExecModels(GlobalAddressSDNode *GA,
|
||||||
Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, NULL, 0);
|
Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
// local exec model
|
// local exec model
|
||||||
ARMConstantPoolValue *CPV =
|
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, "tpoff");
|
||||||
new ARMConstantPoolValue(GV, ARMCP::CPValue, "tpoff");
|
|
||||||
Offset = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
Offset = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
||||||
Offset = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Offset);
|
Offset = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Offset);
|
||||||
Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, NULL, 0);
|
Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, NULL, 0);
|
||||||
|
@ -1256,7 +1254,7 @@ SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op,
|
||||||
if (RelocM == Reloc::PIC_) {
|
if (RelocM == Reloc::PIC_) {
|
||||||
bool UseGOTOFF = GV->hasLocalLinkage() || GV->hasHiddenVisibility();
|
bool UseGOTOFF = GV->hasLocalLinkage() || GV->hasHiddenVisibility();
|
||||||
ARMConstantPoolValue *CPV =
|
ARMConstantPoolValue *CPV =
|
||||||
new ARMConstantPoolValue(GV, ARMCP::CPValue, UseGOTOFF ? "GOTOFF":"GOT");
|
new ARMConstantPoolValue(GV, UseGOTOFF ? "GOTOFF" : "GOT");
|
||||||
SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
||||||
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
|
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
|
||||||
SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(),
|
SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(),
|
||||||
|
@ -1274,34 +1272,19 @@ SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol
|
|
||||||
/// even in non-static mode.
|
|
||||||
static bool GVIsIndirectSymbol(GlobalValue *GV, Reloc::Model RelocM) {
|
|
||||||
// If symbol visibility is hidden, the extra load is not needed if
|
|
||||||
// the symbol is definitely defined in the current translation unit.
|
|
||||||
bool isDecl = GV->isDeclaration() || GV->hasAvailableExternallyLinkage();
|
|
||||||
if (GV->hasHiddenVisibility() && (!isDecl && !GV->hasCommonLinkage()))
|
|
||||||
return false;
|
|
||||||
return RelocM != Reloc::Static && (isDecl || GV->isWeakForLinker());
|
|
||||||
}
|
|
||||||
|
|
||||||
SDValue ARMTargetLowering::LowerGlobalAddressDarwin(SDValue Op,
|
SDValue ARMTargetLowering::LowerGlobalAddressDarwin(SDValue Op,
|
||||||
SelectionDAG &DAG) {
|
SelectionDAG &DAG) {
|
||||||
EVT PtrVT = getPointerTy();
|
EVT PtrVT = getPointerTy();
|
||||||
DebugLoc dl = Op.getDebugLoc();
|
DebugLoc dl = Op.getDebugLoc();
|
||||||
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
||||||
Reloc::Model RelocM = getTargetMachine().getRelocationModel();
|
Reloc::Model RelocM = getTargetMachine().getRelocationModel();
|
||||||
bool IsIndirect = GVIsIndirectSymbol(GV, RelocM);
|
|
||||||
SDValue CPAddr;
|
SDValue CPAddr;
|
||||||
if (RelocM == Reloc::Static)
|
if (RelocM == Reloc::Static)
|
||||||
CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 4);
|
CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 4);
|
||||||
else {
|
else {
|
||||||
unsigned PCAdj = (RelocM != Reloc::PIC_)
|
unsigned PCAdj = (RelocM != Reloc::PIC_) ? 0 : (Subtarget->isThumb()?4:8);
|
||||||
? 0 : (Subtarget->isThumb() ? 4 : 8);
|
ARMConstantPoolValue *CPV =
|
||||||
ARMCP::ARMCPKind Kind = IsIndirect ? ARMCP::CPNonLazyPtr
|
new ARMConstantPoolValue(GV, ARMPCLabelIndex, PCAdj);
|
||||||
: ARMCP::CPValue;
|
|
||||||
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, ARMPCLabelIndex,
|
|
||||||
Kind, PCAdj);
|
|
||||||
CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
||||||
}
|
}
|
||||||
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
|
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
|
||||||
|
@ -1313,7 +1296,8 @@ SDValue ARMTargetLowering::LowerGlobalAddressDarwin(SDValue Op,
|
||||||
SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex++, MVT::i32);
|
SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex++, MVT::i32);
|
||||||
Result = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
|
Result = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
|
||||||
}
|
}
|
||||||
if (IsIndirect)
|
|
||||||
|
if (Subtarget->GVIsIndirectSymbol(GV, RelocM == Reloc::Static))
|
||||||
Result = DAG.getLoad(PtrVT, dl, Chain, Result, NULL, 0);
|
Result = DAG.getLoad(PtrVT, dl, Chain, Result, NULL, 0);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
|
@ -1328,8 +1312,7 @@ SDValue ARMTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDValue Op,
|
||||||
unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
|
unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
|
||||||
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(),
|
ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(),
|
||||||
"_GLOBAL_OFFSET_TABLE_",
|
"_GLOBAL_OFFSET_TABLE_",
|
||||||
ARMPCLabelIndex,
|
ARMPCLabelIndex, PCAdj);
|
||||||
ARMCP::CPValue, PCAdj);
|
|
||||||
SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
||||||
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
|
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
|
||||||
SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, NULL, 0);
|
SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, NULL, 0);
|
||||||
|
@ -1403,14 +1386,13 @@ ARMTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) {
|
||||||
SDValue CPAddr;
|
SDValue CPAddr;
|
||||||
unsigned PCAdj = (RelocM != Reloc::PIC_)
|
unsigned PCAdj = (RelocM != Reloc::PIC_)
|
||||||
? 0 : (Subtarget->isThumb() ? 4 : 8);
|
? 0 : (Subtarget->isThumb() ? 4 : 8);
|
||||||
ARMCP::ARMCPKind Kind = ARMCP::CPValue;
|
|
||||||
// Save off the LSDA name for the AsmPrinter to use when it's time
|
// Save off the LSDA name for the AsmPrinter to use when it's time
|
||||||
// to emit the table
|
// to emit the table
|
||||||
std::string LSDAName = "L_lsda_";
|
std::string LSDAName = "L_lsda_";
|
||||||
LSDAName += MF.getFunction()->getName();
|
LSDAName += MF.getFunction()->getName();
|
||||||
ARMConstantPoolValue *CPV =
|
ARMConstantPoolValue *CPV =
|
||||||
new ARMConstantPoolValue(*DAG.getContext(), LSDAName.c_str(),
|
new ARMConstantPoolValue(*DAG.getContext(), LSDAName.c_str(),
|
||||||
ARMPCLabelIndex, Kind, PCAdj);
|
ARMPCLabelIndex, PCAdj);
|
||||||
CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
|
||||||
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
|
CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
|
||||||
SDValue Result =
|
SDValue Result =
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "ARMSubtarget.h"
|
#include "ARMSubtarget.h"
|
||||||
#include "ARMGenSubtarget.inc"
|
#include "ARMGenSubtarget.inc"
|
||||||
|
#include "llvm/GlobalValue.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/Target/TargetOptions.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
@ -92,3 +93,13 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS,
|
||||||
if (isTargetDarwin())
|
if (isTargetDarwin())
|
||||||
IsR9Reserved = ReserveR9 | (ARMArchVersion < V6);
|
IsR9Reserved = ReserveR9 | (ARMArchVersion < V6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol.
|
||||||
|
bool ARMSubtarget::GVIsIndirectSymbol(GlobalValue *GV, bool isStatic) const {
|
||||||
|
// If symbol visibility is hidden, the extra load is not needed if
|
||||||
|
// the symbol is definitely defined in the current translation unit.
|
||||||
|
bool isDecl = GV->isDeclaration() || GV->hasAvailableExternallyLinkage();
|
||||||
|
if (GV->hasHiddenVisibility() && (!isDecl && !GV->hasCommonLinkage()))
|
||||||
|
return false;
|
||||||
|
return !isStatic && (isDecl || GV->isWeakForLinker());
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
class GlobalValue;
|
||||||
|
|
||||||
class ARMSubtarget : public TargetSubtarget {
|
class ARMSubtarget : public TargetSubtarget {
|
||||||
protected:
|
protected:
|
||||||
|
@ -129,6 +130,10 @@ protected:
|
||||||
/// stack frame on entry to the function and which must be maintained by every
|
/// stack frame on entry to the function and which must be maintained by every
|
||||||
/// function for this subtarget.
|
/// function for this subtarget.
|
||||||
unsigned getStackAlignment() const { return stackAlignment; }
|
unsigned getStackAlignment() const { return stackAlignment; }
|
||||||
|
|
||||||
|
/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect
|
||||||
|
/// symbol.
|
||||||
|
bool GVIsIndirectSymbol(GlobalValue *GV, bool isStatic) const;
|
||||||
};
|
};
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
|
||||||
|
|
|
@ -79,34 +79,6 @@ namespace {
|
||||||
/// visibility that require non-lazy-pointers for indirect access.
|
/// visibility that require non-lazy-pointers for indirect access.
|
||||||
StringMap<std::string> HiddenGVNonLazyPtrs;
|
StringMap<std::string> HiddenGVNonLazyPtrs;
|
||||||
|
|
||||||
struct FnStubInfo {
|
|
||||||
std::string Stub, LazyPtr, SLP, SCV;
|
|
||||||
|
|
||||||
FnStubInfo() {}
|
|
||||||
|
|
||||||
void Init(const GlobalValue *GV, Mangler *Mang) {
|
|
||||||
// Already initialized.
|
|
||||||
if (!Stub.empty()) return;
|
|
||||||
Stub = Mang->getMangledName(GV, "$stub", true);
|
|
||||||
LazyPtr = Mang->getMangledName(GV, "$lazy_ptr", true);
|
|
||||||
SLP = Mang->getMangledName(GV, "$slp", true);
|
|
||||||
SCV = Mang->getMangledName(GV, "$scv", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Init(const std::string &GV, Mangler *Mang) {
|
|
||||||
// Already initialized.
|
|
||||||
if (!Stub.empty()) return;
|
|
||||||
Stub = Mang->makeNameProper(GV + "$stub", Mangler::Private);
|
|
||||||
LazyPtr = Mang->makeNameProper(GV + "$lazy_ptr", Mangler::Private);
|
|
||||||
SLP = Mang->makeNameProper(GV + "$slp", Mangler::Private);
|
|
||||||
SCV = Mang->makeNameProper(GV + "$scv", Mangler::Private);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// FnStubs - Keeps the set of external function GlobalAddresses that the
|
|
||||||
/// asm printer should generate stubs for.
|
|
||||||
StringMap<FnStubInfo> FnStubs;
|
|
||||||
|
|
||||||
/// True if asm printer is printing a series of CONSTPOOL_ENTRY.
|
/// True if asm printer is printing a series of CONSTPOOL_ENTRY.
|
||||||
bool InCPMode;
|
bool InCPMode;
|
||||||
public:
|
public:
|
||||||
|
@ -188,36 +160,26 @@ namespace {
|
||||||
GlobalValue *GV = ACPV->getGV();
|
GlobalValue *GV = ACPV->getGV();
|
||||||
std::string Name;
|
std::string Name;
|
||||||
|
|
||||||
|
if (GV) {
|
||||||
if (ACPV->isNonLazyPointer()) {
|
bool isIndirect = Subtarget->isTargetDarwin() &&
|
||||||
std::string SymName = Mang->getMangledName(GV);
|
Subtarget->GVIsIndirectSymbol(GV,
|
||||||
Name = Mang->getMangledName(GV, "$non_lazy_ptr", true);
|
TM.getRelocationModel() == Reloc::Static);
|
||||||
|
if (!isIndirect)
|
||||||
if (GV->hasHiddenVisibility())
|
|
||||||
HiddenGVNonLazyPtrs[SymName] = Name;
|
|
||||||
else
|
|
||||||
GVNonLazyPtrs[SymName] = Name;
|
|
||||||
} else if (ACPV->isStub()) {
|
|
||||||
if (GV) {
|
|
||||||
FnStubInfo &FnInfo = FnStubs[Mang->getMangledName(GV)];
|
|
||||||
FnInfo.Init(GV, Mang);
|
|
||||||
Name = FnInfo.Stub;
|
|
||||||
} else {
|
|
||||||
FnStubInfo &FnInfo = FnStubs[Mang->makeNameProper(ACPV->getSymbol())];
|
|
||||||
FnInfo.Init(ACPV->getSymbol(), Mang);
|
|
||||||
Name = FnInfo.Stub;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (GV)
|
|
||||||
Name = Mang->getMangledName(GV);
|
Name = Mang->getMangledName(GV);
|
||||||
else if (!strncmp(ACPV->getSymbol(), "L_lsda_", 7))
|
else {
|
||||||
Name = ACPV->getSymbol();
|
// FIXME: Remove this when Darwin transition to @GOT like syntax.
|
||||||
else
|
std::string SymName = Mang->getMangledName(GV);
|
||||||
Name = Mang->makeNameProper(ACPV->getSymbol());
|
Name = Mang->getMangledName(GV, "$non_lazy_ptr", true);
|
||||||
}
|
if (GV->hasHiddenVisibility())
|
||||||
O << Name;
|
HiddenGVNonLazyPtrs[SymName] = Name;
|
||||||
|
else
|
||||||
|
GVNonLazyPtrs[SymName] = Name;
|
||||||
|
}
|
||||||
|
} else if (!strncmp(ACPV->getSymbol(), "L_lsda_", 7))
|
||||||
|
Name = ACPV->getSymbol();
|
||||||
|
else
|
||||||
|
Name = Mang->makeNameProper(ACPV->getSymbol());
|
||||||
|
O << Name;
|
||||||
|
|
||||||
if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
|
if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
|
||||||
if (ACPV->getPCAdjustment() != 0) {
|
if (ACPV->getPCAdjustment() != 0) {
|
||||||
|
@ -372,18 +334,7 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
|
||||||
case MachineOperand::MO_GlobalAddress: {
|
case MachineOperand::MO_GlobalAddress: {
|
||||||
bool isCallOp = Modifier && !strcmp(Modifier, "call");
|
bool isCallOp = Modifier && !strcmp(Modifier, "call");
|
||||||
GlobalValue *GV = MO.getGlobal();
|
GlobalValue *GV = MO.getGlobal();
|
||||||
std::string Name;
|
O << Mang->getMangledName(GV);
|
||||||
bool isExt = GV->isDeclaration() || GV->isWeakForLinker();
|
|
||||||
if (isExt && isCallOp && Subtarget->isTargetDarwin() &&
|
|
||||||
TM.getRelocationModel() != Reloc::Static) {
|
|
||||||
FnStubInfo &FnInfo = FnStubs[Mang->getMangledName(GV)];
|
|
||||||
FnInfo.Init(GV, Mang);
|
|
||||||
Name = FnInfo.Stub;
|
|
||||||
} else {
|
|
||||||
Name = Mang->getMangledName(GV);
|
|
||||||
}
|
|
||||||
|
|
||||||
O << Name;
|
|
||||||
|
|
||||||
printOffset(MO.getOffset());
|
printOffset(MO.getOffset());
|
||||||
|
|
||||||
|
@ -394,14 +345,7 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
|
||||||
}
|
}
|
||||||
case MachineOperand::MO_ExternalSymbol: {
|
case MachineOperand::MO_ExternalSymbol: {
|
||||||
bool isCallOp = Modifier && !strcmp(Modifier, "call");
|
bool isCallOp = Modifier && !strcmp(Modifier, "call");
|
||||||
std::string Name;
|
std::string Name = Mang->makeNameProper(MO.getSymbolName());
|
||||||
if (isCallOp && Subtarget->isTargetDarwin() &&
|
|
||||||
TM.getRelocationModel() != Reloc::Static) {
|
|
||||||
FnStubInfo &FnInfo = FnStubs[Mang->makeNameProper(MO.getSymbolName())];
|
|
||||||
FnInfo.Init(MO.getSymbolName(), Mang);
|
|
||||||
Name = FnInfo.Stub;
|
|
||||||
} else
|
|
||||||
Name = Mang->makeNameProper(MO.getSymbolName());
|
|
||||||
|
|
||||||
O << Name;
|
O << Name;
|
||||||
if (isCallOp && Subtarget->isTargetELF() &&
|
if (isCallOp && Subtarget->isTargetELF() &&
|
||||||
|
@ -1277,55 +1221,7 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
|
||||||
static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering());
|
static_cast<TargetLoweringObjectFileMachO &>(getObjFileLowering());
|
||||||
|
|
||||||
O << '\n';
|
O << '\n';
|
||||||
|
|
||||||
if (!FnStubs.empty()) {
|
|
||||||
unsigned StubSize = 12;
|
|
||||||
const char *StubSectionName = "__symbol_stub4";
|
|
||||||
|
|
||||||
if (TM.getRelocationModel() == Reloc::PIC_) {
|
|
||||||
StubSize = 16;
|
|
||||||
StubSectionName = "__picsymbolstub4";
|
|
||||||
}
|
|
||||||
|
|
||||||
const MCSection *StubSection
|
|
||||||
= TLOFMacho.getMachOSection("__TEXT", StubSectionName,
|
|
||||||
MCSectionMachO::S_SYMBOL_STUBS,
|
|
||||||
StubSize, SectionKind::getText());
|
|
||||||
|
|
||||||
const MCSection *LazySymbolPointerSection
|
|
||||||
= TLOFMacho.getLazySymbolPointerSection();
|
|
||||||
|
|
||||||
// Output stubs for dynamically-linked functions
|
|
||||||
for (StringMap<FnStubInfo>::iterator I = FnStubs.begin(),
|
|
||||||
E = FnStubs.end(); I != E; ++I) {
|
|
||||||
const FnStubInfo &Info = I->second;
|
|
||||||
|
|
||||||
OutStreamer.SwitchSection(StubSection);
|
|
||||||
EmitAlignment(2);
|
|
||||||
O << "\t.code\t32\n";
|
|
||||||
|
|
||||||
O << Info.Stub << ":\n";
|
|
||||||
O << "\t.indirect_symbol " << I->getKeyData() << '\n';
|
|
||||||
O << "\tldr ip, " << Info.SLP << '\n';
|
|
||||||
if (TM.getRelocationModel() == Reloc::PIC_) {
|
|
||||||
O << Info.SCV << ":\n";
|
|
||||||
O << "\tadd ip, pc, ip\n";
|
|
||||||
}
|
|
||||||
O << "\tldr pc, [ip, #0]\n";
|
|
||||||
O << Info.SLP << ":\n";
|
|
||||||
O << "\t.long\t" << Info.LazyPtr;
|
|
||||||
if (TM.getRelocationModel() == Reloc::PIC_)
|
|
||||||
O << "-(" << Info.SCV << "+8)";
|
|
||||||
O << '\n';
|
|
||||||
|
|
||||||
OutStreamer.SwitchSection(LazySymbolPointerSection);
|
|
||||||
O << Info.LazyPtr << ":\n";
|
|
||||||
O << "\t.indirect_symbol " << I->getKeyData() << "\n";
|
|
||||||
O << "\t.long\tdyld_stub_binding_helper\n";
|
|
||||||
}
|
|
||||||
O << '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output non-lazy-pointers for external and common global variables.
|
// Output non-lazy-pointers for external and common global variables.
|
||||||
if (!GVNonLazyPtrs.empty()) {
|
if (!GVNonLazyPtrs.empty()) {
|
||||||
// Switch with ".non_lazy_symbol_pointer" directive.
|
// Switch with ".non_lazy_symbol_pointer" directive.
|
||||||
|
@ -1349,7 +1245,6 @@ bool ARMAsmPrinter::doFinalization(Module &M) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Funny Darwin hack: This flag tells the linker that no global symbols
|
// Funny Darwin hack: This flag tells the linker that no global symbols
|
||||||
// contain code that falls through to other global symbols (e.g. the obvious
|
// contain code that falls through to other global symbols (e.g. the obvious
|
||||||
// implementation of multiple entry points). If this doesn't occur, the
|
// implementation of multiple entry points). If this doesn't occur, the
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
; RUN: llvm-as < %s | llc -relocation-model=static | FileCheck %s -check-prefix=STATIC
|
|
||||||
; RUN: llvm-as < %s | llc -relocation-model=pic | FileCheck %s -check-prefix=PIC
|
|
||||||
; RUN: llvm-as < %s | llc -relocation-model=dynamic-no-pic | FileCheck %s -check-prefix=DYNAMIC
|
|
||||||
; PR4482
|
|
||||||
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
|
||||||
target triple = "armv6-apple-darwin2"
|
|
||||||
|
|
||||||
define i32 @foo(i64 %x) nounwind {
|
|
||||||
entry:
|
|
||||||
; STATIC: _foo:
|
|
||||||
; STATIC: bl _exact_log2
|
|
||||||
; STATIC: ldmfd sp!, {r7, pc}
|
|
||||||
; STATIC: .subsections_via_symbols
|
|
||||||
|
|
||||||
; PIC: _foo:
|
|
||||||
; PIC: bl L_exact_log2$stub
|
|
||||||
; PIC: ldmfd sp!, {r7, pc}
|
|
||||||
|
|
||||||
; DYNAMIC: _foo:
|
|
||||||
; DYNAMIC: bl L_exact_log2$stub
|
|
||||||
; DYNAMIC: ldmfd sp!, {r7, pc}
|
|
||||||
|
|
||||||
%A = call i32 @exact_log2(i64 %x)
|
|
||||||
ret i32 %A
|
|
||||||
}
|
|
||||||
|
|
||||||
define available_externally i32 @exact_log2(i64 %x) nounwind {
|
|
||||||
ret i32 4
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
; PIC: .section __TEXT,__picsymbolstub4,symbol_stubs,none,16
|
|
||||||
; PIC: L_exact_log2$stub:
|
|
||||||
; PIC: .indirect_symbol _exact_log2
|
|
||||||
; PIC: ldr ip, L_exact_log2$slp
|
|
||||||
; PIC: L_exact_log2$scv:
|
|
||||||
; PIC: add ip, pc, ip
|
|
||||||
; PIC: ldr pc, [ip, #0]
|
|
||||||
; PIC: L_exact_log2$slp:
|
|
||||||
; PIC: .long L_exact_log2$lazy_ptr-(L_exact_log2$scv+8)
|
|
||||||
|
|
||||||
; PIC: .section __DATA,__la_symbol_ptr,lazy_symbol_pointers
|
|
||||||
; PIC: L_exact_log2$lazy_ptr:
|
|
||||||
; PIC: .indirect_symbol _exact_log2
|
|
||||||
; PIC: .long dyld_stub_binding_helper
|
|
||||||
|
|
||||||
; PIC: .subsections_via_symbols
|
|
||||||
|
|
||||||
|
|
||||||
; DYNAMIC: .section __TEXT,__symbol_stub4,symbol_stubs,none,12
|
|
||||||
; DYNAMIC: L_exact_log2$stub:
|
|
||||||
; DYNAMIC: .indirect_symbol _exact_log2
|
|
||||||
; DYNAMIC: ldr ip, L_exact_log2$slp
|
|
||||||
; DYNAMIC: ldr pc, [ip, #0]
|
|
||||||
; DYNAMIC: L_exact_log2$slp:
|
|
||||||
; DYNAMIC: .long L_exact_log2$lazy_ptr
|
|
||||||
|
|
||||||
; DYNAMIC: .section __DATA,__la_symbol_ptr,lazy_symbol_pointers
|
|
||||||
; DYNAMIC: L_exact_log2$lazy_ptr:
|
|
||||||
; DYNAMIC: .indirect_symbol _exact_log2
|
|
||||||
; DYNAMIC: .long dyld_stub_binding_helper
|
|
||||||
; DYNAMIC: .subsections_via_symbols
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ declare void @g(i32, i32, i32, i32)
|
||||||
|
|
||||||
define void @f() {
|
define void @f() {
|
||||||
; DARWIN: f:
|
; DARWIN: f:
|
||||||
; DARWIN: blx L_g$stub
|
; DARWIN: blx _g
|
||||||
|
|
||||||
; LINUX: f:
|
; LINUX: f:
|
||||||
; LINUX: bl g
|
; LINUX: bl g
|
||||||
|
|
Loading…
Reference in New Issue