X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FELFCodeEmitter.cpp;h=3fb087c5ea8b8c5bc096a45f6d5c2c044f4a74fe;hb=bcb8c6d09ee426e0f774e3412912f6ae9e5f78dd;hp=57b75a37f2317738efa5a1468fd2325cff720bb0;hpb=45f5d6417bfe9941ba58777865e00098ffff5793;p=oota-llvm.git diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp index 57b75a37f23..3fb087c5ea8 100644 --- a/lib/CodeGen/ELFCodeEmitter.cpp +++ b/lib/CodeGen/ELFCodeEmitter.cpp @@ -17,12 +17,16 @@ #include "llvm/Function.h" #include "llvm/CodeGen/BinaryObject.h" #include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineRelocation.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetELFWriterInfo.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" //===----------------------------------------------------------------------===// // ELFCodeEmitter Implementation @@ -33,81 +37,76 @@ namespace llvm { /// startFunction - This callback is invoked when a new machine function is /// about to be emitted. void ELFCodeEmitter::startFunction(MachineFunction &MF) { - // Get the ELF Section that this function belongs in. - ES = &EW.getTextSection(); + DEBUG(dbgs() << "processing function: " + << MF.getFunction()->getName() << "\n"); - DOUT << "processing function: " << MF.getFunction()->getName() << "\n"; + // Get the ELF Section that this function belongs in. + ES = &EW.getTextSection(MF.getFunction()); - // FIXME: better memory management, this will be replaced by BinaryObjects - BinaryData &BD = ES->getData(); - BD.reserve(4096); - BufferBegin = &BD[0]; - BufferEnd = BufferBegin + BD.capacity(); + // Set the desired binary object to be used by the code emitters + setBinaryObject(ES); // Get the function alignment in bytes unsigned Align = (1 << MF.getAlignment()); - // Align the section size with the function alignment, so the function can - // start in a aligned offset, also update the section alignment if needed. - if (ES->Align < Align) ES->Align = Align; - ES->Size = (ES->Size + (Align-1)) & (-Align); - - // Snaity check on allocated space for text section - assert( ES->Size < 4096 && "no more space in TextSection" ); - - // FIXME: Using ES->Size directly here instead of calculating it from the - // output buffer size (impossible because the code emitter deals only in raw - // bytes) forces us to manually synchronize size and write padding zero bytes - // to the output buffer for all non-text sections. For text sections, we do - // not synchonize the output buffer, and we just blow up if anyone tries to - // write non-code to it. An assert should probably be added to - // AddSymbolToSection to prevent calling it on the text section. - CurBufferPtr = BufferBegin + ES->Size; - - // Record function start address relative to BufferBegin - FnStartPtr = CurBufferPtr; + // The function must start on its required alignment + ES->emitAlignment(Align); + + // Update the section alignment if needed. + ES->Align = std::max(ES->Align, Align); + + // Record the function start offset + FnStartOff = ES->getCurrentPCOffset(); + + // Emit constant pool and jump tables to their appropriate sections. + // They need to be emitted before the function because in some targets + // the later may reference JT or CP entry address. + emitConstantPool(MF.getConstantPool()); + if (MF.getJumpTableInfo()) + emitJumpTables(MF.getJumpTableInfo()); } /// finishFunction - This callback is invoked after the function is completely /// finished. bool ELFCodeEmitter::finishFunction(MachineFunction &MF) { - // Update Section Size - ES->Size = CurBufferPtr - BufferBegin; - // Add a symbol to represent the function. const Function *F = MF.getFunction(); - ELFSym FnSym(F); - FnSym.setType(ELFSym::STT_FUNC); - FnSym.setBind(EW.getGlobalELFLinkage(F)); - FnSym.setVisibility(EW.getGlobalELFVisibility(F)); - FnSym.SectionIdx = ES->SectionIdx; - FnSym.Size = CurBufferPtr-FnStartPtr; + ELFSym *FnSym = ELFSym::getGV(F, EW.getGlobalELFBinding(F), ELF::STT_FUNC, + EW.getGlobalELFVisibility(F)); + FnSym->SectionIdx = ES->SectionIdx; + FnSym->Size = ES->getCurrentPCOffset()-FnStartOff; + EW.AddPendingGlobalSymbol(F, true); // Offset from start of Section - FnSym.Value = FnStartPtr-BufferBegin; - - // Locals should go on the symbol list front - if (!F->hasPrivateLinkage()) { - if (FnSym.getBind() == ELFSym::STB_LOCAL) - EW.SymbolList.push_front(FnSym); - else - EW.SymbolList.push_back(FnSym); + FnSym->Value = FnStartOff; + + if (!F->hasPrivateLinkage()) + EW.SymbolList.push_back(FnSym); + + // Patch up Jump Table Section relocations to use the real MBBs offsets + // now that the MBB label offsets inside the function are known. + if (MF.getJumpTableInfo()) { + ELFSection &JTSection = EW.getJumpTableSection(); + for (std::vector::iterator MRI = JTRelocations.begin(), + MRE = JTRelocations.end(); MRI != MRE; ++MRI) { + MachineRelocation &MR = *MRI; + uintptr_t MBBOffset = getMachineBasicBlockAddress(MR.getBasicBlock()); + MR.setResultPointer((void*)MBBOffset); + MR.setConstantVal(ES->SectionIdx); + JTSection.addRelocation(MR); + } } - // Emit constant pool to appropriate section(s) - emitConstantPool(MF.getConstantPool()); - - // Relocations - // ----------- // 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. + // 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.isGlobalValue()) { - EW.PendingGlobals.insert(MR.getGlobalValue()); + EW.AddPendingGlobalSymbol(MR.getGlobalValue()); + } else if (MR.isExternalSymbol()) { + EW.AddPendingExternalSymbol(MR.getExternalSymbol()); } else if (MR.isBasicBlock()) { Addr = getMachineBasicBlockAddress(MR.getBasicBlock()); MR.setConstantVal(ES->SectionIdx); @@ -116,13 +115,24 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) { Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex()); MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]); MR.setResultPointer((void*)Addr); + } else if (MR.isJumpTableIndex()) { + ELFSection &JTSection = EW.getJumpTableSection(); + Addr = getJumpTableEntryAddress(MR.getJumpTableIndex()); + MR.setConstantVal(JTSection.SectionIdx); + MR.setResultPointer((void*)Addr); } else { - assert(0 && "Unhandled relocation type"); + llvm_unreachable("Unhandled relocation type"); } ES->addRelocation(MR); } - Relocations.clear(); + // Clear per-function data structures. + JTRelocations.clear(); + Relocations.clear(); + CPLocations.clear(); + CPSections.clear(); + JTLocations.clear(); + MBBLocations.clear(); return false; } @@ -136,25 +146,59 @@ void ELFCodeEmitter::emitConstantPool(MachineConstantPool *MCP) { assert(TM.getRelocationModel() != Reloc::PIC_ && "PIC codegen not yet handled for elf constant pools!"); - const TargetAsmInfo *TAI = TM.getTargetAsmInfo(); for (unsigned i = 0, e = CP.size(); i != e; ++i) { MachineConstantPoolEntry CPE = CP[i]; - // Get the right ELF Section for this constant pool entry - std::string CstPoolName = - TAI->SelectSectionForMachineConst(CPE.getType())->getName(); - ELFSection &CstPoolSection = - EW.getConstantPoolSection(CstPoolName, CPE.getAlignment()); - // Record the constant pool location and the section index - CPLocations.push_back(CstPoolSection.size()); - CPSections.push_back(CstPoolSection.SectionIdx); + ELFSection &CstPool = EW.getConstantPoolSection(CPE); + CPLocations.push_back(CstPool.size()); + CPSections.push_back(CstPool.SectionIdx); if (CPE.isMachineConstantPoolEntry()) assert("CPE.isMachineConstantPoolEntry not supported yet"); // Emit the constant to constant pool section - EW.EmitGlobalConstant(CPE.Val.ConstVal, CstPoolSection); + EW.EmitGlobalConstant(CPE.Val.ConstVal, CstPool); + } +} + +/// emitJumpTables - Emit all the jump tables for a given jump table info +/// record to the appropriate section. +void ELFCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) { + const std::vector &JT = MJTI->getJumpTables(); + if (JT.empty()) return; + + // FIXME: handle PIC codegen + assert(TM.getRelocationModel() != Reloc::PIC_ && + "PIC codegen not yet handled for elf jump tables!"); + + const TargetELFWriterInfo *TEW = TM.getELFWriterInfo(); + unsigned EntrySize = 4; //MJTI->getEntrySize(); + + // Get the ELF Section to emit the jump table + ELFSection &JTSection = EW.getJumpTableSection(); + + // For each JT, record its offset from the start of the section + for (unsigned i = 0, e = JT.size(); i != e; ++i) { + const std::vector &MBBs = JT[i].MBBs; + + // Record JT 'i' offset in the JT section + JTLocations.push_back(JTSection.size()); + + // Each MBB entry in the Jump table section has a relocation entry + // against the current text section. + for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { + unsigned MachineRelTy = TEW->getAbsoluteLabelMachineRelTy(); + MachineRelocation MR = + MachineRelocation::getBB(JTSection.size(), MachineRelTy, MBBs[mi]); + + // Add the relocation to the Jump Table section + JTRelocations.push_back(MR); + + // Output placeholder for MBB in the JT section + for (unsigned s=0; s < EntrySize; ++s) + JTSection.emitByte(0); + } } }