X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FELFCodeEmitter.cpp;h=660424c3c1411343c76870147f016bd161822493;hb=dc81e5da271ed394e2029c83458773c4ae2fc5f4;hp=8cb7c94c5d0f1a34cbd36475b779e362dfaff9d2;hpb=0d3193ef3ce7377eeaa1d38ca08f8a62ebcd5f63;p=oota-llvm.git diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp index 8cb7c94c5d0..660424c3c14 100644 --- a/lib/CodeGen/ELFCodeEmitter.cpp +++ b/lib/CodeGen/ELFCodeEmitter.cpp @@ -9,15 +9,24 @@ #define DEBUG_TYPE "elfce" +#include "ELF.h" +#include "ELFWriter.h" #include "ELFCodeEmitter.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #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/MC/MCAsmInfo.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" //===----------------------------------------------------------------------===// // ELFCodeEmitter Implementation @@ -28,104 +37,169 @@ namespace llvm { /// startFunction - This callback is invoked when a new machine function is /// about to be emitted. void ELFCodeEmitter::startFunction(MachineFunction &MF) { + DEBUG(dbgs() << "processing function: " + << MF.getFunction()->getName() << "\n"); + // Get the ELF Section that this function belongs in. - ES = &EW.getTextSection(); - - DOUT << "processing function: " << MF.getFunction()->getName() << "\n"; - - // FIXME: better memory management, this will be replaced by BinaryObjects - BinaryData &BD = ES->getData(); - BD.reserve(4096); - BufferBegin = &BD[0]; - BufferEnd = BufferBegin + BD.capacity(); - - // Align the output buffer with function alignment, and - // upgrade the section alignment if required - unsigned Align = - TM.getELFWriterInfo()->getFunctionAlignment(MF.getFunction()); - 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; + ES = &EW.getTextSection(MF.getFunction()); + + // 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()); + + // 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) { // Add a symbol to represent the function. - ELFSym FnSym(MF.getFunction()); - - // Update Section Size - ES->Size = CurBufferPtr - BufferBegin; - - // Set the symbol type as a function - FnSym.setType(ELFSym::STT_FUNC); - FnSym.SectionIdx = ES->SectionIdx; - FnSym.Size = CurBufferPtr-FnStartPtr; + const Function *F = MF.getFunction(); + 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; - - // Figure out the binding (linkage) of the symbol. - switch (MF.getFunction()->getLinkage()) { - default: - // appending linkage is illegal for functions. - assert(0 && "Unknown linkage type!"); - case GlobalValue::ExternalLinkage: - FnSym.setBind(ELFSym::STB_GLOBAL); - EW.SymbolList.push_back(FnSym); - break; - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - FnSym.setBind(ELFSym::STB_WEAK); + FnSym->Value = FnStartOff; + + if (!F->hasPrivateLinkage()) EW.SymbolList.push_back(FnSym); - break; - case GlobalValue::PrivateLinkage: - assert (0 && "PrivateLinkage should not be in the symbol table."); - case GlobalValue::InternalLinkage: - FnSym.setBind(ELFSym::STB_LOCAL); - EW.SymbolList.push_front(FnSym); - break; + + // 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); + } } - // Relocations - // ----------- - // If we have emitted any relocations to function-specific objects such as + // 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.isBasicBlock()) { + if (MR.isGlobalValue()) { + EW.AddPendingGlobalSymbol(MR.getGlobalValue()); + } else if (MR.isExternalSymbol()) { + EW.AddPendingExternalSymbol(MR.getExternalSymbol()); + } else if (MR.isBasicBlock()) { Addr = getMachineBasicBlockAddress(MR.getBasicBlock()); MR.setConstantVal(ES->SectionIdx); MR.setResultPointer((void*)Addr); - } else if (MR.isGlobalValue()) { - EW.PendingGlobals.insert(MR.getGlobalValue()); + } else if (MR.isConstantPoolIndex()) { + 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; } +/// emitConstantPool - For each constant pool entry, figure out which section +/// the constant should live in and emit the constant +void ELFCodeEmitter::emitConstantPool(MachineConstantPool *MCP) { + const std::vector &CP = MCP->getConstants(); + if (CP.empty()) return; + + // TODO: handle PIC codegen + assert(TM.getRelocationModel() != Reloc::PIC_ && + "PIC codegen not yet handled for elf constant pools!"); + + for (unsigned i = 0, e = CP.size(); i != e; ++i) { + MachineConstantPoolEntry CPE = CP[i]; + + // Record the constant pool location and the section index + ELFSection &CstPool = EW.getConstantPoolSection(CPE); + CPLocations.push_back(CstPool.size()); + CPSections.push_back(CstPool.SectionIdx); + + if (CPE.isMachineConstantPoolEntry()) + assert(0 && "CPE.isMachineConstantPoolEntry not supported yet"); + + // Emit the constant to constant pool section + 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); + } + } +} + } // end namespace llvm