llvm.org GIT mirror llvm / d76a68e
Merge 80404 from mainline. Let Darwin linker auto-synthesize stubs and lazy-pointers. This deletes a bunch of nasty code in ARM asm printer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_26@81647 91177308-0d34-0410-b5e6-96231b3b80d8 Tanya Lattner 10 years ago
9 changed file(s) with 60 addition(s) and 263 deletion(s). Raw diff Collapse all Expand all
422422
423423 GlobalValue *GV = ACPV->getGV();
424424 if (GV) {
425 assert(!ACPV->isStub() && "Don't know how to deal this yet!");
426 if (ACPV->isNonLazyPointer())
427 MCE.addRelocation(MachineRelocation::getIndirectSymbol(
428 MCE.getCurrentPCOffset(), ARM::reloc_arm_machine_cp_entry, GV,
429 (intptr_t)ACPV, false));
430 else
431 emitGlobalAddress(GV, ARM::reloc_arm_machine_cp_entry,
432 ACPV->isStub() || isa(GV), (intptr_t)ACPV);
425 emitGlobalAddress(GV, ARM::reloc_arm_machine_cp_entry,
426 isa(GV), (intptr_t)ACPV);
433427 } else {
434 assert(!ACPV->isNonLazyPointer() && "Don't know how to deal this yet!");
435428 emitExternalSymbolAddress(ACPV->getSymbol(), ARM::reloc_arm_absolute);
436429 }
437430 emitWordLE(0);
2020 using namespace llvm;
2121
2222 ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, unsigned id,
23 ARMCP::ARMCPKind k,
2423 unsigned char PCAdj,
2524 const char *Modif,
2625 bool AddCA)
2726 : MachineConstantPoolValue((const Type*)gv->getType()),
28 GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj),
27 GV(gv), S(NULL), LabelId(id), PCAdjust(PCAdj),
2928 Modifier(Modif), AddCurrentAddress(AddCA) {}
3029
3130 ARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C,
3231 const char *s, unsigned id,
33 ARMCP::ARMCPKind k,
3432 unsigned char PCAdj,
3533 const char *Modif,
3634 bool AddCA)
3735 : MachineConstantPoolValue((const Type*)Type::getInt32Ty(C)),
38 GV(NULL), S(strdup(s)), LabelId(id), Kind(k), PCAdjust(PCAdj),
36 GV(NULL), S(strdup(s)), LabelId(id), PCAdjust(PCAdj),
3937 Modifier(Modif), AddCurrentAddress(AddCA) {}
4038
41 ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv,
42 ARMCP::ARMCPKind k,
43 const char *Modif)
39 ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, const char *Modif)
4440 : MachineConstantPoolValue((const Type*)Type::getInt32Ty(gv->getContext())),
45 GV(gv), S(NULL), LabelId(0), Kind(k), PCAdjust(0),
41 GV(gv), S(NULL), LabelId(0), PCAdjust(0),
4642 Modifier(Modif) {}
4743
4844 int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
5753 if (CPV->GV == GV &&
5854 CPV->S == S &&
5955 CPV->LabelId == LabelId &&
60 CPV->Kind == Kind &&
6156 CPV->PCAdjust == PCAdjust)
6257 return i;
6358 }
7570 ID.AddPointer(GV);
7671 ID.AddPointer(S);
7772 ID.AddInteger(LabelId);
78 ID.AddInteger((unsigned)Kind);
7973 ID.AddInteger(PCAdjust);
8074 }
8175
9387 O << GV->getName();
9488 else
9589 O << S;
96 if (isNonLazyPointer()) O << "$non_lazy_ptr";
97 else if (isStub()) O << "$stub";
9890 if (Modifier) O << "(" << Modifier << ")";
9991 if (PCAdjust != 0) {
10092 O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust;
2121 class GlobalValue;
2222 class LLVMContext;
2323
24 namespace ARMCP {
25 enum ARMCPKind {
26 CPValue,
27 CPNonLazyPtr,
28 CPStub
29 };
30 }
31
3224 /// ARMConstantPoolValue - ARM specific constantpool value. This is used to
3325 /// represent PC relative displacement between the address of the load
3426 /// instruction and the global value being loaded, i.e. (&GV-(LPIC+8)).
3628 GlobalValue *GV; // GlobalValue being loaded.
3729 const char *S; // ExtSymbol being loaded.
3830 unsigned LabelId; // Label id of the load.
39 ARMCP::ARMCPKind Kind; // non_lazy_ptr or stub?
4031 unsigned char PCAdjust; // Extra adjustment if constantpool is pc relative.
4132 // 8 for ARM, 4 for Thumb.
4233 const char *Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8))
4435
4536 public:
4637 ARMConstantPoolValue(GlobalValue *gv, unsigned id,
47 ARMCP::ARMCPKind Kind = ARMCP::CPValue,
4838 unsigned char PCAdj = 0, const char *Modifier = NULL,
4939 bool AddCurrentAddress = false);
5040 ARMConstantPoolValue(LLVMContext &C, const char *s, unsigned id,
51 ARMCP::ARMCPKind Kind = ARMCP::CPValue,
5241 unsigned char PCAdj = 0, const char *Modifier = NULL,
5342 bool AddCurrentAddress = false);
54 ARMConstantPoolValue(GlobalValue *GV, ARMCP::ARMCPKind Kind,
55 const char *Modifier);
43 ARMConstantPoolValue(GlobalValue *GV, const char *Modifier);
5644 ARMConstantPoolValue();
5745 ~ARMConstantPoolValue();
5846
6351 bool hasModifier() const { return Modifier != NULL; }
6452 bool mustAddCurrentAddress() const { return AddCurrentAddress; }
6553 unsigned getLabelId() const { return LabelId; }
66 bool isNonLazyPointer() const { return Kind == ARMCP::CPNonLazyPtr; }
67 bool isStub() const { return Kind == ARMCP::CPStub; }
6854 unsigned char getPCAdjustment() const { return PCAdjust; }
6955
7056 virtual unsigned getRelocationInfo() const {
974974 isLocalARMFunc = !Subtarget->isThumb() && !isExt;
975975 // tBX takes a register source operand.
976976 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
977 ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, ARMPCLabelIndex,
978 ARMCP::CPStub, 4);
977 ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV,
978 ARMPCLabelIndex, 4);
979979 SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4);
980980 CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
981981 Callee = DAG.getLoad(getPointerTy(), dl,
994994 const char *Sym = S->getSymbol();
995995 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
996996 ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(),
997 Sym, ARMPCLabelIndex,
998 ARMCP::CPStub, 4);
997 Sym, ARMPCLabelIndex, 4);
999998 SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4);
1000999 CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
10011000 Callee = DAG.getLoad(getPointerTy(), dl,
11721171 EVT PtrVT = getPointerTy();
11731172 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
11741173 ARMConstantPoolValue *CPV =
1175 new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex, ARMCP::CPValue,
1174 new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex,
11761175 PCAdj, "tlsgd", true);
11771176 SDValue Argument = DAG.getTargetConstantPool(CPV, PtrVT, 4);
11781177 Argument = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Argument);
12141213 // initial exec model
12151214 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
12161215 ARMConstantPoolValue *CPV =
1217 new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex, ARMCP::CPValue,
1216 new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex,
12181217 PCAdj, "gottpoff", true);
12191218 Offset = DAG.getTargetConstantPool(CPV, PtrVT, 4);
12201219 Offset = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Offset);
12271226 Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, NULL, 0);
12281227 } else {
12291228 // local exec model
1230 ARMConstantPoolValue *CPV =
1231 new ARMConstantPoolValue(GV, ARMCP::CPValue, "tpoff");
1229 ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, "tpoff");
12321230 Offset = DAG.getTargetConstantPool(CPV, PtrVT, 4);
12331231 Offset = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Offset);
12341232 Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, NULL, 0);
12621260 if (RelocM == Reloc::PIC_) {
12631261 bool UseGOTOFF = GV->hasLocalLinkage() || GV->hasHiddenVisibility();
12641262 ARMConstantPoolValue *CPV =
1265 new ARMConstantPoolValue(GV, ARMCP::CPValue, UseGOTOFF ? "GOTOFF":"GOT");
1263 new ARMConstantPoolValue(GV, UseGOTOFF ? "GOTOFF" : "GOT");
12661264 SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
12671265 CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
12681266 SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(),
12801278 }
12811279 }
12821280
1283 /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol
1284 /// even in non-static mode.
1285 static bool GVIsIndirectSymbol(GlobalValue *GV, Reloc::Model RelocM) {
1286 // If symbol visibility is hidden, the extra load is not needed if
1287 // the symbol is definitely defined in the current translation unit.
1288 bool isDecl = GV->isDeclaration() || GV->hasAvailableExternallyLinkage();
1289 if (GV->hasHiddenVisibility() && (!isDecl && !GV->hasCommonLinkage()))
1290 return false;
1291 return RelocM != Reloc::Static && (isDecl || GV->isWeakForLinker());
1292 }
1293
12941281 SDValue ARMTargetLowering::LowerGlobalAddressDarwin(SDValue Op,
12951282 SelectionDAG &DAG) {
12961283 EVT PtrVT = getPointerTy();
12971284 DebugLoc dl = Op.getDebugLoc();
12981285 GlobalValue *GV = cast(Op)->getGlobal();
12991286 Reloc::Model RelocM = getTargetMachine().getRelocationModel();
1300 bool IsIndirect = GVIsIndirectSymbol(GV, RelocM);
13011287 SDValue CPAddr;
13021288 if (RelocM == Reloc::Static)
13031289 CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 4);
13041290 else {
1305 unsigned PCAdj = (RelocM != Reloc::PIC_)
1306 ? 0 : (Subtarget->isThumb() ? 4 : 8);
1307 ARMCP::ARMCPKind Kind = IsIndirect ? ARMCP::CPNonLazyPtr
1308 : ARMCP::CPValue;
1309 ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, ARMPCLabelIndex,
1310 Kind, PCAdj);
1291 unsigned PCAdj = (RelocM != Reloc::PIC_) ? 0 : (Subtarget->isThumb()?4:8);
1292 ARMConstantPoolValue *CPV =
1293 new ARMConstantPoolValue(GV, ARMPCLabelIndex, PCAdj);
13111294 CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
13121295 }
13131296 CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
13191302 SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex++, MVT::i32);
13201303 Result = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
13211304 }
1322 if (IsIndirect)
1305
1306 if (Subtarget->GVIsIndirectSymbol(GV, RelocM == Reloc::Static))
13231307 Result = DAG.getLoad(PtrVT, dl, Chain, Result, NULL, 0);
13241308
13251309 return Result;
13341318 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
13351319 ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(),
13361320 "_GLOBAL_OFFSET_TABLE_",
1337 ARMPCLabelIndex,
1338 ARMCP::CPValue, PCAdj);
1321 ARMPCLabelIndex, PCAdj);
13391322 SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
13401323 CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
13411324 SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, NULL, 0);
14161399 SDValue CPAddr;
14171400 unsigned PCAdj = (RelocM != Reloc::PIC_)
14181401 ? 0 : (Subtarget->isThumb() ? 4 : 8);
1419 ARMCP::ARMCPKind Kind = ARMCP::CPValue;
14201402 // Save off the LSDA name for the AsmPrinter to use when it's time
14211403 // to emit the table
14221404 std::string LSDAName = "L_lsda_";
14231405 LSDAName += MF.getFunction()->getName();
14241406 ARMConstantPoolValue *CPV =
14251407 new ARMConstantPoolValue(*DAG.getContext(), LSDAName.c_str(),
1426 ARMPCLabelIndex, Kind, PCAdj);
1408 ARMPCLabelIndex, PCAdj);
14271409 CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
14281410 CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
14291411 SDValue Result =
1212
1313 #include "ARMSubtarget.h"
1414 #include "ARMGenSubtarget.inc"
15 #include "llvm/GlobalValue.h"
1516 #include "llvm/Target/TargetOptions.h"
1617 #include "llvm/Support/CommandLine.h"
1718 using namespace llvm;
9192 if (isTargetDarwin())
9293 IsR9Reserved = ReserveR9 | (ARMArchVersion < V6);
9394 }
95
96 /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol.
97 bool ARMSubtarget::GVIsIndirectSymbol(GlobalValue *GV, bool isStatic) const {
98 // If symbol visibility is hidden, the extra load is not needed if
99 // the symbol is definitely defined in the current translation unit.
100 bool isDecl = GV->isDeclaration() || GV->hasAvailableExternallyLinkage();
101 if (GV->hasHiddenVisibility() && (!isDecl && !GV->hasCommonLinkage()))
102 return false;
103 return !isStatic && (isDecl || GV->isWeakForLinker());
104 }
1818 #include
1919
2020 namespace llvm {
21 class GlobalValue;
2122
2223 class ARMSubtarget : public TargetSubtarget {
2324 protected:
128129 /// stack frame on entry to the function and which must be maintained by every
129130 /// function for this subtarget.
130131 unsigned getStackAlignment() const { return stackAlignment; }
132
133 /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect
134 /// symbol.
135 bool GVIsIndirectSymbol(GlobalValue *GV, bool isStatic) const;
131136 };
132137 } // End llvm namespace
133138
7878 /// visibility that require non-lazy-pointers for indirect access.
7979 StringMap HiddenGVNonLazyPtrs;
8080
81 struct FnStubInfo {
82 std::string Stub, LazyPtr, SLP, SCV;
83
84 FnStubInfo() {}
85
86 void Init(const GlobalValue *GV, Mangler *Mang) {
87 // Already initialized.
88 if (!Stub.empty()) return;
89 Stub = Mang->getMangledName(GV, "$stub", true);
90 LazyPtr = Mang->getMangledName(GV, "$lazy_ptr", true);
91 SLP = Mang->getMangledName(GV, "$slp", true);
92 SCV = Mang->getMangledName(GV, "$scv", true);
93 }
94
95 void Init(const std::string &GV, Mangler *Mang) {
96 // Already initialized.
97 if (!Stub.empty()) return;
98 Stub = Mang->makeNameProper(GV + "$stub", Mangler::Private);
99 LazyPtr = Mang->makeNameProper(GV + "$lazy_ptr", Mangler::Private);
100 SLP = Mang->makeNameProper(GV + "$slp", Mangler::Private);
101 SCV = Mang->makeNameProper(GV + "$scv", Mangler::Private);
102 }
103 };
104
105 /// FnStubs - Keeps the set of external function GlobalAddresses that the
106 /// asm printer should generate stubs for.
107 StringMap FnStubs;
108
10981 /// True if asm printer is printing a series of CONSTPOOL_ENTRY.
11082 bool InCPMode;
11183 public:
187159 GlobalValue *GV = ACPV->getGV();
188160 std::string Name;
189161
190
191 if (ACPV->isNonLazyPointer()) {
192 std::string SymName = Mang->getMangledName(GV);
193 Name = Mang->getMangledName(GV, "$non_lazy_ptr", true);
194
195 if (GV->hasHiddenVisibility())
196 HiddenGVNonLazyPtrs[SymName] = Name;
197 else
198 GVNonLazyPtrs[SymName] = Name;
199 } else if (ACPV->isStub()) {
200 if (GV) {
201 FnStubInfo &FnInfo = FnStubs[Mang->getMangledName(GV)];
202 FnInfo.Init(GV, Mang);
203 Name = FnInfo.Stub;
204 } else {
205 FnStubInfo &FnInfo = FnStubs[Mang->makeNameProper(ACPV->getSymbol())];
206 FnInfo.Init(ACPV->getSymbol(), Mang);
207 Name = FnInfo.Stub;
162 if (GV) {
163 bool isIndirect = Subtarget->isTargetDarwin() &&
164 Subtarget->GVIsIndirectSymbol(GV,
165 TM.getRelocationModel() == Reloc::Static);
166 if (!isIndirect)
167 Name = Mang->getMangledName(GV);
168 else {
169 // FIXME: Remove this when Darwin transition to @GOT like syntax.
170 std::string SymName = Mang->getMangledName(GV);
171 Name = Mang->getMangledName(GV, "$non_lazy_ptr", true);
172 if (GV->hasHiddenVisibility())
173 HiddenGVNonLazyPtrs[SymName] = Name;
174 else
175 GVNonLazyPtrs[SymName] = Name;
208176 }
209 } else {
210 if (GV)
211 Name = Mang->getMangledName(GV);
212 else if (!strncmp(ACPV->getSymbol(), "L_lsda_", 7))
213 Name = ACPV->getSymbol();
214 else
215 Name = Mang->makeNameProper(ACPV->getSymbol());
216 }
217 O << Name;
218
219
177 } else if (!strncmp(ACPV->getSymbol(), "L_lsda_", 7))
178 Name = ACPV->getSymbol();
179 else
180 Name = Mang->makeNameProper(ACPV->getSymbol());
181 O << Name;
220182
221183 if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
222184 if (ACPV->getPCAdjustment() != 0) {
371333 case MachineOperand::MO_GlobalAddress: {
372334 bool isCallOp = Modifier && !strcmp(Modifier, "call");
373335 GlobalValue *GV = MO.getGlobal();
374 std::string Name;
375 bool isExt = GV->isDeclaration() || GV->isWeakForLinker();
376 if (isExt && isCallOp && Subtarget->isTargetDarwin() &&
377 TM.getRelocationModel() != Reloc::Static) {
378 FnStubInfo &FnInfo = FnStubs[Mang->getMangledName(GV)];
379 FnInfo.Init(GV, Mang);
380 Name = FnInfo.Stub;
381 } else {
382 Name = Mang->getMangledName(GV);
383 }
384
385 O << Name;
336 O << Mang->getMangledName(GV);
386337
387338 printOffset(MO.getOffset());
388339
393344 }
394345 case MachineOperand::MO_ExternalSymbol: {
395346 bool isCallOp = Modifier && !strcmp(Modifier, "call");
396 std::string Name;
397 if (isCallOp && Subtarget->isTargetDarwin() &&
398 TM.getRelocationModel() != Reloc::Static) {
399 FnStubInfo &FnInfo = FnStubs[Mang->makeNameProper(MO.getSymbolName())];
400 FnInfo.Init(MO.getSymbolName(), Mang);
401 Name = FnInfo.Stub;
402 } else
403 Name = Mang->makeNameProper(MO.getSymbolName());
347 std::string Name = Mang->makeNameProper(MO.getSymbolName());
404348
405349 O << Name;
406350 if (isCallOp && Subtarget->isTargetELF() &&
12761220 static_cast(getObjFileLowering());
12771221
12781222 O << '\n';
1279
1280 if (!FnStubs.empty()) {
1281 unsigned StubSize = 12;
1282 const char *StubSectionName = "__symbol_stub4";
1283
1284 if (TM.getRelocationModel() == Reloc::PIC_) {
1285 StubSize = 16;
1286 StubSectionName = "__picsymbolstub4";
1287 }
1288
1289 const MCSection *StubSection
1290 = TLOFMacho.getMachOSection("__TEXT", StubSectionName,
1291 MCSectionMachO::S_SYMBOL_STUBS,
1292 StubSize, SectionKind::getText());
1293
1294 const MCSection *LazySymbolPointerSection
1295 = TLOFMacho.getLazySymbolPointerSection();
1296
1297 // Output stubs for dynamically-linked functions
1298 for (StringMap::iterator I = FnStubs.begin(),
1299 E = FnStubs.end(); I != E; ++I) {
1300 const FnStubInfo &Info = I->second;
1301
1302 OutStreamer.SwitchSection(StubSection);
1303 EmitAlignment(2);
1304 O << "\t.code\t32\n";
1305
1306 O << Info.Stub << ":\n";
1307 O << "\t.indirect_symbol " << I->getKeyData() << '\n';
1308 O << "\tldr ip, " << Info.SLP << '\n';
1309 if (TM.getRelocationModel() == Reloc::PIC_) {
1310 O << Info.SCV << ":\n";
1311 O << "\tadd ip, pc, ip\n";
1312 }
1313 O << "\tldr pc, [ip, #0]\n";
1314 O << Info.SLP << ":\n";
1315 O << "\t.long\t" << Info.LazyPtr;
1316 if (TM.getRelocationModel() == Reloc::PIC_)
1317 O << "-(" << Info.SCV << "+8)";
1318 O << '\n';
1319
1320 OutStreamer.SwitchSection(LazySymbolPointerSection);
1321 O << Info.LazyPtr << ":\n";
1322 O << "\t.indirect_symbol " << I->getKeyData() << "\n";
1323 O << "\t.long\tdyld_stub_binding_helper\n";
1324 }
1325 O << '\n';
1326 }
1327
1223
13281224 // Output non-lazy-pointers for external and common global variables.
13291225 if (!GVNonLazyPtrs.empty()) {
13301226 // Switch with ".non_lazy_symbol_pointer" directive.
13481244 }
13491245 }
13501246
1351
13521247 // Funny Darwin hack: This flag tells the linker that no global symbols
13531248 // contain code that falls through to other global symbols (e.g. the obvious
13541249 // implementation of multiple entry points). If this doesn't occur, the
+0
-67
test/CodeGen/ARM/stubs.ll less more
None ; RUN: llvm-as < %s | llc -relocation-model=static | FileCheck %s -check-prefix=STATIC
1 ; RUN: llvm-as < %s | llc -relocation-model=pic | FileCheck %s -check-prefix=PIC
2 ; RUN: llvm-as < %s | llc -relocation-model=dynamic-no-pic | FileCheck %s -check-prefix=DYNAMIC
3 ; PR4482
4 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"
5 target triple = "armv6-apple-darwin2"
6
7 define i32 @foo(i64 %x) nounwind {
8 entry:
9 ; STATIC: _foo:
10 ; STATIC: bl _exact_log2
11 ; STATIC: ldmfd sp!, {r7, pc}
12 ; STATIC: .subsections_via_symbols
13
14 ; PIC: _foo:
15 ; PIC: bl L_exact_log2$stub
16 ; PIC: ldmfd sp!, {r7, pc}
17
18 ; DYNAMIC: _foo:
19 ; DYNAMIC: bl L_exact_log2$stub
20 ; DYNAMIC: ldmfd sp!, {r7, pc}
21
22 %A = call i32 @exact_log2(i64 %x)
23 ret i32 %A
24 }
25
26 define available_externally i32 @exact_log2(i64 %x) nounwind {
27 ret i32 4
28 }
29
30
31 ; PIC: .section __TEXT,__picsymbolstub4,symbol_stubs,none,16
32 ; PIC: L_exact_log2$stub:
33 ; PIC: .indirect_symbol _exact_log2
34 ; PIC: ldr ip, L_exact_log2$slp
35 ; PIC: L_exact_log2$scv:
36 ; PIC: add ip, pc, ip
37 ; PIC: ldr pc, [ip, #0]
38 ; PIC: L_exact_log2$slp:
39 ; PIC: .long L_exact_log2$lazy_ptr-(L_exact_log2$scv+8)
40
41 ; PIC: .section __DATA,__la_symbol_ptr,lazy_symbol_pointers
42 ; PIC: L_exact_log2$lazy_ptr:
43 ; PIC: .indirect_symbol _exact_log2
44 ; PIC: .long dyld_stub_binding_helper
45
46 ; PIC: .subsections_via_symbols
47
48
49 ; DYNAMIC: .section __TEXT,__symbol_stub4,symbol_stubs,none,12
50 ; DYNAMIC: L_exact_log2$stub:
51 ; DYNAMIC: .indirect_symbol _exact_log2
52 ; DYNAMIC: ldr ip, L_exact_log2$slp
53 ; DYNAMIC: ldr pc, [ip, #0]
54 ; DYNAMIC: L_exact_log2$slp:
55 ; DYNAMIC: .long L_exact_log2$lazy_ptr
56
57 ; DYNAMIC: .section __DATA,__la_symbol_ptr,lazy_symbol_pointers
58 ; DYNAMIC: L_exact_log2$lazy_ptr:
59 ; DYNAMIC: .indirect_symbol _exact_log2
60 ; DYNAMIC: .long dyld_stub_binding_helper
61 ; DYNAMIC: .subsections_via_symbols
62
63
64
65
66
66
77 define void @f() {
88 ; DARWIN: f:
9 ; DARWIN: blx L_g$stub
9 ; DARWIN: blx _g
1010
1111 ; LINUX: f:
1212 ; LINUX: bl g