diff --git a/lib/CodeGen/ELF.h b/lib/CodeGen/ELF.h index 28b6be8910e..8d92373b713 100644 --- a/lib/CodeGen/ELF.h +++ b/lib/CodeGen/ELF.h @@ -144,6 +144,9 @@ namespace llvm { uint8_t Other; unsigned short SectionIdx; + // Symbol index into the Symbol table + unsigned SymTabIdx; + enum { STB_LOCAL = 0, STB_GLOBAL = 1, @@ -168,7 +171,8 @@ namespace llvm { ELFSym(const GlobalValue *gv) : GV(gv), IsCommon(false), IsBss(false), IsConstant(false), NameIdx(0), Value(0), Size(0), Info(0), Other(STV_DEFAULT), - SectionIdx(ELFSection::SHN_UNDEF) { + SectionIdx(ELFSection::SHN_UNDEF), + SymTabIdx(0) { if (!GV) return; @@ -191,6 +195,10 @@ namespace llvm { return (Info >> 4) & 0xf; } + unsigned getType() { + return Info & 0xf; + } + void setBind(unsigned X) { assert(X == (X & 0xF) && "Bind value out of range!"); Info = (Info & 0x0F) | (X << 4); diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp index 8cb7c94c5d0..168fed56c19 100644 --- a/lib/CodeGen/ELFCodeEmitter.cpp +++ b/lib/CodeGen/ELFCodeEmitter.cpp @@ -16,6 +16,7 @@ #include "llvm/CodeGen/BinaryObject.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/Debug.h" @@ -103,21 +104,28 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) { break; } + // Emit constant pool to appropriate section(s) + emitConstantPool(MF.getConstantPool()); + // 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. for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { MachineRelocation &MR = Relocations[i]; intptr_t Addr; - if (MR.isBasicBlock()) { + if (MR.isGlobalValue()) { + EW.PendingGlobals.insert(MR.getGlobalValue()); + } 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 { assert(0 && "Unhandled relocation type"); } @@ -128,4 +136,36 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) { 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!"); + + 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); + + if (CPE.isMachineConstantPoolEntry()) + assert("CPE.isMachineConstantPoolEntry not supported yet"); + + // Emit the constant to constant pool section + EW.EmitGlobalConstant(CPE.Val.ConstVal, CstPoolSection); + } +} + } // end namespace llvm diff --git a/lib/CodeGen/ELFCodeEmitter.h b/lib/CodeGen/ELFCodeEmitter.h index c0289daf3e9..c309ef75971 100644 --- a/lib/CodeGen/ELFCodeEmitter.h +++ b/lib/CodeGen/ELFCodeEmitter.h @@ -31,6 +31,14 @@ namespace llvm { /// emitted. std::vector Relocations; + /// CPLocations - This is a map of constant pool indices to offsets from the + /// start of the section for that constant pool index. + std::vector CPLocations; + + /// CPSections - This is a map of constant pool indices to the MachOSection + /// containing the constant pool entry for that index. + std::vector CPSections; + /// MBBLocations - This vector is a mapping from MBB ID's to their address. /// It is filled in by the StartMachineBasicBlock callback and queried by /// the getMachineBasicBlockAddress callback. @@ -62,9 +70,10 @@ namespace llvm { } virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const { - assert(0 && "CP not implementated yet!"); - return 0; + assert(CPLocations.size() > Index && "CP not emitted!"); + return CPLocations[Index]; } + virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const { assert(0 && "JT not implementated yet!"); return 0; @@ -86,6 +95,10 @@ namespace llvm { abort(); } + /// emitConstantPool - For each constant pool entry, figure out which section + /// the constant should live in and emit the constant. + void emitConstantPool(MachineConstantPool *MCP); + virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { } /// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE! diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp index 03db65699a2..041defa5236 100644 --- a/lib/CodeGen/ELFWriter.cpp +++ b/lib/CodeGen/ELFWriter.cpp @@ -389,6 +389,24 @@ bool ELFWriter::doFinalization(Module &M) { if (TAI->getNonexecutableStackDirective()) getNonExecStackSection(); + // Emit a symbol for each section created until now + for (std::map::iterator I = SectionLookup.begin(), + E = SectionLookup.end(); I != E; ++I) { + ELFSection *ES = I->second; + + // Skip null section + if (ES->SectionIdx == 0) continue; + + ELFSym SectionSym(0); + SectionSym.SectionIdx = ES->SectionIdx; + SectionSym.Size = 0; + SectionSym.setBind(ELFSym::STB_LOCAL); + SectionSym.setType(ELFSym::STT_SECTION); + + // Local symbols go in the list front + SymbolList.push_front(SectionSym); + } + // Emit string table EmitStringTable(); @@ -451,15 +469,25 @@ void ELFWriter::EmitRelocations() { // Constant addend used to compute the value to be stored // into the relocatable field - int64_t Addend = TEW->getAddendForRelTy(RelType); + int64_t Addend = 0; // There are several machine relocations types, and each one of // them needs a different approach to retrieve the symbol table index. if (MR.isGlobalValue()) { const GlobalValue *G = MR.getGlobalValue(); SymIdx = GblSymLookup[G]; + Addend = TEW->getAddendForRelTy(RelType); } else { - assert(0 && "dunno how to handle other relocation types"); + unsigned SectionIdx = MR.getConstantVal(); + // TODO: use a map for this. + for (std::list::iterator I = SymbolList.begin(), + E = SymbolList.end(); I != E; ++I) + if ((SectionIdx == I->SectionIdx) && + (I->getType() == ELFSym::STT_SECTION)) { + SymIdx = I->SymTabIdx; + break; + } + Addend = (uint64_t)MR.getResultPointer(); } // Get the relocation entry and emit to the relocation section @@ -540,7 +568,8 @@ void ELFWriter::EmitStringTable() { E = SymbolList.end(); I != E; ++I) { // Use the name mangler to uniquify the LLVM symbol. - std::string Name = Mang->getValueName(I->GV); + std::string Name; + if (I->GV) Name.append(Mang->getValueName(I->GV)); if (Name.empty()) { I->NameIdx = 0; @@ -589,7 +618,11 @@ void ELFWriter::EmitSymbolTable() { EmitSymbol(SymTab, *I); // Record the symbol table index for each global value - GblSymLookup[I->GV] = Index; + if (I->GV) + GblSymLookup[I->GV] = Index; + + // Keep track on the symbol index into the symbol table + I->SymTabIdx = Index; } SymTab.Info = FirstNonLocalSymbol; diff --git a/lib/CodeGen/ELFWriter.h b/lib/CodeGen/ELFWriter.h index 39577d9a97d..e0e71d01fa5 100644 --- a/lib/CodeGen/ELFWriter.h +++ b/lib/CodeGen/ELFWriter.h @@ -147,6 +147,12 @@ namespace llvm { ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC); } + /// Get a constant pool section based on the section name returned by TAI + ELFSection &getConstantPoolSection(std::string SName, unsigned Align) { + return getSection(SName, ELFSection::SHT_PROGBITS, + ELFSection::SHF_MERGE | ELFSection::SHF_ALLOC, Align); + } + /// Return the relocation section of section 'S'. 'RelA' is true /// if the relocation section contains entries with addends. ELFSection &getRelocSection(std::string SName, bool RelA) {