| LEFT | RIGHT |
| 1 //===-- JITEmitter.cpp - Write machine code to executable memory ----------===// | 1 //===-- JITEmitter.cpp - Write machine code to executable memory ----------===// |
| 2 // | 2 // |
| 3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file defines a MachineCodeEmitter object that is used by the JIT to | 10 // This file defines a MachineCodeEmitter object that is used by the JIT to |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 /// getExternalFunctionStub - Return a stub for the function at the | 264 /// getExternalFunctionStub - Return a stub for the function at the |
| 265 /// specified address, created lazily on demand. | 265 /// specified address, created lazily on demand. |
| 266 void *JITResolver::getExternalFunctionStub(void *FnAddr) { | 266 void *JITResolver::getExternalFunctionStub(void *FnAddr) { |
| 267 // If we already have a stub for this function, recycle it. | 267 // If we already have a stub for this function, recycle it. |
| 268 void *&Stub = ExternalFnToStubMap[FnAddr]; | 268 void *&Stub = ExternalFnToStubMap[FnAddr]; |
| 269 if (Stub) return Stub; | 269 if (Stub) return Stub; |
| 270 | 270 |
| 271 Stub = TheJIT->getJITInfo().emitFunctionStub(0, FnAddr, | 271 Stub = TheJIT->getJITInfo().emitFunctionStub(0, FnAddr, |
| 272 *TheJIT->getCodeEmitter()); | 272 *TheJIT->getCodeEmitter()); |
| 273 | 273 |
| 274 DOUT << "JIT: Stub emitted at [" << Stub | 274 DEBUG(errs() << "JIT: Stub emitted at [" << Stub |
| 275 << "] for external function at '" << FnAddr << "'\n"; | 275 << "] for external function at '" << FnAddr << "'\n"); |
| 276 return Stub; | 276 return Stub; |
| 277 } | 277 } |
| 278 | 278 |
| 279 unsigned JITResolver::getGOTIndexForAddr(void* addr) { | 279 unsigned JITResolver::getGOTIndexForAddr(void* addr) { |
| 280 unsigned idx = revGOTMap[addr]; | 280 unsigned idx = revGOTMap[addr]; |
| 281 if (!idx) { | 281 if (!idx) { |
| 282 idx = ++nextGOTIndex; | 282 idx = ++nextGOTIndex; |
| 283 revGOTMap[addr] = idx; | 283 revGOTMap[addr] = idx; |
| 284 DOUT << "JIT: Adding GOT entry " << idx << " for addr [" << addr << "]\n"; | 284 DEBUG(errs() << "JIT: Adding GOT entry " << idx << " for addr [" |
| 285 << addr << "]\n"); |
| 285 } | 286 } |
| 286 return idx; | 287 return idx; |
| 287 } | 288 } |
| 288 | 289 |
| 289 void JITResolver::getRelocatableGVs(SmallVectorImpl<GlobalValue*> &GVs, | 290 void JITResolver::getRelocatableGVs(SmallVectorImpl<GlobalValue*> &GVs, |
| 290 SmallVectorImpl<void*> &Ptrs) { | 291 SmallVectorImpl<void*> &Ptrs) { |
| 291 MutexGuard locked(TheJIT->lock); | 292 MutexGuard locked(TheJIT->lock); |
| 292 | 293 |
| 293 FunctionToStubMapTy &FM = state.getFunctionToStubMap(locked); | 294 FunctionToStubMapTy &FM = state.getFunctionToStubMap(locked); |
| 294 GlobalToIndirectSymMapTy &GM = state.getGlobalToIndirectSymMap(locked); | 295 GlobalToIndirectSymMapTy &GM = state.getGlobalToIndirectSymMap(locked); |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 DenseMap<void *, SmallPtrSet<const Function*, 1> > StubFnRefs; | 503 DenseMap<void *, SmallPtrSet<const Function*, 1> > StubFnRefs; |
| 503 | 504 |
| 504 // ExtFnStubs - A map of external function names to stubs which have entries | 505 // ExtFnStubs - A map of external function names to stubs which have entries |
| 505 // in the JITResolver's ExternalFnToStubMap. | 506 // in the JITResolver's ExternalFnToStubMap. |
| 506 StringMap<void *> ExtFnStubs; | 507 StringMap<void *> ExtFnStubs; |
| 507 | 508 |
| 508 DebugLocTuple PrevDLT; | 509 DebugLocTuple PrevDLT; |
| 509 | 510 |
| 510 public: | 511 public: |
| 511 JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM) | 512 JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM) |
| 512 : SizeEstimate(0), Resolver(jit), CurFn(0) { | 513 : SizeEstimate(0), Resolver(jit), MMI(0), CurFn(0) { |
| 513 MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager(); | 514 MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager(); |
| 514 if (jit.getJITInfo().needsGOT()) { | 515 if (jit.getJITInfo().needsGOT()) { |
| 515 MemMgr->AllocateGOT(); | 516 MemMgr->AllocateGOT(); |
| 516 DOUT << "JIT is managing a GOT\n"; | 517 DEBUG(errs() << "JIT is managing a GOT\n"); |
| 517 } | 518 } |
| 518 | 519 |
| 519 if (DwarfExceptionHandling || JITEmitDebugInfo) { | 520 if (DwarfExceptionHandling || JITEmitDebugInfo) { |
| 520 DE.reset(new JITDwarfEmitter(jit)); | 521 DE.reset(new JITDwarfEmitter(jit)); |
| 521 } | 522 } |
| 522 if (JITEmitDebugInfo) { | 523 if (JITEmitDebugInfo) { |
| 523 DR.reset(new JITDebugRegisterer(TM)); | 524 DR.reset(new JITDebugRegisterer(TM)); |
| 524 } | 525 } |
| 525 } | 526 } |
| 526 ~JITEmitter() { | 527 ~JITEmitter() { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment); | 559 virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment); |
| 559 | 560 |
| 560 virtual void addRelocation(const MachineRelocation &MR) { | 561 virtual void addRelocation(const MachineRelocation &MR) { |
| 561 Relocations.push_back(MR); | 562 Relocations.push_back(MR); |
| 562 } | 563 } |
| 563 | 564 |
| 564 virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { | 565 virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { |
| 565 if (MBBLocations.size() <= (unsigned)MBB->getNumber()) | 566 if (MBBLocations.size() <= (unsigned)MBB->getNumber()) |
| 566 MBBLocations.resize((MBB->getNumber()+1)*2); | 567 MBBLocations.resize((MBB->getNumber()+1)*2); |
| 567 MBBLocations[MBB->getNumber()] = getCurrentPCValue(); | 568 MBBLocations[MBB->getNumber()] = getCurrentPCValue(); |
| 568 DOUT << "JIT: Emitting BB" << MBB->getNumber() << " at [" | 569 DEBUG(errs() << "JIT: Emitting BB" << MBB->getNumber() << " at [" |
| 569 << (void*) getCurrentPCValue() << "]\n"; | 570 << (void*) getCurrentPCValue() << "]\n"); |
| 570 } | 571 } |
| 571 | 572 |
| 572 virtual uintptr_t getConstantPoolEntryAddress(unsigned Entry) const; | 573 virtual uintptr_t getConstantPoolEntryAddress(unsigned Entry) const; |
| 573 virtual uintptr_t getJumpTableEntryAddress(unsigned Entry) const; | 574 virtual uintptr_t getJumpTableEntryAddress(unsigned Entry) const; |
| 574 | 575 |
| 575 virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const
{ | 576 virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const
{ |
| 576 assert(MBBLocations.size() > (unsigned)MBB->getNumber() && | 577 assert(MBBLocations.size() > (unsigned)MBB->getNumber() && |
| 577 MBBLocations[MBB->getNumber()] && "MBB not emitted!"); | 578 MBBLocations[MBB->getNumber()] && "MBB not emitted!"); |
| 578 return MBBLocations[MBB->getNumber()]; | 579 return MBBLocations[MBB->getNumber()]; |
| 579 } | 580 } |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 } | 759 } |
| 759 | 760 |
| 760 /// addSizeOfGlobal - add the size of the global (plus any alignment padding) | 761 /// addSizeOfGlobal - add the size of the global (plus any alignment padding) |
| 761 /// into the running total Size. | 762 /// into the running total Size. |
| 762 | 763 |
| 763 unsigned JITEmitter::addSizeOfGlobal(const GlobalVariable *GV, unsigned Size) { | 764 unsigned JITEmitter::addSizeOfGlobal(const GlobalVariable *GV, unsigned Size) { |
| 764 const Type *ElTy = GV->getType()->getElementType(); | 765 const Type *ElTy = GV->getType()->getElementType(); |
| 765 size_t GVSize = (size_t)TheJIT->getTargetData()->getTypeAllocSize(ElTy); | 766 size_t GVSize = (size_t)TheJIT->getTargetData()->getTypeAllocSize(ElTy); |
| 766 size_t GVAlign = | 767 size_t GVAlign = |
| 767 (size_t)TheJIT->getTargetData()->getPreferredAlignment(GV); | 768 (size_t)TheJIT->getTargetData()->getPreferredAlignment(GV); |
| 768 DOUT << "JIT: Adding in size " << GVSize << " alignment " << GVAlign; | 769 DEBUG(errs() << "JIT: Adding in size " << GVSize << " alignment " << GVAlign); |
| 769 DEBUG(GV->dump()); | 770 DEBUG(GV->dump()); |
| 770 // Assume code section ends with worst possible alignment, so first | 771 // Assume code section ends with worst possible alignment, so first |
| 771 // variable needs maximal padding. | 772 // variable needs maximal padding. |
| 772 if (Size==0) | 773 if (Size==0) |
| 773 Size = 1; | 774 Size = 1; |
| 774 Size = ((Size+GVAlign-1)/GVAlign)*GVAlign; | 775 Size = ((Size+GVAlign-1)/GVAlign)*GVAlign; |
| 775 Size += GVSize; | 776 Size += GVSize; |
| 776 return Size; | 777 return Size; |
| 777 } | 778 } |
| 778 | 779 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 886 // assuming the addresses of the new globals in this module | 887 // assuming the addresses of the new globals in this module |
| 887 // start at 0 (or something) and adjusting them after codegen | 888 // start at 0 (or something) and adjusting them after codegen |
| 888 // complete. Another possibility is to grab a marker bit in GV. | 889 // complete. Another possibility is to grab a marker bit in GV. |
| 889 if (GVSet.insert(GV)) | 890 if (GVSet.insert(GV)) |
| 890 // A variable as yet unseen. Add in its size. | 891 // A variable as yet unseen. Add in its size. |
| 891 Size = addSizeOfGlobal(GV, Size); | 892 Size = addSizeOfGlobal(GV, Size); |
| 892 } | 893 } |
| 893 } | 894 } |
| 894 } | 895 } |
| 895 } | 896 } |
| 896 DOUT << "JIT: About to look through initializers\n"; | 897 DEBUG(errs() << "JIT: About to look through initializers\n"); |
| 897 // Look for more globals that are referenced only from initializers. | 898 // Look for more globals that are referenced only from initializers. |
| 898 // GVSet.end is computed each time because the set can grow as we go. | 899 // GVSet.end is computed each time because the set can grow as we go. |
| 899 for (SmallPtrSet<const GlobalVariable *, 8>::iterator I = GVSet.begin(); | 900 for (SmallPtrSet<const GlobalVariable *, 8>::iterator I = GVSet.begin(); |
| 900 I != GVSet.end(); I++) { | 901 I != GVSet.end(); I++) { |
| 901 const GlobalVariable* GV = *I; | 902 const GlobalVariable* GV = *I; |
| 902 if (GV->hasInitializer()) | 903 if (GV->hasInitializer()) |
| 903 Size = addSizeOfGlobalsInInitializer(GV->getInitializer(), Size); | 904 Size = addSizeOfGlobalsInInitializer(GV->getInitializer(), Size); |
| 904 } | 905 } |
| 905 | 906 |
| 906 return Size; | 907 return Size; |
| 907 } | 908 } |
| 908 | 909 |
| 909 void JITEmitter::startFunction(MachineFunction &F) { | 910 void JITEmitter::startFunction(MachineFunction &F) { |
| 910 DEBUG(errs() << "JIT: Starting CodeGen of Function " | 911 DEBUG(errs() << "JIT: Starting CodeGen of Function " |
| 911 << F.getFunction()->getName() << "\n"); | 912 << F.getFunction()->getName() << "\n"); |
| 912 | 913 |
| 913 uintptr_t ActualSize = 0; | 914 uintptr_t ActualSize = 0; |
| 914 // Set the memory writable, if it's not already | 915 // Set the memory writable, if it's not already |
| 915 MemMgr->setMemoryWritable(); | 916 MemMgr->setMemoryWritable(); |
| 916 if (MemMgr->NeedsExactSize()) { | 917 if (MemMgr->NeedsExactSize()) { |
| 917 DOUT << "JIT: ExactSize\n"; | 918 DEBUG(errs() << "JIT: ExactSize\n"); |
| 918 const TargetInstrInfo* TII = F.getTarget().getInstrInfo(); | 919 const TargetInstrInfo* TII = F.getTarget().getInstrInfo(); |
| 919 MachineJumpTableInfo *MJTI = F.getJumpTableInfo(); | 920 MachineJumpTableInfo *MJTI = F.getJumpTableInfo(); |
| 920 MachineConstantPool *MCP = F.getConstantPool(); | 921 MachineConstantPool *MCP = F.getConstantPool(); |
| 921 | 922 |
| 922 // Ensure the constant pool/jump table info is at least 4-byte aligned. | 923 // Ensure the constant pool/jump table info is at least 4-byte aligned. |
| 923 ActualSize = RoundUpToAlign(ActualSize, 16); | 924 ActualSize = RoundUpToAlign(ActualSize, 16); |
| 924 | 925 |
| 925 // Add the alignment of the constant pool | 926 // Add the alignment of the constant pool |
| 926 ActualSize = RoundUpToAlign(ActualSize, MCP->getConstantPoolAlignment()); | 927 ActualSize = RoundUpToAlign(ActualSize, MCP->getConstantPoolAlignment()); |
| 927 | 928 |
| 928 // Add the constant pool size | 929 // Add the constant pool size |
| 929 ActualSize += GetConstantPoolSizeInBytes(MCP, TheJIT->getTargetData()); | 930 ActualSize += GetConstantPoolSizeInBytes(MCP, TheJIT->getTargetData()); |
| 930 | 931 |
| 931 // Add the aligment of the jump table info | 932 // Add the aligment of the jump table info |
| 932 ActualSize = RoundUpToAlign(ActualSize, MJTI->getAlignment()); | 933 ActualSize = RoundUpToAlign(ActualSize, MJTI->getAlignment()); |
| 933 | 934 |
| 934 // Add the jump table size | 935 // Add the jump table size |
| 935 ActualSize += GetJumpTableSizeInBytes(MJTI); | 936 ActualSize += GetJumpTableSizeInBytes(MJTI); |
| 936 | 937 |
| 937 // Add the alignment for the function | 938 // Add the alignment for the function |
| 938 ActualSize = RoundUpToAlign(ActualSize, | 939 ActualSize = RoundUpToAlign(ActualSize, |
| 939 std::max(F.getFunction()->getAlignment(), 8U)); | 940 std::max(F.getFunction()->getAlignment(), 8U)); |
| 940 | 941 |
| 941 // Add the function size | 942 // Add the function size |
| 942 ActualSize += TII->GetFunctionSizeInBytes(F); | 943 ActualSize += TII->GetFunctionSizeInBytes(F); |
| 943 | 944 |
| 944 DOUT << "JIT: ActualSize before globals " << ActualSize << "\n"; | 945 DEBUG(errs() << "JIT: ActualSize before globals " << ActualSize << "\n"); |
| 945 // Add the size of the globals that will be allocated after this function. | 946 // Add the size of the globals that will be allocated after this function. |
| 946 // These are all the ones referenced from this function that were not | 947 // These are all the ones referenced from this function that were not |
| 947 // previously allocated. | 948 // previously allocated. |
| 948 ActualSize += GetSizeOfGlobalsInBytes(F); | 949 ActualSize += GetSizeOfGlobalsInBytes(F); |
| 949 DOUT << "JIT: ActualSize after globals " << ActualSize << "\n"; | 950 DEBUG(errs() << "JIT: ActualSize after globals " << ActualSize << "\n"); |
| 950 } else if (SizeEstimate > 0) { | 951 } else if (SizeEstimate > 0) { |
| 951 // SizeEstimate will be non-zero on reallocation attempts. | 952 // SizeEstimate will be non-zero on reallocation attempts. |
| 952 ActualSize = SizeEstimate; | 953 ActualSize = SizeEstimate; |
| 953 } | 954 } |
| 954 | 955 |
| 955 BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(), | 956 BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(), |
| 956 ActualSize); | 957 ActualSize); |
| 957 BufferEnd = BufferBegin+ActualSize; | 958 BufferEnd = BufferBegin+ActualSize; |
| 958 | 959 |
| 959 // Ensure the constant pool/jump table info is at least 4-byte aligned. | 960 // Ensure the constant pool/jump table info is at least 4-byte aligned. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 996 NumRelos += Relocations.size(); | 997 NumRelos += Relocations.size(); |
| 997 | 998 |
| 998 // Resolve the relocations to concrete pointers. | 999 // Resolve the relocations to concrete pointers. |
| 999 for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { | 1000 for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { |
| 1000 MachineRelocation &MR = Relocations[i]; | 1001 MachineRelocation &MR = Relocations[i]; |
| 1001 void *ResultPtr = 0; | 1002 void *ResultPtr = 0; |
| 1002 if (!MR.letTargetResolve()) { | 1003 if (!MR.letTargetResolve()) { |
| 1003 if (MR.isExternalSymbol()) { | 1004 if (MR.isExternalSymbol()) { |
| 1004 ResultPtr = TheJIT->getPointerToNamedFunction(MR.getExternalSymbol(), | 1005 ResultPtr = TheJIT->getPointerToNamedFunction(MR.getExternalSymbol(), |
| 1005 false); | 1006 false); |
| 1006 DOUT << "JIT: Map \'" << MR.getExternalSymbol() << "\' to [" | 1007 DEBUG(errs() << "JIT: Map \'" << MR.getExternalSymbol() << "\' to [" |
| 1007 << ResultPtr << "]\n"; | 1008 << ResultPtr << "]\n"); |
| 1008 | 1009 |
| 1009 // If the target REALLY wants a stub for this function, emit it now. | 1010 // If the target REALLY wants a stub for this function, emit it now. |
| 1010 if (!MR.doesntNeedStub()) { | 1011 if (!MR.doesntNeedStub()) { |
| 1011 if (!TheJIT->areDlsymStubsEnabled()) { | 1012 if (!TheJIT->areDlsymStubsEnabled()) { |
| 1012 ResultPtr = Resolver.getExternalFunctionStub(ResultPtr); | 1013 ResultPtr = Resolver.getExternalFunctionStub(ResultPtr); |
| 1013 } else { | 1014 } else { |
| 1014 void *&Stub = ExtFnStubs[MR.getExternalSymbol()]; | 1015 void *&Stub = ExtFnStubs[MR.getExternalSymbol()]; |
| 1015 if (!Stub) { | 1016 if (!Stub) { |
| 1016 Stub = Resolver.getExternalFunctionStub((void *)&Stub); | 1017 Stub = Resolver.getExternalFunctionStub((void *)&Stub); |
| 1017 AddStubToCurrentFunction(Stub); | 1018 AddStubToCurrentFunction(Stub); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1038 | 1039 |
| 1039 MR.setResultPointer(ResultPtr); | 1040 MR.setResultPointer(ResultPtr); |
| 1040 } | 1041 } |
| 1041 | 1042 |
| 1042 // if we are managing the GOT and the relocation wants an index, | 1043 // if we are managing the GOT and the relocation wants an index, |
| 1043 // give it one | 1044 // give it one |
| 1044 if (MR.isGOTRelative() && MemMgr->isManagingGOT()) { | 1045 if (MR.isGOTRelative() && MemMgr->isManagingGOT()) { |
| 1045 unsigned idx = Resolver.getGOTIndexForAddr(ResultPtr); | 1046 unsigned idx = Resolver.getGOTIndexForAddr(ResultPtr); |
| 1046 MR.setGOTIndex(idx); | 1047 MR.setGOTIndex(idx); |
| 1047 if (((void**)MemMgr->getGOTBase())[idx] != ResultPtr) { | 1048 if (((void**)MemMgr->getGOTBase())[idx] != ResultPtr) { |
| 1048 DOUT << "JIT: GOT was out of date for " << ResultPtr | 1049 DEBUG(errs() << "JIT: GOT was out of date for " << ResultPtr |
| 1049 << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] | 1050 << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] |
| 1050 << "\n"; | 1051 << "\n"); |
| 1051 ((void**)MemMgr->getGOTBase())[idx] = ResultPtr; | 1052 ((void**)MemMgr->getGOTBase())[idx] = ResultPtr; |
| 1052 } | 1053 } |
| 1053 } | 1054 } |
| 1054 } | 1055 } |
| 1055 | 1056 |
| 1056 CurFn = 0; | 1057 CurFn = 0; |
| 1057 TheJIT->getJITInfo().relocate(BufferBegin, &Relocations[0], | 1058 TheJIT->getJITInfo().relocate(BufferBegin, &Relocations[0], |
| 1058 Relocations.size(), MemMgr->getGOTBase()); | 1059 Relocations.size(), MemMgr->getGOTBase()); |
| 1059 } | 1060 } |
| 1060 | 1061 |
| 1061 // Update the GOT entry for F to point to the new code. | 1062 // Update the GOT entry for F to point to the new code. |
| 1062 if (MemMgr->isManagingGOT()) { | 1063 if (MemMgr->isManagingGOT()) { |
| 1063 unsigned idx = Resolver.getGOTIndexForAddr((void*)BufferBegin); | 1064 unsigned idx = Resolver.getGOTIndexForAddr((void*)BufferBegin); |
| 1064 if (((void**)MemMgr->getGOTBase())[idx] != (void*)BufferBegin) { | 1065 if (((void**)MemMgr->getGOTBase())[idx] != (void*)BufferBegin) { |
| 1065 DOUT << "JIT: GOT was out of date for " << (void*)BufferBegin | 1066 DEBUG(errs() << "JIT: GOT was out of date for " << (void*)BufferBegin |
| 1066 << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] << "\n"; | 1067 << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] |
| 1068 << "\n"); |
| 1067 ((void**)MemMgr->getGOTBase())[idx] = (void*)BufferBegin; | 1069 ((void**)MemMgr->getGOTBase())[idx] = (void*)BufferBegin; |
| 1068 } | 1070 } |
| 1069 } | 1071 } |
| 1070 | 1072 |
| 1071 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for | 1073 // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for |
| 1072 // global variables that were referenced in the relocations. | 1074 // global variables that were referenced in the relocations. |
| 1073 MemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr); | 1075 MemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr); |
| 1074 | 1076 |
| 1075 if (CurBufferPtr == BufferEnd) { | 1077 if (CurBufferPtr == BufferEnd) { |
| 1076 retryWithMoreMemory(F); | 1078 retryWithMoreMemory(F); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1094 << "] Function: " << F.getFunction()->getName() | 1096 << "] Function: " << F.getFunction()->getName() |
| 1095 << ": " << (FnEnd-FnStart) << " bytes of text, " | 1097 << ": " << (FnEnd-FnStart) << " bytes of text, " |
| 1096 << Relocations.size() << " relocations\n"); | 1098 << Relocations.size() << " relocations\n"); |
| 1097 | 1099 |
| 1098 Relocations.clear(); | 1100 Relocations.clear(); |
| 1099 ConstPoolAddresses.clear(); | 1101 ConstPoolAddresses.clear(); |
| 1100 | 1102 |
| 1101 // Mark code region readable and executable if it's not so already. | 1103 // Mark code region readable and executable if it's not so already. |
| 1102 MemMgr->setMemoryExecutable(); | 1104 MemMgr->setMemoryExecutable(); |
| 1103 | 1105 |
| 1104 #ifndef NDEBUG | 1106 DEBUG( |
| 1105 { | |
| 1106 if (sys::hasDisassembler()) { | 1107 if (sys::hasDisassembler()) { |
| 1107 DOUT << "JIT: Disassembled code:\n"; | 1108 errs() << "JIT: Disassembled code:\n"; |
| 1108 DOUT << sys::disassembleBuffer(FnStart, FnEnd-FnStart, (uintptr_t)FnStart)
; | 1109 errs() << sys::disassembleBuffer(FnStart, FnEnd-FnStart, |
| 1110 (uintptr_t)FnStart); |
| 1109 } else { | 1111 } else { |
| 1110 DOUT << "JIT: Binary code:\n"; | 1112 errs() << "JIT: Binary code:\n"; |
| 1111 DOUT << std::hex; | |
| 1112 uint8_t* q = FnStart; | 1113 uint8_t* q = FnStart; |
| 1113 for (int i = 0; q < FnEnd; q += 4, ++i) { | 1114 for (int i = 0; q < FnEnd; q += 4, ++i) { |
| 1114 if (i == 4) | 1115 if (i == 4) |
| 1115 i = 0; | 1116 i = 0; |
| 1116 if (i == 0) | 1117 if (i == 0) |
| 1117 DOUT << "JIT: " << std::setw(8) << std::setfill('0') | 1118 errs() << "JIT: " << (long)(q - FnStart) << ": "; |
| 1118 << (long)(q - FnStart) << ": "; | |
| 1119 bool Done = false; | 1119 bool Done = false; |
| 1120 for (int j = 3; j >= 0; --j) { | 1120 for (int j = 3; j >= 0; --j) { |
| 1121 if (q + j >= FnEnd) | 1121 if (q + j >= FnEnd) |
| 1122 Done = true; | 1122 Done = true; |
| 1123 else | 1123 else |
| 1124 DOUT << std::setw(2) << std::setfill('0') << (unsigned short)q[j]; | 1124 errs() << (unsigned short)q[j]; |
| 1125 } | 1125 } |
| 1126 if (Done) | 1126 if (Done) |
| 1127 break; | 1127 break; |
| 1128 DOUT << ' '; | 1128 errs() << ' '; |
| 1129 if (i == 3) | 1129 if (i == 3) |
| 1130 DOUT << '\n'; | 1130 errs() << '\n'; |
| 1131 } | 1131 } |
| 1132 DOUT << std::dec; | 1132 errs()<< '\n'; |
| 1133 DOUT<< '\n'; | 1133 } |
| 1134 } | 1134 ); |
| 1135 } | 1135 |
| 1136 #endif | |
| 1137 if (DwarfExceptionHandling || JITEmitDebugInfo) { | 1136 if (DwarfExceptionHandling || JITEmitDebugInfo) { |
| 1138 uintptr_t ActualSize = 0; | 1137 uintptr_t ActualSize = 0; |
| 1139 SavedBufferBegin = BufferBegin; | 1138 SavedBufferBegin = BufferBegin; |
| 1140 SavedBufferEnd = BufferEnd; | 1139 SavedBufferEnd = BufferEnd; |
| 1141 SavedCurBufferPtr = CurBufferPtr; | 1140 SavedCurBufferPtr = CurBufferPtr; |
| 1142 | 1141 |
| 1143 if (MemMgr->NeedsExactSize()) { | 1142 if (MemMgr->NeedsExactSize()) { |
| 1144 ActualSize = DE->GetDwarfTableSizeInBytes(F, *this, FnStart, FnEnd); | 1143 ActualSize = DE->GetDwarfTableSizeInBytes(F, *this, FnStart, FnEnd); |
| 1145 } | 1144 } |
| 1146 | 1145 |
| 1147 BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(), | 1146 BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(), |
| 1148 ActualSize); | 1147 ActualSize); |
| 1149 BufferEnd = BufferBegin+ActualSize; | 1148 BufferEnd = BufferBegin+ActualSize; |
| 1150 uint8_t* EhStart; | 1149 uint8_t *EhStart; |
| 1151 uint8_t* FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd, | 1150 uint8_t *FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd, |
| 1152 EhStart); | 1151 EhStart); |
| 1153 MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr, | 1152 MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr, |
| 1154 FrameRegister); | 1153 FrameRegister); |
| 1155 uint8_t* EhEnd = CurBufferPtr; | 1154 uint8_t *EhEnd = CurBufferPtr; |
| 1156 BufferBegin = SavedBufferBegin; | 1155 BufferBegin = SavedBufferBegin; |
| 1157 BufferEnd = SavedBufferEnd; | 1156 BufferEnd = SavedBufferEnd; |
| 1158 CurBufferPtr = SavedCurBufferPtr; | 1157 CurBufferPtr = SavedCurBufferPtr; |
| 1159 | 1158 |
| 1160 if (DwarfExceptionHandling) { | 1159 if (DwarfExceptionHandling) { |
| 1161 TheJIT->RegisterTable(FrameRegister); | 1160 TheJIT->RegisterTable(FrameRegister); |
| 1162 } | 1161 } |
| 1163 | 1162 |
| 1164 if (JITEmitDebugInfo) { | 1163 if (JITEmitDebugInfo) { |
| 1165 DebugInfo I; | 1164 DebugInfo I; |
| 1166 I.FnStart = FnStart; | 1165 I.FnStart = FnStart; |
| 1167 I.FnEnd = FnEnd; | 1166 I.FnEnd = FnEnd; |
| 1168 I.EhStart = EhStart; | 1167 I.EhStart = EhStart; |
| 1169 I.EhEnd = EhEnd; | 1168 I.EhEnd = EhEnd; |
| 1170 DR->RegisterFunction(F.getFunction(), I); | 1169 DR->RegisterFunction(F.getFunction(), I); |
| 1171 } | 1170 } |
| 1172 } | 1171 } |
| 1173 | 1172 |
| 1174 if (MMI) | 1173 if (MMI) |
| 1175 MMI->EndFunction(); | 1174 MMI->EndFunction(); |
| 1176 | 1175 |
| 1177 return false; | 1176 return false; |
| 1178 } | 1177 } |
| 1179 | 1178 |
| 1180 void JITEmitter::retryWithMoreMemory(MachineFunction &F) { | 1179 void JITEmitter::retryWithMoreMemory(MachineFunction &F) { |
| 1181 DOUT << "JIT: Ran out of space for native code. Reattempting.\n"; | 1180 DEBUG(errs() << "JIT: Ran out of space for native code. Reattempting.\n"); |
| 1182 Relocations.clear(); // Clear the old relocations or we'll reapply them. | 1181 Relocations.clear(); // Clear the old relocations or we'll reapply them. |
| 1183 ConstPoolAddresses.clear(); | 1182 ConstPoolAddresses.clear(); |
| 1184 ++NumRetries; | 1183 ++NumRetries; |
| 1185 deallocateMemForFunction(F.getFunction()); | 1184 deallocateMemForFunction(F.getFunction()); |
| 1186 // Try again with at least twice as much free space. | 1185 // Try again with at least twice as much free space. |
| 1187 SizeEstimate = (uintptr_t)(2 * (BufferEnd - BufferBegin)); | 1186 SizeEstimate = (uintptr_t)(2 * (BufferEnd - BufferBegin)); |
| 1188 } | 1187 } |
| 1189 | 1188 |
| 1190 /// deallocateMemForFunction - Deallocate all memory for the specified | 1189 /// deallocateMemForFunction - Deallocate all memory for the specified |
| 1191 /// function body. Also drop any references the function has to stubs. | 1190 /// function body. Also drop any references the function has to stubs. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1212 if (StubFnRefs.count(Stub) == 0) | 1211 if (StubFnRefs.count(Stub) == 0) |
| 1213 continue; | 1212 continue; |
| 1214 | 1213 |
| 1215 SmallPtrSet<const Function *, 1> &FnRefs = StubFnRefs[Stub]; | 1214 SmallPtrSet<const Function *, 1> &FnRefs = StubFnRefs[Stub]; |
| 1216 FnRefs.erase(F); | 1215 FnRefs.erase(F); |
| 1217 | 1216 |
| 1218 // If this function was the last reference to the stub, invalidate the stub | 1217 // If this function was the last reference to the stub, invalidate the stub |
| 1219 // in the JITResolver. Were there a memory manager deallocateStub routine, | 1218 // in the JITResolver. Were there a memory manager deallocateStub routine, |
| 1220 // we could call that at this point too. | 1219 // we could call that at this point too. |
| 1221 if (FnRefs.empty()) { | 1220 if (FnRefs.empty()) { |
| 1222 DOUT << "\nJIT: Invalidated Stub at [" << Stub << "]\n"; | 1221 DEBUG(errs() << "\nJIT: Invalidated Stub at [" << Stub << "]\n"); |
| 1223 StubFnRefs.erase(Stub); | 1222 StubFnRefs.erase(Stub); |
| 1224 | 1223 |
| 1225 // Invalidate the stub. If it is a GV stub, update the JIT's global | 1224 // Invalidate the stub. If it is a GV stub, update the JIT's global |
| 1226 // mapping for that GV to zero, otherwise, search the string map of | 1225 // mapping for that GV to zero, otherwise, search the string map of |
| 1227 // external function names to stubs and remove the entry for this stub. | 1226 // external function names to stubs and remove the entry for this stub. |
| 1228 GlobalValue *GV = Resolver.invalidateStub(Stub); | 1227 GlobalValue *GV = Resolver.invalidateStub(Stub); |
| 1229 if (GV) { | 1228 if (GV) { |
| 1230 TheJIT->updateGlobalMapping(GV, 0); | 1229 TheJIT->updateGlobalMapping(GV, 0); |
| 1231 } else { | 1230 } else { |
| 1232 for (StringMapIterator<void*> i = ExtFnStubs.begin(), | 1231 for (StringMapIterator<void*> i = ExtFnStubs.begin(), |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1267 const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants(); | 1266 const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants(); |
| 1268 if (Constants.empty()) return; | 1267 if (Constants.empty()) return; |
| 1269 | 1268 |
| 1270 unsigned Size = GetConstantPoolSizeInBytes(MCP, TheJIT->getTargetData()); | 1269 unsigned Size = GetConstantPoolSizeInBytes(MCP, TheJIT->getTargetData()); |
| 1271 unsigned Align = MCP->getConstantPoolAlignment(); | 1270 unsigned Align = MCP->getConstantPoolAlignment(); |
| 1272 ConstantPoolBase = allocateSpace(Size, Align); | 1271 ConstantPoolBase = allocateSpace(Size, Align); |
| 1273 ConstantPool = MCP; | 1272 ConstantPool = MCP; |
| 1274 | 1273 |
| 1275 if (ConstantPoolBase == 0) return; // Buffer overflow. | 1274 if (ConstantPoolBase == 0) return; // Buffer overflow. |
| 1276 | 1275 |
| 1277 DOUT << "JIT: Emitted constant pool at [" << ConstantPoolBase | 1276 DEBUG(errs() << "JIT: Emitted constant pool at [" << ConstantPoolBase |
| 1278 << "] (size: " << Size << ", alignment: " << Align << ")\n"; | 1277 << "] (size: " << Size << ", alignment: " << Align << ")\n"); |
| 1279 | 1278 |
| 1280 // Initialize the memory for all of the constant pool entries. | 1279 // Initialize the memory for all of the constant pool entries. |
| 1281 unsigned Offset = 0; | 1280 unsigned Offset = 0; |
| 1282 for (unsigned i = 0, e = Constants.size(); i != e; ++i) { | 1281 for (unsigned i = 0, e = Constants.size(); i != e; ++i) { |
| 1283 MachineConstantPoolEntry CPE = Constants[i]; | 1282 MachineConstantPoolEntry CPE = Constants[i]; |
| 1284 unsigned AlignMask = CPE.getAlignment() - 1; | 1283 unsigned AlignMask = CPE.getAlignment() - 1; |
| 1285 Offset = (Offset + AlignMask) & ~AlignMask; | 1284 Offset = (Offset + AlignMask) & ~AlignMask; |
| 1286 | 1285 |
| 1287 uintptr_t CAddr = (uintptr_t)ConstantPoolBase + Offset; | 1286 uintptr_t CAddr = (uintptr_t)ConstantPoolBase + Offset; |
| 1288 ConstPoolAddresses.push_back(CAddr); | 1287 ConstPoolAddresses.push_back(CAddr); |
| 1289 if (CPE.isMachineConstantPoolEntry()) { | 1288 if (CPE.isMachineConstantPoolEntry()) { |
| 1290 // FIXME: add support to lower machine constant pool values into bytes! | 1289 // FIXME: add support to lower machine constant pool values into bytes! |
| 1291 llvm_report_error("Initialize memory with machine specific constant pool" | 1290 llvm_report_error("Initialize memory with machine specific constant pool" |
| 1292 "entry has not been implemented!"); | 1291 "entry has not been implemented!"); |
| 1293 } | 1292 } |
| 1294 TheJIT->InitializeMemory(CPE.Val.ConstVal, (void*)CAddr); | 1293 TheJIT->InitializeMemory(CPE.Val.ConstVal, (void*)CAddr); |
| 1295 DOUT << "JIT: CP" << i << " at [0x" | 1294 DEBUG(errs() << "JIT: CP" << i << " at [0x"; |
| 1296 << std::hex << CAddr << std::dec << "]\n"; | 1295 errs().write_hex(CAddr) << "]\n"); |
| 1297 | 1296 |
| 1298 const Type *Ty = CPE.Val.ConstVal->getType(); | 1297 const Type *Ty = CPE.Val.ConstVal->getType(); |
| 1299 Offset += TheJIT->getTargetData()->getTypeAllocSize(Ty); | 1298 Offset += TheJIT->getTargetData()->getTypeAllocSize(Ty); |
| 1300 } | 1299 } |
| 1301 } | 1300 } |
| 1302 | 1301 |
| 1303 void JITEmitter::initJumpTableInfo(MachineJumpTableInfo *MJTI) { | 1302 void JITEmitter::initJumpTableInfo(MachineJumpTableInfo *MJTI) { |
| 1304 if (TheJIT->getJITInfo().hasCustomJumpTables()) | 1303 if (TheJIT->getJITInfo().hasCustomJumpTables()) |
| 1305 return; | 1304 return; |
| 1306 | 1305 |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1559 // retranslated next time it is used. | 1558 // retranslated next time it is used. |
| 1560 void *OldPtr = updateGlobalMapping(F, 0); | 1559 void *OldPtr = updateGlobalMapping(F, 0); |
| 1561 | 1560 |
| 1562 if (OldPtr) | 1561 if (OldPtr) |
| 1563 TheJIT->NotifyFreeingMachineCode(*F, OldPtr); | 1562 TheJIT->NotifyFreeingMachineCode(*F, OldPtr); |
| 1564 | 1563 |
| 1565 // Free the actual memory for the function body and related stuff. | 1564 // Free the actual memory for the function body and related stuff. |
| 1566 assert(isa<JITEmitter>(JCE) && "Unexpected MCE?"); | 1565 assert(isa<JITEmitter>(JCE) && "Unexpected MCE?"); |
| 1567 cast<JITEmitter>(JCE)->deallocateMemForFunction(F); | 1566 cast<JITEmitter>(JCE)->deallocateMemForFunction(F); |
| 1568 } | 1567 } |
| LEFT | RIGHT |