bool ARMCodeEmitter::runOnMachineFunction(MachineFunction &MF) { assert((MF.getTarget().getRelocationModel() != Reloc::Default || MF.getTarget().getRelocationModel() != Reloc::Static) && "JIT relocation model must be set to static or default!"); JTI = ((ARMTargetMachine&)MF.getTarget()).getJITInfo(); II = ((ARMTargetMachine&)MF.getTarget()).getInstrInfo(); TD = ((ARMTargetMachine&)MF.getTarget()).getTargetData(); Subtarget = &TM.getSubtarget<ARMSubtarget>(); MCPEs = &MF.getConstantPool()->getConstants(); MJTEs = 0; if (MF.getJumpTableInfo()) MJTEs = &MF.getJumpTableInfo()->getJumpTables(); IsPIC = TM.getRelocationModel() == Reloc::PIC_; JTI->Initialize(MF, IsPIC); MCE.setModuleInfo(&getAnalysis<MachineModuleInfo>()); do { DEBUG(errs() << "JITTing function '" << MF.getFunction()->getName() << "'\n"); MCE.startFunction(MF); for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); MBB != E; ++MBB) { MCE.StartMachineBasicBlock(MBB); for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); I != E; ++I) emitInstruction(*I); } } while (MCE.finishFunction(MF)); return false; }
bool MipsCodeEmitter::runOnMachineFunction(MachineFunction &MF) { JTI = ((MipsTargetMachine&) MF.getTarget()).getJITInfo(); II = ((const MipsTargetMachine&) MF.getTarget()).getInstrInfo(); TD = ((const MipsTargetMachine&) MF.getTarget()).getDataLayout(); Subtarget = &TM.getSubtarget<MipsSubtarget> (); MCPEs = &MF.getConstantPool()->getConstants(); MJTEs = 0; if (MF.getJumpTableInfo()) MJTEs = &MF.getJumpTableInfo()->getJumpTables(); JTI->Initialize(MF, IsPIC, Subtarget->isLittle()); MCE.setModuleInfo(&getAnalysis<MachineModuleInfo> ()); do { DEBUG(errs() << "JITTing function '" << MF.getName() << "'\n"); MCE.startFunction(MF); for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); MBB != E; ++MBB){ MCE.StartMachineBasicBlock(MBB); for (MachineBasicBlock::instr_iterator I = MBB->instr_begin(), E = MBB->instr_end(); I != E; ++I) emitInstruction(*I); } } while (MCE.finishFunction(MF)); return false; }
void MIRPrinter::print(const MachineFunction &MF) { initRegisterMaskIds(MF); yaml::MachineFunction YamlMF; YamlMF.Name = MF.getName(); YamlMF.Alignment = MF.getAlignment(); YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice(); YamlMF.HasInlineAsm = MF.hasInlineAsm(); convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo()); ModuleSlotTracker MST(MF.getFunction()->getParent()); MST.incorporateFunction(*MF.getFunction()); convert(MST, YamlMF.FrameInfo, *MF.getFrameInfo()); convertStackObjects(YamlMF, *MF.getFrameInfo(), MF.getMMI(), MST, MF.getSubtarget().getRegisterInfo()); if (const auto *ConstantPool = MF.getConstantPool()) convert(YamlMF, *ConstantPool); if (const auto *JumpTableInfo = MF.getJumpTableInfo()) convert(MST, YamlMF.JumpTableInfo, *JumpTableInfo); raw_string_ostream StrOS(YamlMF.Body.Value.Value); bool IsNewlineNeeded = false; for (const auto &MBB : MF) { if (IsNewlineNeeded) StrOS << "\n"; MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping) .print(MBB); IsNewlineNeeded = true; } StrOS.flush(); yaml::Output Out(OS); Out << YamlMF; }
void JITEmitter::startFunction(MachineFunction &F) { DEBUG(dbgs() << "JIT: Starting CodeGen of Function " << F.getName() << "\n"); uintptr_t ActualSize = 0; // Set the memory writable, if it's not already MemMgr->setMemoryWritable(); if (SizeEstimate > 0) { // SizeEstimate will be non-zero on reallocation attempts. ActualSize = SizeEstimate; } BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(), ActualSize); BufferEnd = BufferBegin+ActualSize; EmittedFunctions[F.getFunction()].FunctionBody = BufferBegin; // Ensure the constant pool/jump table info is at least 4-byte aligned. emitAlignment(16); emitConstantPool(F.getConstantPool()); if (MachineJumpTableInfo *MJTI = F.getJumpTableInfo()) initJumpTableInfo(MJTI); // About to start emitting the machine code for the function. emitAlignment(std::max(F.getFunction()->getAlignment(), 8U)); TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr); EmittedFunctions[F.getFunction()].Code = CurBufferPtr; MBBLocations.clear(); EmissionDetails.MF = &F; EmissionDetails.LineStarts.clear(); }
void MIRPrinter::print(const MachineFunction &MF) { initRegisterMaskIds(MF); yaml::MachineFunction YamlMF; YamlMF.Name = MF.getName(); YamlMF.Alignment = MF.getAlignment(); YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice(); YamlMF.HasInlineAsm = MF.hasInlineAsm(); convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo()); ModuleSlotTracker MST(MF.getFunction()->getParent()); MST.incorporateFunction(*MF.getFunction()); convert(MST, YamlMF.FrameInfo, *MF.getFrameInfo()); convertStackObjects(YamlMF, *MF.getFrameInfo(), MF.getSubtarget().getRegisterInfo()); if (const auto *ConstantPool = MF.getConstantPool()) convert(YamlMF, *ConstantPool); if (const auto *JumpTableInfo = MF.getJumpTableInfo()) convert(MST, YamlMF.JumpTableInfo, *JumpTableInfo); for (const auto &MBB : MF) { yaml::MachineBasicBlock YamlMBB; convert(MST, YamlMBB, MBB); YamlMF.BasicBlocks.push_back(YamlMBB); } yaml::Output Out(OS); Out << YamlMF; }
/// runOnMachineFunction - This uses the printMachineInstruction() /// method to print assembly for each instruction. /// bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) { this->MF = &MF; SetupMachineFunction(MF); O << "\n\n"; // Print out constants referenced by the function EmitConstantPool(MF.getConstantPool()); // Print out jump tables referenced by the function EmitJumpTableInfo(MF.getJumpTableInfo(), MF); // Print out labels for the function. const Function *F = MF.getFunction(); OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); EmitAlignment(MF.getAlignment(), F); switch (F->getLinkage()) { default: llvm_unreachable("Unknown linkage type!"); case Function::InternalLinkage: // Symbols default to internal. case Function::PrivateLinkage: case Function::LinkerPrivateLinkage: break; case Function::ExternalLinkage: O << "\t.globl " << CurrentFnName << "\n"; break; case Function::WeakAnyLinkage: case Function::WeakODRLinkage: case Function::LinkOnceAnyLinkage: case Function::LinkOnceODRLinkage: O << TAI->getWeakRefDirective() << CurrentFnName << "\n"; break; } printVisibility(CurrentFnName, F->getVisibility()); O << "\t.ent " << CurrentFnName << "\n"; O << CurrentFnName << ":\n"; // Print out code for the function. for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E; ++I) { if (I != MF.begin()) { printBasicBlockLabel(I, true, true); O << '\n'; } for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); II != E; ++II) { // Print the assembly for the instruction. ++EmittedInsts; printInstruction(II); } } O << "\t.end " << CurrentFnName << "\n"; // We didn't modify anything. return false; }
void JITEmitter::startFunction(MachineFunction &F) { uintptr_t ActualSize = 0; if (MemMgr->NeedsExactSize()) { const TargetInstrInfo* TII = F.getTarget().getInstrInfo(); MachineJumpTableInfo *MJTI = F.getJumpTableInfo(); MachineConstantPool *MCP = F.getConstantPool(); // Ensure the constant pool/jump table info is at least 4-byte aligned. ActualSize = RoundUpToAlign(ActualSize, 16); // Add the alignment of the constant pool ActualSize = RoundUpToAlign(ActualSize, 1 << MCP->getConstantPoolAlignment()); // Add the constant pool size ActualSize += GetConstantPoolSizeInBytes(MCP); // Add the aligment of the jump table info ActualSize = RoundUpToAlign(ActualSize, MJTI->getAlignment()); // Add the jump table size ActualSize += GetJumpTableSizeInBytes(MJTI); // Add the alignment for the function ActualSize = RoundUpToAlign(ActualSize, std::max(F.getFunction()->getAlignment(), 8U)); // Add the function size ActualSize += TII->GetFunctionSizeInBytes(F); } BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(), ActualSize); BufferEnd = BufferBegin+ActualSize; // Ensure the constant pool/jump table info is at least 4-byte aligned. emitAlignment(16); emitConstantPool(F.getConstantPool()); initJumpTableInfo(F.getJumpTableInfo()); // About to start emitting the machine code for the function. emitAlignment(std::max(F.getFunction()->getAlignment(), 8U)); TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr); MBBLocations.clear(); }
/// runOnMachineFunction - This uses the printMachineInstruction() /// method to print assembly for each instruction. /// bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) { SetupMachineFunction(MF); O << "\n\n"; // Print out constants referenced by the function EmitConstantPool(MF.getConstantPool()); // Print out jump tables referenced by the function EmitJumpTableInfo(MF.getJumpTableInfo(), MF); // Print out labels for the function. const Function *F = MF.getFunction(); SwitchToSection(TAI->SectionForGlobal(F)); EmitAlignment(4, F); switch (F->getLinkage()) { default: assert(0 && "Unknown linkage type!"); case Function::InternalLinkage: // Symbols default to internal. case Function::PrivateLinkage: break; case Function::ExternalLinkage: O << "\t.globl " << CurrentFnName << "\n"; break; case Function::WeakLinkage: case Function::LinkOnceLinkage: O << TAI->getWeakRefDirective() << CurrentFnName << "\n"; break; } printVisibility(CurrentFnName, F->getVisibility()); O << "\t.ent " << CurrentFnName << "\n"; O << CurrentFnName << ":\n"; // Print out code for the function. for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E; ++I) { if (I != MF.begin()) { printBasicBlockLabel(I, true, true); O << '\n'; } for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); II != E; ++II) { // Print the assembly for the instruction. ++EmittedInsts; if (!printInstruction(II)) { assert(0 && "Unhandled instruction in asm writer!"); abort(); } } } O << "\t.end " << CurrentFnName << "\n"; // We didn't modify anything. return false; }
/// finishFunction - This callback is invoked after the function is completely /// finished. bool MachOCodeEmitter::finishFunction(MachineFunction &MF) { // Get the Mach-O Section that this function belongs in. MachOWriter::MachOSection *MOS = MOW.getTextSection(); // Get a symbol for the function to add to the symbol table // FIXME: it seems like we should call something like AddSymbolToSection // in startFunction rather than changing the section size and symbol n_value // here. const GlobalValue *FuncV = MF.getFunction(); MachOSym FnSym(FuncV, MOW.Mang->getValueName(FuncV), MOS->Index, TM); FnSym.n_value = MOS->size; MOS->size = CurBufferPtr - BufferBegin; // Emit constant pool to appropriate section(s) emitConstantPool(MF.getConstantPool()); // Emit jump tables to appropriate section emitJumpTables(MF.getJumpTableInfo()); // If we have emitted any relocations to function-specific objects such as // basic blocks, constant pools entries, or jump tables, record their // addresses now so that we can rewrite them with the correct addresses // later. for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { MachineRelocation &MR = Relocations[i]; intptr_t Addr; if (MR.isBasicBlock()) { Addr = getMachineBasicBlockAddress(MR.getBasicBlock()); MR.setConstantVal(MOS->Index); MR.setResultPointer((void*)Addr); } else if (MR.isJumpTableIndex()) { Addr = getJumpTableEntryAddress(MR.getJumpTableIndex()); MR.setConstantVal(MOW.getJumpTableSection()->Index); MR.setResultPointer((void*)Addr); } else if (MR.isConstantPoolIndex()) { Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex()); MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]); MR.setResultPointer((void*)Addr); } else if (MR.isGlobalValue()) { // FIXME: This should be a set or something that uniques MOW.PendingGlobals.push_back(MR.getGlobalValue()); } else { assert(0 && "Unhandled relocation type"); } MOS->Relocations.push_back(MR); } Relocations.clear(); // Finally, add it to the symtab. MOW.SymbolTable.push_back(FnSym); return false; }
// Align all targets of indirect branches on bundle size. Used only if target // is NaCl. void MipsAsmPrinter::NaClAlignIndirectJumpTargets(MachineFunction &MF) { // Align all blocks that are jumped to through jump table. if (MachineJumpTableInfo *JtInfo = MF.getJumpTableInfo()) { const std::vector<MachineJumpTableEntry> &JT = JtInfo->getJumpTables(); for (unsigned I = 0; I < JT.size(); ++I) { const std::vector<MachineBasicBlock*> &MBBs = JT[I].MBBs; for (unsigned J = 0; J < MBBs.size(); ++J) MBBs[J]->setAlignment(MIPS_NACL_BUNDLE_ALIGN); } } // If basic block address is taken, block can be target of indirect branch. for (auto &MBB : MF) { if (MBB.hasAddressTaken()) MBB.setAlignment(MIPS_NACL_BUNDLE_ALIGN); } }
void MIRPrinter::print(const MachineFunction &MF) { initRegisterMaskIds(MF); yaml::MachineFunction YamlMF; YamlMF.Name = MF.getName(); YamlMF.Alignment = MF.getAlignment(); YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice(); YamlMF.HasWinCFI = MF.hasWinCFI(); YamlMF.Legalized = MF.getProperties().hasProperty( MachineFunctionProperties::Property::Legalized); YamlMF.RegBankSelected = MF.getProperties().hasProperty( MachineFunctionProperties::Property::RegBankSelected); YamlMF.Selected = MF.getProperties().hasProperty( MachineFunctionProperties::Property::Selected); YamlMF.FailedISel = MF.getProperties().hasProperty( MachineFunctionProperties::Property::FailedISel); convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo()); ModuleSlotTracker MST(MF.getFunction().getParent()); MST.incorporateFunction(MF.getFunction()); convert(MST, YamlMF.FrameInfo, MF.getFrameInfo()); convertStackObjects(YamlMF, MF, MST); if (const auto *ConstantPool = MF.getConstantPool()) convert(YamlMF, *ConstantPool); if (const auto *JumpTableInfo = MF.getJumpTableInfo()) convert(MST, YamlMF.JumpTableInfo, *JumpTableInfo); raw_string_ostream StrOS(YamlMF.Body.Value.Value); bool IsNewlineNeeded = false; for (const auto &MBB : MF) { if (IsNewlineNeeded) StrOS << "\n"; MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping) .print(MBB); IsNewlineNeeded = true; } StrOS.flush(); yaml::Output Out(OS); if (!SimplifyMIR) Out.setWriteDefaultValues(true); Out << YamlMF; }
/// runOnMachineFunction - This uses the printMachineInstruction() /// method to print assembly for each instruction. /// bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) { SetupMachineFunction(MF); O << "\n\n"; // Print out constants referenced by the function EmitConstantPool(MF.getConstantPool()); // Print out labels for the function. const Function *F = MF.getFunction(); unsigned CC = F->getCallingConv(); // Populate function information map. Actually, We don't want to populate // non-stdcall or non-fastcall functions' information right now. if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall) FunctionInfoMap[F] = *MF.getInfo<X86MachineFunctionInfo>(); decorateName(CurrentFnName, F); SwitchToTextSection("_text", F); unsigned FnAlign = 4; if (F->hasFnAttr(Attribute::OptimizeForSize)) FnAlign = 1; switch (F->getLinkage()) { default: assert(0 && "Unsupported linkage type!"); case Function::PrivateLinkage: case Function::InternalLinkage: EmitAlignment(FnAlign); break; case Function::DLLExportLinkage: DLLExportedFns.insert(CurrentFnName); //FALLS THROUGH case Function::ExternalLinkage: O << "\tpublic " << CurrentFnName << "\n"; EmitAlignment(FnAlign); break; } O << CurrentFnName << "\tproc near\n"; // Print out code for the function. for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E; ++I) { // Print a label for the basic block if there are any predecessors. if (!I->pred_empty()) { printBasicBlockLabel(I, true, true); O << '\n'; } for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); II != E; ++II) { // Print the assembly for the instruction. printMachineInstruction(II); } } // Print out jump tables referenced by the function. EmitJumpTableInfo(MF.getJumpTableInfo(), MF); O << CurrentFnName << "\tendp\n"; O.flush(); // We didn't modify anything. return false; }
bool JITEmitter::finishFunction(MachineFunction &F) { if (CurBufferPtr == BufferEnd) { // We must call endFunctionBody before retrying, because // deallocateMemForFunction requires it. MemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr); retryWithMoreMemory(F); return true; } if (MachineJumpTableInfo *MJTI = F.getJumpTableInfo()) emitJumpTableInfo(MJTI); // FnStart is the start of the text, not the start of the constant pool and // other per-function data. uint8_t *FnStart = (uint8_t *)TheJIT->getPointerToGlobalIfAvailable(F.getFunction()); // FnEnd is the end of the function's machine code. uint8_t *FnEnd = CurBufferPtr; if (!Relocations.empty()) { CurFn = F.getFunction(); NumRelos += Relocations.size(); // Resolve the relocations to concrete pointers. for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { MachineRelocation &MR = Relocations[i]; void *ResultPtr = 0; if (!MR.letTargetResolve()) { if (MR.isExternalSymbol()) { ResultPtr = TheJIT->getPointerToNamedFunction(MR.getExternalSymbol(), false); DEBUG(dbgs() << "JIT: Map \'" << MR.getExternalSymbol() << "\' to [" << ResultPtr << "]\n"); // If the target REALLY wants a stub for this function, emit it now. if (MR.mayNeedFarStub()) { ResultPtr = Resolver.getExternalFunctionStub(ResultPtr); } } else if (MR.isGlobalValue()) { ResultPtr = getPointerToGlobal(MR.getGlobalValue(), BufferBegin+MR.getMachineCodeOffset(), MR.mayNeedFarStub()); } else if (MR.isIndirectSymbol()) { ResultPtr = getPointerToGVIndirectSym( MR.getGlobalValue(), BufferBegin+MR.getMachineCodeOffset()); } else if (MR.isBasicBlock()) { ResultPtr = (void*)getMachineBasicBlockAddress(MR.getBasicBlock()); } else if (MR.isConstantPoolIndex()) { ResultPtr = (void*)getConstantPoolEntryAddress(MR.getConstantPoolIndex()); } else { assert(MR.isJumpTableIndex()); ResultPtr=(void*)getJumpTableEntryAddress(MR.getJumpTableIndex()); } MR.setResultPointer(ResultPtr); } // if we are managing the GOT and the relocation wants an index, // give it one if (MR.isGOTRelative() && MemMgr->isManagingGOT()) { unsigned idx = Resolver.getGOTIndexForAddr(ResultPtr); MR.setGOTIndex(idx); if (((void**)MemMgr->getGOTBase())[idx] != ResultPtr) { DEBUG(dbgs() << "JIT: GOT was out of date for " << ResultPtr << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] << "\n"); ((void**)MemMgr->getGOTBase())[idx] = ResultPtr; } } } CurFn = 0; TheJIT->getJITInfo().relocate(BufferBegin, &Relocations[0], Relocations.size(), MemMgr->getGOTBase()); } // Update the GOT entry for F to point to the new code. if (MemMgr->isManagingGOT()) { unsigned idx = Resolver.getGOTIndexForAddr((void*)BufferBegin); if (((void**)MemMgr->getGOTBase())[idx] != (void*)BufferBegin) { DEBUG(dbgs() << "JIT: GOT was out of date for " << (void*)BufferBegin << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] << "\n"); ((void**)MemMgr->getGOTBase())[idx] = (void*)BufferBegin; } } // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for // global variables that were referenced in the relocations. MemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr); if (CurBufferPtr == BufferEnd) { retryWithMoreMemory(F); return true; } else { // Now that we've succeeded in emitting the function, reset the // SizeEstimate back down to zero. SizeEstimate = 0; } BufferBegin = CurBufferPtr = 0; NumBytes += FnEnd-FnStart; // Invalidate the icache if necessary. sys::Memory::InvalidateInstructionCache(FnStart, FnEnd-FnStart); TheJIT->NotifyFunctionEmitted(*F.getFunction(), FnStart, FnEnd-FnStart, EmissionDetails); // Reset the previous debug location. PrevDL = DebugLoc(); DEBUG(dbgs() << "JIT: Finished CodeGen of [" << (void*)FnStart << "] Function: " << F.getName() << ": " << (FnEnd-FnStart) << " bytes of text, " << Relocations.size() << " relocations\n"); Relocations.clear(); ConstPoolAddresses.clear(); // Mark code region readable and executable if it's not so already. MemMgr->setMemoryExecutable(); DEBUG({ if (sys::hasDisassembler()) { dbgs() << "JIT: Disassembled code:\n"; dbgs() << sys::disassembleBuffer(FnStart, FnEnd-FnStart, (uintptr_t)FnStart); } else { dbgs() << "JIT: Binary code:\n"; uint8_t* q = FnStart; for (int i = 0; q < FnEnd; q += 4, ++i) { if (i == 4) i = 0; if (i == 0) dbgs() << "JIT: " << (long)(q - FnStart) << ": "; bool Done = false; for (int j = 3; j >= 0; --j) { if (q + j >= FnEnd) Done = true; else dbgs() << (unsigned short)q[j]; } if (Done) break; dbgs() << ' '; if (i == 3) dbgs() << '\n'; } dbgs()<< '\n'; } });
bool JITEmitter::finishFunction(MachineFunction &F) { if (CurBufferPtr == BufferEnd) { // FIXME: Allocate more space, then try again. cerr << "JIT: Ran out of space for generated machine code!\n"; abort(); } emitJumpTableInfo(F.getJumpTableInfo()); // FnStart is the start of the text, not the start of the constant pool and // other per-function data. unsigned char *FnStart = (unsigned char *)TheJIT->getPointerToGlobalIfAvailable(F.getFunction()); unsigned char *FnEnd = CurBufferPtr; MemMgr->endFunctionBody(F.getFunction(), BufferBegin, FnEnd); NumBytes += FnEnd-FnStart; if (!Relocations.empty()) { NumRelos += Relocations.size(); // Resolve the relocations to concrete pointers. for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { MachineRelocation &MR = Relocations[i]; void *ResultPtr; if (MR.isString()) { ResultPtr = TheJIT->getPointerToNamedFunction(MR.getString()); // If the target REALLY wants a stub for this function, emit it now. if (!MR.doesntNeedStub()) ResultPtr = Resolver.getExternalFunctionStub(ResultPtr); } else if (MR.isGlobalValue()) { ResultPtr = getPointerToGlobal(MR.getGlobalValue(), BufferBegin+MR.getMachineCodeOffset(), MR.doesntNeedStub()); } else if (MR.isGlobalValueLazyPtr()) { ResultPtr = getPointerToGVLazyPtr(MR.getGlobalValue(), BufferBegin+MR.getMachineCodeOffset(), MR.doesntNeedStub()); } else if (MR.isBasicBlock()) { ResultPtr = (void*)getMachineBasicBlockAddress(MR.getBasicBlock()); } else if (MR.isConstantPoolIndex()) { ResultPtr=(void*)getConstantPoolEntryAddress(MR.getConstantPoolIndex()); } else { assert(MR.isJumpTableIndex()); ResultPtr=(void*)getJumpTableEntryAddress(MR.getJumpTableIndex()); } MR.setResultPointer(ResultPtr); // if we are managing the GOT and the relocation wants an index, // give it one if (MR.isGOTRelative() && MemMgr->isManagingGOT()) { unsigned idx = Resolver.getGOTIndexForAddr(ResultPtr); MR.setGOTIndex(idx); if (((void**)MemMgr->getGOTBase())[idx] != ResultPtr) { DOUT << "GOT was out of date for " << ResultPtr << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] << "\n"; ((void**)MemMgr->getGOTBase())[idx] = ResultPtr; } } } TheJIT->getJITInfo().relocate(BufferBegin, &Relocations[0], Relocations.size(), MemMgr->getGOTBase()); } // Update the GOT entry for F to point to the new code. if (MemMgr->isManagingGOT()) { unsigned idx = Resolver.getGOTIndexForAddr((void*)BufferBegin); if (((void**)MemMgr->getGOTBase())[idx] != (void*)BufferBegin) { DOUT << "GOT was out of date for " << (void*)BufferBegin << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] << "\n"; ((void**)MemMgr->getGOTBase())[idx] = (void*)BufferBegin; } } // Invalidate the icache if necessary. synchronizeICache(FnStart, FnEnd-FnStart); // Add it to the JIT symbol table if the host wants it. AddFunctionToSymbolTable(F.getFunction()->getNameStart(), FnStart, FnEnd-FnStart); DOUT << "JIT: Finished CodeGen of [" << (void*)FnStart << "] Function: " << F.getFunction()->getName() << ": " << (FnEnd-FnStart) << " bytes of text, " << Relocations.size() << " relocations\n"; Relocations.clear(); #ifndef NDEBUG if (sys::hasDisassembler()) DOUT << "Disassembled code:\n" << sys::disassembleBuffer(FnStart, FnEnd-FnStart, (uintptr_t)FnStart); #endif if (ExceptionHandling) { uintptr_t ActualSize = 0; SavedBufferBegin = BufferBegin; SavedBufferEnd = BufferEnd; SavedCurBufferPtr = CurBufferPtr; if (MemMgr->NeedsExactSize()) { ActualSize = DE->GetDwarfTableSizeInBytes(F, *this, FnStart, FnEnd); } BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(), ActualSize); BufferEnd = BufferBegin+ActualSize; unsigned char* FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd); MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr, FrameRegister); BufferBegin = SavedBufferBegin; BufferEnd = SavedBufferEnd; CurBufferPtr = SavedCurBufferPtr; TheJIT->RegisterTable(FrameRegister); } MMI->EndFunction(); return false; }