llvm.org GIT mirror llvm / be8c03f
X86 PIC JIT support fixes: encoding bugs, add lazy pointer stubs support. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45575 91177308-0d34-0410-b5e6-96231b3b80d8 Evan Cheng 12 years ago
6 changed file(s) with 154 addition(s) and 32 deletion(s). Raw diff Collapse all Expand all
3838 enum AddressType {
3939 isResult, // Relocation has be transformed into its result pointer.
4040 isGV, // The Target.GV field is valid.
41 isGVLazyPtr, // Relocation of a lazily resolved GV address.
4142 isBB, // Relocation of BB address.
4243 isExtSym, // The Target.ExtSym field is valid.
4344 isConstPool, // Relocation of constant pool address.
5455
5556 union {
5657 void *Result; // If this has been resolved to a resolved pointer
57 GlobalValue *GV; // If this is a pointer to an LLVM global
58 GlobalValue *GV; // If this is a pointer to a GV or a GV lazy ptr
5859 MachineBasicBlock *MBB; // If this is a pointer to a LLVM BB
5960 const char *ExtSym; // If this is a pointer to a named symbol
6061 unsigned Index; // Constant pool / jump table index
9293 return Result;
9394 }
9495
96 /// MachineRelocation::getGVLazyPtr - Return a relocation entry for a
97 /// lazily resolved GlobalValue address.
98 static MachineRelocation getGVLazyPtr(intptr_t offset,
99 unsigned RelocationType,
100 GlobalValue *GV, intptr_t cst = 0,
101 bool NeedStub = 0,
102 bool GOTrelative = 0) {
103 assert((RelocationType & ~63) == 0 && "Relocation type too large!");
104 MachineRelocation Result;
105 Result.Offset = offset;
106 Result.ConstantVal = cst;
107 Result.TargetReloType = RelocationType;
108 Result.AddrType = isGVLazyPtr;
109 Result.NeedStub = NeedStub;
110 Result.GOTRelative = GOTrelative;
111 Result.Target.GV = GV;
112 return Result;
113 }
114
95115 /// MachineRelocation::getBB - Return a relocation entry for a BB.
96116 ///
97117 static MachineRelocation getBB(intptr_t offset,unsigned RelocationType,
190210 /// opposed to a constant string.
191211 bool isGlobalValue() const {
192212 return AddrType == isGV;
213 }
214
215 /// isGlobalValueVLazyPtr - Return true if this relocation is the address
216 /// of a lazily resolved GlobalValue.
217 bool isGlobalValueLazyPtr() const {
218 return AddrType == isGVLazyPtr;
193219 }
194220
195221 /// isBasicBlock - Return true if this relocation is a basic block reference.
233259 /// getGlobalValue - If this is a global value reference, return the
234260 /// referenced global.
235261 GlobalValue *getGlobalValue() const {
236 assert(isGlobalValue() && "This is not a global value reference!");
262 assert((isGlobalValue() || isGlobalValueLazyPtr()) &&
263 "This is not a global value reference!");
237264 return Target.GV;
238265 }
239266
3838 /// code.
3939 ///
4040 virtual void replaceMachineCodeForFunction(void *Old, void *New) = 0;
41
42 /// emitGlobalValueLazyPtr - Use the specified MachineCodeEmitter object to
43 /// emit a lazy pointer which contains the address of the specified GV.
44 virtual void *emitGlobalValueLazyPtr(void *GV, MachineCodeEmitter &MCE) {
45 assert(0 && "This target doesn't implement emitGlobalValueLazyPtr!");
46 return 0;
47 }
4148
4249 /// emitFunctionStub - Use the specified MachineCodeEmitter object to emit a
4350 /// small native function that simply calls the function at the specified
5151 /// corresponds to.
5252 std::map StubToFunctionMap;
5353
54 /// GlobalToLazyPtrMap - Keep track of the lazy pointer created for a
55 /// particular GlobalVariable so that we can reuse them if necessary.
56 std::map GlobalToLazyPtrMap;
57
5458 public:
5559 std::map& getFunctionToStubMap(const MutexGuard& locked) {
5660 assert(locked.holds(TheJIT->lock));
6064 std::map& getStubToFunctionMap(const MutexGuard& locked) {
6165 assert(locked.holds(TheJIT->lock));
6266 return StubToFunctionMap;
67 }
68
69 std::map&
70 getGlobalToLazyPtrMap(const MutexGuard& locked) {
71 assert(locked.holds(TheJIT->lock));
72 return GlobalToLazyPtrMap;
6373 }
6474 };
6575
101111 /// getExternalFunctionStub - Return a stub for the function at the
102112 /// specified address, created lazily on demand.
103113 void *getExternalFunctionStub(void *FnAddr);
114
115 /// getGlobalValueLazyPtr - Return a lazy pointer containing the specified
116 /// GV address.
117 void *getGlobalValueLazyPtr(GlobalValue *V, void *GVAddress);
104118
105119 /// AddCallbackAtLocation - If the target is capable of rewriting an
106120 /// instruction without the use of a stub, record the location of the use so
178192 // JITCompilerFn knows which function to compile!
179193 state.getStubToFunctionMap(locked)[Stub] = F;
180194 return Stub;
195 }
196
197 /// getGlobalValueLazyPtr - Return a lazy pointer containing the specified
198 /// GV address.
199 void *JITResolver::getGlobalValueLazyPtr(GlobalValue *GV, void *GVAddress) {
200 MutexGuard locked(TheJIT->lock);
201
202 // If we already have a stub for this global variable, recycle it.
203 void *&LazyPtr = state.getGlobalToLazyPtrMap(locked)[GV];
204 if (LazyPtr) return LazyPtr;
205
206 // Otherwise, codegen a new lazy pointer.
207 LazyPtr = TheJIT->getJITInfo().emitGlobalValueLazyPtr(GVAddress,
208 *TheJIT->getCodeEmitter());
209
210 DOUT << "JIT: Stub emitted at [" << LazyPtr << "] for GV '"
211 << GV->getName() << "'\n";
212
213 return LazyPtr;
181214 }
182215
183216 /// getExternalFunctionStub - Return a stub for the function at the
360393 }
361394 private:
362395 void *getPointerToGlobal(GlobalValue *GV, void *Reference, bool NoNeedStub);
396 void *getPointerToGVLazyPtr(GlobalValue *V, void *Reference,
397 bool NoNeedStub);
363398 };
364399 }
365400
394429 // Otherwise, we have to emit a lazy resolving stub.
395430 return Resolver.getFunctionStub(F);
396431 }
432
433 void *JITEmitter::getPointerToGVLazyPtr(GlobalValue *V, void *Reference,
434 bool DoesntNeedStub) {
435 // Make sure GV is emitted first.
436 // FIXME: For now, if the GV is an external function we force the JIT to
437 // compile it so the lazy pointer will contain the fully resolved address.
438 void *GVAddress = getPointerToGlobal(V, Reference, true);
439 return Resolver.getGlobalValueLazyPtr(V, GVAddress);
440 }
441
397442
398443 void JITEmitter::startFunction(MachineFunction &F) {
399444 uintptr_t ActualSize;
449494 ResultPtr = getPointerToGlobal(MR.getGlobalValue(),
450495 BufferBegin+MR.getMachineCodeOffset(),
451496 MR.doesntNeedStub());
497 } else if (MR.isGlobalValueLazyPtr()) {
498 ResultPtr = getPointerToGVLazyPtr(MR.getGlobalValue(),
499 BufferBegin+MR.getMachineCodeOffset(),
500 MR.doesntNeedStub());
452501 } else if (MR.isBasicBlock()) {
453502 ResultPtr = (void*)getMachineBasicBlockAddress(MR.getBasicBlock());
454503 } else if (MR.isConstantPoolIndex()) {
3939 intptr_t PICBase;
4040 bool Is64BitMode;
4141 bool IsPIC;
42 bool IsStatic;
4342 public:
4443 static char ID;
4544 explicit Emitter(TargetMachine &tm, MachineCodeEmitter &mce)
4645 : MachineFunctionPass((intptr_t)&ID), II(0), TD(0), TM(tm),
4746 MCE(mce), PICBase(0), Is64BitMode(false),
48 IsPIC(TM.getRelocationModel() == Reloc::PIC_),
49 IsStatic(TM.getRelocationModel() == Reloc::Static) {}
47 IsPIC(TM.getRelocationModel() == Reloc::PIC_) {}
5048 Emitter(TargetMachine &tm, MachineCodeEmitter &mce,
5149 const X86InstrInfo &ii, const TargetData &td, bool is64)
5250 : MachineFunctionPass((intptr_t)&ID), II(&ii), TD(&td), TM(tm),
5351 MCE(mce), PICBase(0), Is64BitMode(is64),
54 IsPIC(TM.getRelocationModel() == Reloc::PIC_),
55 IsStatic(TM.getRelocationModel() == Reloc::Static) {}
52 IsPIC(TM.getRelocationModel() == Reloc::PIC_) {}
5653
5754 bool runOnMachineFunction(MachineFunction &MF);
5855
6663 void emitPCRelativeBlockAddress(MachineBasicBlock *MBB);
6764 void emitGlobalAddress(GlobalValue *GV, unsigned Reloc,
6865 int Disp = 0, intptr_t PCAdj = 0,
69 bool NeedStub = false);
66 bool NeedStub = false, bool IsLazy = false);
7067 void emitExternalSymbolAddress(const char *ES, unsigned Reloc);
7168 void emitConstPoolAddress(unsigned CPI, unsigned Reloc, int Disp = 0,
7269 intptr_t PCAdj = 0);
8784 unsigned getX86RegNum(unsigned RegNo);
8885 bool isX86_64ExtendedReg(const MachineOperand &MO);
8986 unsigned determineREX(const MachineInstr &MI);
87
88 bool gvNeedsLazyPtr(const GlobalValue *GV);
9089 };
9190 char Emitter::ID = 0;
9291 }
102101 assert((MF.getTarget().getRelocationModel() != Reloc::Default ||
103102 MF.getTarget().getRelocationModel() != Reloc::Static) &&
104103 "JIT relocation model must be set to static or default!");
105 II = ((X86TargetMachine&)MF.getTarget()).getInstrInfo();
106 TD = ((X86TargetMachine&)MF.getTarget()).getTargetData();
107 Is64BitMode =
108 ((X86TargetMachine&)MF.getTarget()).getSubtarget().is64Bit();
104 II = ((X86TargetMachine&)TM).getInstrInfo();
105 TD = ((X86TargetMachine&)TM).getTargetData();
106 Is64BitMode = TM.getSubtarget().is64Bit();
109107
110108 do {
111109 MCE.startFunction(MF);
138136 ///
139137 void Emitter::emitGlobalAddress(GlobalValue *GV, unsigned Reloc,
140138 int Disp /* = 0 */, intptr_t PCAdj /* = 0 */,
141 bool NeedStub /* = false */) {
139 bool NeedStub /* = false */,
140 bool isLazy /* = false */) {
141 intptr_t RelocCST = 0;
142142 if (Reloc == X86::reloc_picrel_word)
143 PCAdj += PICBase;
144 MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc,
145 GV, PCAdj, NeedStub));
143 RelocCST = PICBase;
144 else if (Reloc == X86::reloc_pcrel_word)
145 RelocCST = PCAdj;
146 MachineRelocation MR = isLazy
147 ? MachineRelocation::getGVLazyPtr(MCE.getCurrentPCOffset(), Reloc,
148 GV, RelocCST, NeedStub)
149 : MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc,
150 GV, RelocCST, NeedStub);
151 MCE.addRelocation(MR);
146152 if (Reloc == X86::reloc_absolute_dword)
147153 MCE.emitWordLE(0);
148154 MCE.emitWordLE(Disp); // The relocated value will be added to the displacement
152158 /// be emitted to the current location in the function, and allow it to be PC
153159 /// relative.
154160 void Emitter::emitExternalSymbolAddress(const char *ES, unsigned Reloc) {
155 intptr_t PCAdj = (Reloc == X86::reloc_picrel_word) ? PICBase : 0;
161 intptr_t RelocCST = (Reloc == X86::reloc_picrel_word) ? PICBase : 0;
156162 MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(),
157 Reloc, ES, PCAdj));
163 Reloc, ES, RelocCST));
158164 if (Reloc == X86::reloc_absolute_dword)
159165 MCE.emitWordLE(0);
160166 MCE.emitWordLE(0);
166172 void Emitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc,
167173 int Disp /* = 0 */,
168174 intptr_t PCAdj /* = 0 */) {
175 intptr_t RelocCST = 0;
169176 if (Reloc == X86::reloc_picrel_word)
170 PCAdj += PICBase;
177 RelocCST = PICBase;
178 else if (Reloc == X86::reloc_pcrel_word)
179 RelocCST = PCAdj;
171180 MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(),
172 Reloc, CPI, PCAdj));
181 Reloc, CPI, RelocCST));
173182 if (Reloc == X86::reloc_absolute_dword)
174183 MCE.emitWordLE(0);
175184 MCE.emitWordLE(Disp); // The relocated value will be added to the displacement
180189 /// relative.
181190 void Emitter::emitJumpTableAddress(unsigned JTI, unsigned Reloc,
182191 intptr_t PCAdj /* = 0 */) {
192 intptr_t RelocCST = 0;
183193 if (Reloc == X86::reloc_picrel_word)
184 PCAdj += PICBase;
194 RelocCST = PICBase;
195 else if (Reloc == X86::reloc_pcrel_word)
196 RelocCST = PCAdj;
185197 MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
186 Reloc, JTI, PCAdj));
198 Reloc, JTI, RelocCST));
187199 if (Reloc == X86::reloc_absolute_dword)
188200 MCE.emitWordLE(0);
189201 MCE.emitWordLE(0); // The relocated value will be added to the displacement
220232 /// sign-extended field.
221233 static bool isDisp8(int Value) {
222234 return Value == (signed char)Value;
235 }
236
237 bool Emitter::gvNeedsLazyPtr(const GlobalValue *GV) {
238 return !Is64BitMode &&
239 TM.getSubtarget().GVRequiresExtraLoad(GV, TM, false);
223240 }
224241
225242 void Emitter::emitDisplacementField(const MachineOperand *RelocOp,
240257 // 89 04 25 00 00 00 00 mov %eax,0x0 # Absolute
241258 unsigned rt = Is64BitMode ? X86::reloc_pcrel_word
242259 : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word);
243 bool NeedStub = !IsStatic || isa(RelocOp->getGlobal());
260 bool NeedStub = isa(RelocOp->getGlobal());
261 bool isLazy = gvNeedsLazyPtr(RelocOp->getGlobal());
244262 emitGlobalAddress(RelocOp->getGlobal(), rt, RelocOp->getOffset(),
245 PCAdj, NeedStub);
263 PCAdj, NeedStub, isLazy);
246264 } else if (RelocOp->isConstantPoolIndex()) {
247265 unsigned rt = Is64BitMode ? X86::reloc_pcrel_word : X86::reloc_picrel_word;
248266 emitConstPoolAddress(RelocOp->getIndex(), rt,
600618 if (MO.isMachineBasicBlock()) {
601619 emitPCRelativeBlockAddress(MO.getMBB());
602620 } else if (MO.isGlobalAddress()) {
603 bool NeedStub = !IsStatic ||
604 (Is64BitMode && TM.getCodeModel() == CodeModel::Large);
621 bool NeedStub = Is64BitMode && TM.getCodeModel() == CodeModel::Large;
605622 emitGlobalAddress(MO.getGlobal(), X86::reloc_pcrel_word,
606623 0, 0, NeedStub);
607624 } else if (MO.isExternalSymbol()) {
633650 if (Opcode == X86::MOV64ri)
634651 rt = X86::reloc_absolute_dword; // FIXME: add X86II flag?
635652 if (MO1.isGlobalAddress()) {
636 bool NeedStub = !IsStatic || isa(MO1.getGlobal());
637 emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0, NeedStub);
653 bool NeedStub = isa(MO1.getGlobal());
654 bool isLazy = gvNeedsLazyPtr(MO1.getGlobal());
655 emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0,
656 NeedStub, isLazy);
638657 } else if (MO1.isExternalSymbol())
639658 emitExternalSymbolAddress(MO1.getSymbolName(), rt);
640659 else if (MO1.isConstantPoolIndex())
703722 if (Opcode == X86::MOV64ri32)
704723 rt = X86::reloc_absolute_word; // FIXME: add X86II flag?
705724 if (MO1.isGlobalAddress()) {
706 bool NeedStub = !IsStatic || isa(MO1.getGlobal());
707 emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0, NeedStub);
725 bool NeedStub = isa(MO1.getGlobal());
726 bool isLazy = gvNeedsLazyPtr(MO1.getGlobal());
727 emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0,
728 NeedStub, isLazy);
708729 } else if (MO1.isExternalSymbol())
709730 emitExternalSymbolAddress(MO1.getSymbolName(), rt);
710731 else if (MO1.isConstantPoolIndex())
738759 if (Opcode == X86::MOV64mi32)
739760 rt = X86::reloc_absolute_word; // FIXME: add X86II flag?
740761 if (MO.isGlobalAddress()) {
741 bool NeedStub = !IsStatic || isa(MO.getGlobal());
742 emitGlobalAddress(MO.getGlobal(), rt, MO.getOffset(), 0, NeedStub);
762 bool NeedStub = isa(MO.getGlobal());
763 bool isLazy = gvNeedsLazyPtr(MO.getGlobal());
764 emitGlobalAddress(MO.getGlobal(), rt, MO.getOffset(), 0,
765 NeedStub, isLazy);
743766 } else if (MO.isExternalSymbol())
744767 emitExternalSymbolAddress(MO.getSymbolName(), rt);
745768 else if (MO.isConstantPoolIndex())
379379 return X86CompilationCallback;
380380 }
381381
382 void *X86JITInfo::emitGlobalValueLazyPtr(void *GV, MachineCodeEmitter &MCE) {
383 #ifdef __x86_64__
384 MCE.startFunctionStub(8, 8);
385 MCE.emitWordLE(((unsigned *)&GV)[0]);
386 MCE.emitWordLE(((unsigned *)&GV)[1]);
387 #else
388 MCE.startFunctionStub(4, 4);
389 MCE.emitWordLE((unsigned)GV);
390 #endif
391 return MCE.finishFunctionStub(0);
392 }
393
382394 void *X86JITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) {
383395 // Note, we cast to intptr_t here to silence a -pedantic warning that
384396 // complains about casting a function pointer to a normal pointer.
3030 ///
3131 virtual void replaceMachineCodeForFunction(void *Old, void *New);
3232
33 /// emitGlobalValueLazyPtr - Use the specified MachineCodeEmitter object to
34 /// emit a lazy pointer which contains the address of the specified GV.
35 virtual void *emitGlobalValueLazyPtr(void *GV, MachineCodeEmitter &MCE);
36
3337 /// emitFunctionStub - Use the specified MachineCodeEmitter object to emit a
3438 /// small native function that simply calls the function at the specified
3539 /// address.