From ac57e6e498abccb117e0d61c2fa0f733845e50cb Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Mon, 6 Jul 2009 05:09:34 +0000 Subject: [PATCH] Add the Object Code Emitter class. Original patch by Aaron Gray, I did some cleanup, removed some #includes and moved Object Code Emitter out-of-line. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74813 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/BinaryObject.h | 36 ++--- include/llvm/CodeGen/FileWriters.h | 10 +- include/llvm/CodeGen/MachineCodeEmitter.h | 21 +-- include/llvm/Target/TargetMachine.h | 30 ++++- lib/CodeGen/ELFWriter.cpp | 6 +- lib/CodeGen/LLVMTargetMachine.cpp | 17 +++ lib/CodeGen/MachO.h | 88 ++++++------- lib/CodeGen/MachOCodeEmitter.cpp | 63 +++------ lib/CodeGen/MachOCodeEmitter.h | 76 ++--------- lib/CodeGen/MachOWriter.cpp | 153 ++++++++++------------ lib/CodeGen/MachOWriter.h | 23 +++- lib/Target/ARM/ARM.h | 3 + lib/Target/ARM/ARMCodeEmitter.cpp | 17 +-- lib/Target/ARM/ARMTargetMachine.cpp | 33 +++++ lib/Target/ARM/ARMTargetMachine.h | 6 + lib/Target/Alpha/Alpha.h | 5 +- lib/Target/Alpha/AlphaCodeEmitter.cpp | 5 + lib/Target/Alpha/AlphaTargetMachine.cpp | 17 +++ lib/Target/Alpha/AlphaTargetMachine.h | 6 + lib/Target/PowerPC/PPC.h | 5 +- lib/Target/PowerPC/PPCCodeEmitter.cpp | 8 ++ lib/Target/PowerPC/PPCTargetMachine.cpp | 48 +++++++ lib/Target/PowerPC/PPCTargetMachine.h | 5 + lib/Target/X86/X86.h | 2 + lib/Target/X86/X86CodeEmitter.cpp | 17 +-- lib/Target/X86/X86TargetMachine.cpp | 43 ++++++ lib/Target/X86/X86TargetMachine.h | 5 + tools/llc/llc.cpp | 9 +- tools/lto/LTOCodeGenerator.cpp | 8 +- 29 files changed, 440 insertions(+), 325 deletions(-) diff --git a/include/llvm/CodeGen/BinaryObject.h b/include/llvm/CodeGen/BinaryObject.h index ce0c07af951..f8fce03c313 100644 --- a/include/llvm/CodeGen/BinaryObject.h +++ b/include/llvm/CodeGen/BinaryObject.h @@ -146,27 +146,27 @@ public: /// emitDWordLE - This callback is invoked when a 64-bit word needs to be /// written to the data stream in little-endian format. inline void emitDWordLE(uint64_t W) { - Data.push_back(unsigned(W >> 0) & 255); - Data.push_back(unsigned(W >> 8) & 255); - Data.push_back(unsigned(W >> 16) & 255); - Data.push_back(unsigned(W >> 24) & 255); - Data.push_back(unsigned(W >> 32) & 255); - Data.push_back(unsigned(W >> 40) & 255); - Data.push_back(unsigned(W >> 48) & 255); - Data.push_back(unsigned(W >> 56) & 255); + Data.push_back((W >> 0) & 255); + Data.push_back((W >> 8) & 255); + Data.push_back((W >> 16) & 255); + Data.push_back((W >> 24) & 255); + Data.push_back((W >> 32) & 255); + Data.push_back((W >> 40) & 255); + Data.push_back((W >> 48) & 255); + Data.push_back((W >> 56) & 255); } /// emitDWordBE - This callback is invoked when a 64-bit word needs to be /// written to the data stream in big-endian format. inline void emitDWordBE(uint64_t W) { - Data.push_back(unsigned(W >> 56) & 255); - Data.push_back(unsigned(W >> 48) & 255); - Data.push_back(unsigned(W >> 40) & 255); - Data.push_back(unsigned(W >> 32) & 255); - Data.push_back(unsigned(W >> 24) & 255); - Data.push_back(unsigned(W >> 16) & 255); - Data.push_back(unsigned(W >> 8) & 255); - Data.push_back(unsigned(W >> 0) & 255); + Data.push_back((W >> 56) & 255); + Data.push_back((W >> 48) & 255); + Data.push_back((W >> 40) & 255); + Data.push_back((W >> 32) & 255); + Data.push_back((W >> 24) & 255); + Data.push_back((W >> 16) & 255); + Data.push_back((W >> 8) & 255); + Data.push_back((W >> 0) & 255); } /// fixByte - This callback is invoked when a byte needs to be @@ -270,11 +270,11 @@ public: } /// emitAlignment - Pad the data to the specified alignment. - void emitAlignment(unsigned Alignment) { + void emitAlignment(unsigned Alignment, uint8_t fill = 0) { if (Alignment <= 1) return; unsigned PadSize = -Data.size() & (Alignment-1); for (unsigned i = 0; igetMachineCodeEmitter(); + return (ObjectCodeEmitter*) &EW->getMachineCodeEmitter(); } //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index a163cac75b0..196d7d9e1eb 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -126,6 +126,23 @@ bool LLVMTargetMachine::addPassesToEmitFileFinish(PassManagerBase &PM, return false; // success! } +/// addPassesToEmitFileFinish - If the passes to emit the specified file had to +/// be split up (e.g., to add an object writer pass), this method can be used to +/// finish up adding passes to emit the file, if necessary. +bool LLVMTargetMachine::addPassesToEmitFileFinish(PassManagerBase &PM, + ObjectCodeEmitter *OCE, + CodeGenOpt::Level OptLevel) { + if (OCE) + addSimpleCodeEmitter(PM, OptLevel, PrintEmittedAsm, *OCE); + + PM.add(createGCInfoDeleter()); + + // Delete machine code for this function + PM.add(createMachineCodeDeleter()); + + return false; // success! +} + /// addPassesToEmitMachineCode - Add passes to the specified pass manager to /// get machine code emitted. This uses a MachineCodeEmitter object to handle /// actually outputting the machine code and resolving things like the address diff --git a/lib/CodeGen/MachO.h b/lib/CodeGen/MachO.h index bd9bd61e9ed..76c869992c4 100644 --- a/lib/CodeGen/MachO.h +++ b/lib/CodeGen/MachO.h @@ -17,6 +17,7 @@ #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/CodeGen/BinaryObject.h" #include "llvm/Target/TargetAsmInfo.h" #include #include @@ -272,11 +273,10 @@ struct MachOSegment { /// turned into the SectionCommand in the load command for a particlar /// segment. -struct MachOSection { +struct MachOSection : public BinaryObject { std::string sectname; // name of this section, std::string segname; // segment this section goes in uint64_t addr; // memory address of this section - uint64_t size; // size in bytes of this section uint32_t offset; // file offset of this section uint32_t align; // section alignment (power of 2) uint32_t reloff; // file offset of relocation entries @@ -290,19 +290,10 @@ struct MachOSection { /// to the correct section. uint32_t Index; - /// SectionData - The actual data for this section which we are building - /// up for emission to the file. - DataBuffer SectionData; - /// RelocBuffer - A buffer to hold the mach-o relocations before we write /// them out at the appropriate location in the file. DataBuffer RelocBuffer; - /// Relocations - The relocations that we have encountered so far in this - /// section that we will need to convert to MachORelocation entries when - /// the file is written. - std::vector Relocations; - // Constants for the section types (low 8 bits of flags field) // see enum { S_REGULAR = 0, @@ -374,48 +365,49 @@ struct MachOSection { } MachOSection(const std::string &seg, const std::string §) - : sectname(sect), segname(seg), addr(0), size(0), offset(0), align(2), - reloff(0), nreloc(0), flags(0), reserved1(0), reserved2(0), + : BinaryObject(), sectname(sect), segname(seg), addr(0), offset(0), + align(2), reloff(0), nreloc(0), flags(0), reserved1(0), reserved2(0), reserved3(0) { } }; // end struct MachOSection - /// MachOSymTab - This struct contains information about the offsets and - /// size of symbol table information. - /// segment. - struct MachODySymTab { - uint32_t cmd; // LC_DYSYMTAB - uint32_t cmdsize; // sizeof( MachODySymTab ) - uint32_t ilocalsym; // index to local symbols - uint32_t nlocalsym; // number of local symbols - uint32_t iextdefsym; // index to externally defined symbols - uint32_t nextdefsym; // number of externally defined symbols - uint32_t iundefsym; // index to undefined symbols - uint32_t nundefsym; // number of undefined symbols - uint32_t tocoff; // file offset to table of contents - uint32_t ntoc; // number of entries in table of contents - uint32_t modtaboff; // file offset to module table - uint32_t nmodtab; // number of module table entries - uint32_t extrefsymoff; // offset to referenced symbol table - uint32_t nextrefsyms; // number of referenced symbol table entries - uint32_t indirectsymoff; // file offset to the indirect symbol table - uint32_t nindirectsyms; // number of indirect symbol table entries - uint32_t extreloff; // offset to external relocation entries - uint32_t nextrel; // number of external relocation entries - uint32_t locreloff; // offset to local relocation entries - uint32_t nlocrel; // number of local relocation entries +/// MachOSymTab - This struct contains information about the offsets and +/// size of symbol table information. +/// segment. +struct MachODySymTab { + uint32_t cmd; // LC_DYSYMTAB + uint32_t cmdsize; // sizeof(MachODySymTab) + uint32_t ilocalsym; // index to local symbols + uint32_t nlocalsym; // number of local symbols + uint32_t iextdefsym; // index to externally defined symbols + uint32_t nextdefsym; // number of externally defined symbols + uint32_t iundefsym; // index to undefined symbols + uint32_t nundefsym; // number of undefined symbols + uint32_t tocoff; // file offset to table of contents + uint32_t ntoc; // number of entries in table of contents + uint32_t modtaboff; // file offset to module table + uint32_t nmodtab; // number of module table entries + uint32_t extrefsymoff; // offset to referenced symbol table + uint32_t nextrefsyms; // number of referenced symbol table entries + uint32_t indirectsymoff; // file offset to the indirect symbol table + uint32_t nindirectsyms; // number of indirect symbol table entries + uint32_t extreloff; // offset to external relocation entries + uint32_t nextrel; // number of external relocation entries + uint32_t locreloff; // offset to local relocation entries + uint32_t nlocrel; // number of local relocation entries + + // Constants for the cmd field + // see + enum { LC_DYSYMTAB = 0x0B // dynamic link-edit symbol table info + }; + + MachODySymTab() : cmd(LC_DYSYMTAB), cmdsize(20 * sizeof(uint32_t)), + ilocalsym(0), nlocalsym(0), iextdefsym(0), nextdefsym(0), + iundefsym(0), nundefsym(0), tocoff(0), ntoc(0), modtaboff(0), + nmodtab(0), extrefsymoff(0), nextrefsyms(0), indirectsymoff(0), + nindirectsyms(0), extreloff(0), nextrel(0), locreloff(0), nlocrel(0) { } - // Constants for the cmd field - // see - enum { LC_DYSYMTAB = 0x0B // dynamic link-edit symbol table info - }; - - MachODySymTab() : cmd(LC_DYSYMTAB), cmdsize(20 * sizeof(uint32_t)), - ilocalsym(0), nlocalsym(0), iextdefsym(0), nextdefsym(0), - iundefsym(0), nundefsym(0), tocoff(0), ntoc(0), modtaboff(0), - nmodtab(0), extrefsymoff(0), nextrefsyms(0), indirectsymoff(0), - nindirectsyms(0), extreloff(0), nextrel(0), locreloff(0), nlocrel(0) { } - }; +}; // end struct MachODySymTab } // end namespace llvm diff --git a/lib/CodeGen/MachOCodeEmitter.cpp b/lib/CodeGen/MachOCodeEmitter.cpp index 02b02de9ec3..52b50923673 100644 --- a/lib/CodeGen/MachOCodeEmitter.cpp +++ b/lib/CodeGen/MachOCodeEmitter.cpp @@ -16,6 +16,7 @@ #include "llvm/Target/TargetAsmInfo.h" #include "llvm/Support/Mangler.h" #include "llvm/Support/OutputBuffer.h" +#include //===----------------------------------------------------------------------===// // MachOCodeEmitter Implementation @@ -39,28 +40,18 @@ void MachOCodeEmitter::startFunction(MachineFunction &MF) { // Get the Mach-O Section that this function belongs in. MachOSection *MOS = MOW.getTextSection(); - // FIXME: better memory management - MOS->SectionData.reserve(4096); - BufferBegin = &MOS->SectionData[0]; - BufferEnd = BufferBegin + MOS->SectionData.capacity(); - // Upgrade the section alignment if required. if (MOS->align < Align) MOS->align = Align; - // Round the size up to the correct alignment for starting the new function. - if ((MOS->size & ((1 << Align) - 1)) != 0) { - MOS->size += (1 << Align); - MOS->size &= ~((1 << Align) - 1); - } + MOS->emitAlignment(Align); - // FIXME: Using MOS->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 + MOS->size; + // Create symbol for function entry + const GlobalValue *FuncV = MF.getFunction(); + MachOSym FnSym(FuncV, MOW.Mang->getValueName(FuncV), MOS->Index, TAI); + FnSym.n_value = getCurrentPCOffset(); + + // add it to the symtab. + MOW.SymbolTable.push_back(FnSym); } /// finishFunction - This callback is invoked after the function is completely @@ -71,15 +62,6 @@ bool MachOCodeEmitter::finishFunction(MachineFunction &MF) { // Get the Mach-O Section that this function belongs in. 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, TAI); - FnSym.n_value = MOS->size; - MOS->size = CurBufferPtr - BufferBegin; - // Emit constant pool to appropriate section(s) emitConstantPool(MF.getConstantPool()); @@ -112,12 +94,9 @@ bool MachOCodeEmitter::finishFunction(MachineFunction &MF) { } else { assert(0 && "Unhandled relocation type"); } - MOS->Relocations.push_back(MR); + MOS->addRelocation(MR); } Relocations.clear(); - - // Finally, add it to the symtab. - MOW.SymbolTable.push_back(FnSym); // Clear per-function data structures. CPLocations.clear(); @@ -151,13 +130,10 @@ void MachOCodeEmitter::emitConstantPool(MachineConstantPool *MCP) { unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); MachOSection *Sec = MOW.getConstSection(CP[i].Val.ConstVal); - OutputBuffer SecDataOut(Sec->SectionData, is64Bit, isLittleEndian); + OutputBuffer SecDataOut(Sec->getData(), is64Bit, isLittleEndian); - CPLocations.push_back(Sec->SectionData.size()); + CPLocations.push_back(Sec->size()); CPSections.push_back(Sec->Index); - - // FIXME: remove when we have unified size + output buffer - Sec->size += Size; // Allocate space in the section for the global. // FIXME: need alignment? @@ -165,14 +141,12 @@ void MachOCodeEmitter::emitConstantPool(MachineConstantPool *MCP) { for (unsigned j = 0; j < Size; ++j) SecDataOut.outbyte(0); - MOW.InitMem(CP[i].Val.ConstVal, &Sec->SectionData[0], CPLocations[i], - TM.getTargetData(), Sec->Relocations); + MachOWriter::InitMem(CP[i].Val.ConstVal, CPLocations[i], TM.getTargetData(), Sec); } } /// emitJumpTables - Emit all the jump tables for a given jump table info /// record to the appropriate section. - void MachOCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) { const std::vector &JT = MJTI->getJumpTables(); if (JT.empty()) return; @@ -183,24 +157,21 @@ void MachOCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) { MachOSection *Sec = MOW.getJumpTableSection(); unsigned TextSecIndex = MOW.getTextSection()->Index; - OutputBuffer SecDataOut(Sec->SectionData, is64Bit, isLittleEndian); + OutputBuffer SecDataOut(Sec->getData(), is64Bit, isLittleEndian); for (unsigned i = 0, e = JT.size(); i != e; ++i) { // For each jump table, record its offset from the start of the section, // reserve space for the relocations to the MBBs, and add the relocations. const std::vector &MBBs = JT[i].MBBs; - JTLocations.push_back(Sec->SectionData.size()); + JTLocations.push_back(Sec->size()); for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { - MachineRelocation MR(MOW.GetJTRelocation(Sec->SectionData.size(), - MBBs[mi])); + MachineRelocation MR(MOW.GetJTRelocation(Sec->size(), MBBs[mi])); MR.setResultPointer((void *)JTLocations[i]); MR.setConstantVal(TextSecIndex); - Sec->Relocations.push_back(MR); + Sec->addRelocation(MR); SecDataOut.outaddr(0); } } - // FIXME: remove when we have unified size + output buffer - Sec->size = Sec->SectionData.size(); } } // end namespace llvm diff --git a/lib/CodeGen/MachOCodeEmitter.h b/lib/CodeGen/MachOCodeEmitter.h index 0a6e4e4d19e..c280706e488 100644 --- a/lib/CodeGen/MachOCodeEmitter.h +++ b/lib/CodeGen/MachOCodeEmitter.h @@ -11,15 +11,13 @@ #define MACHOCODEEMITTER_H #include "MachOWriter.h" -#include "llvm/CodeGen/MachineCodeEmitter.h" -#include namespace llvm { /// MachOCodeEmitter - This class is used by the MachOWriter to emit the code /// for functions to the Mach-O file. -class MachOCodeEmitter : public MachineCodeEmitter { +class MachOCodeEmitter : public ObjectCodeEmitter { MachOWriter &MOW; /// Target machine description. @@ -34,27 +32,12 @@ class MachOCodeEmitter : public MachineCodeEmitter { /// Relocations - These are the relocations that the function needs, as /// 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; - - /// JTLocations - This is a map of jump table indices to offsets from the - /// start of the section for that jump table index. - std::vector JTLocations; - - /// 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. - std::vector MBBLocations; - + + std::map Labels; + public: - MachOCodeEmitter(MachOWriter &mow) : MOW(mow), TM(MOW.TM) - { + MachOCodeEmitter(MachOWriter &mow, MachOSection &mos) : + ObjectCodeEmitter(&mos), MOW(mow), TM(MOW.TM) { is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; isLittleEndian = TM.getTargetData()->isLittleEndian(); TAI = TM.getTargetAsmInfo(); @@ -69,58 +52,17 @@ public: void emitConstantPool(MachineConstantPool *MCP); void emitJumpTables(MachineJumpTableInfo *MJTI); - - virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const { - assert(CPLocations.size() > Index && "CP not emitted!"); - return CPLocations[Index]; - } - virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const { - assert(JTLocations.size() > Index && "JT not emitted!"); - return JTLocations[Index]; - } - - virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { - if (MBBLocations.size() <= (unsigned)MBB->getNumber()) - MBBLocations.resize((MBB->getNumber()+1)*2); - MBBLocations[MBB->getNumber()] = getCurrentPCOffset(); - } - virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { - assert(MBBLocations.size() > (unsigned)MBB->getNumber() && - MBBLocations[MBB->getNumber()] && "MBB not emitted!"); - return MBBLocations[MBB->getNumber()]; + virtual void emitLabel(uint64_t LabelID) { + Labels[LabelID] = getCurrentPCOffset(); } virtual uintptr_t getLabelAddress(uint64_t Label) const { - assert(0 && "get Label not implemented"); - abort(); - return 0; - } - - virtual void emitLabel(uint64_t LabelID) { - assert(0 && "emit Label not implemented"); - abort(); + return Labels.find(Label)->second; } virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { } - /// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE! - virtual void startGVStub(const GlobalValue* F, unsigned StubSize, - unsigned Alignment = 1) { - assert(0 && "JIT specific function called!"); - abort(); - } - virtual void startGVStub(const GlobalValue* F, void *Buffer, - unsigned StubSize) { - assert(0 && "JIT specific function called!"); - abort(); - } - virtual void *finishGVStub(const GlobalValue* F) { - assert(0 && "JIT specific function called!"); - abort(); - return 0; - } - }; // end class MachOCodeEmitter } // end namespace llvm diff --git a/lib/CodeGen/MachOWriter.cpp b/lib/CodeGen/MachOWriter.cpp index 163df6994aa..1dbbf15d9d7 100644 --- a/lib/CodeGen/MachOWriter.cpp +++ b/lib/CodeGen/MachOWriter.cpp @@ -46,12 +46,12 @@ namespace llvm { /// AddMachOWriter - Concrete function to add the Mach-O writer to the function /// pass manager. -MachineCodeEmitter *AddMachOWriter(PassManagerBase &PM, +ObjectCodeEmitter *AddMachOWriter(PassManagerBase &PM, raw_ostream &O, TargetMachine &TM) { MachOWriter *MOW = new MachOWriter(O, TM); PM.add(MOW); - return &MOW->getMachineCodeEmitter(); + return MOW->getObjectCodeEmitter(); } //===----------------------------------------------------------------------===// @@ -60,8 +60,9 @@ MachineCodeEmitter *AddMachOWriter(PassManagerBase &PM, char MachOWriter::ID = 0; -MachOWriter::MachOWriter(raw_ostream &o, TargetMachine &tm) - : MachineFunctionPass(&ID), O(o), TM(tm) { +MachOWriter::MachOWriter(raw_ostream &o, TargetMachine &tm) + : MachineFunctionPass(&ID), O(o), TM(tm) + { is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; isLittleEndian = TM.getTargetData()->isLittleEndian(); @@ -69,11 +70,11 @@ MachOWriter::MachOWriter(raw_ostream &o, TargetMachine &tm) // Create the machine code emitter object for this target. - MCE = new MachOCodeEmitter(*this); + MachOCE = new MachOCodeEmitter(*this, *getTextSection(true)); } MachOWriter::~MachOWriter() { - delete MCE; + delete MachOCE; } bool MachOWriter::doInitialization(Module &M) { @@ -97,13 +98,13 @@ bool MachOWriter::runOnMachineFunction(MachineFunction &MF) { /// the Mach-O file to 'O'. bool MachOWriter::doFinalization(Module &M) { // FIXME: we don't handle debug info yet, we should probably do that. - - // Okay, the.text section has been completed, build the .data, .bss, and + // Okay, the.text section has been completed, build the .data, .bss, and // "common" sections next. + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) EmitGlobal(I); - + // Emit the header and load commands. EmitHeaderAndLoadCommands(); @@ -133,38 +134,32 @@ void MachOWriter::AddSymbolToSection(MachOSection *Sec, GlobalVariable *GV) { // Reserve space in the .bss section for this symbol while maintaining the // desired section alignment, which must be at least as much as required by // this symbol. - OutputBuffer SecDataOut(Sec->SectionData, is64Bit, isLittleEndian); + OutputBuffer SecDataOut(Sec->getData(), is64Bit, isLittleEndian); if (Align) { - uint64_t OrigSize = Sec->size; Align = Log2_32(Align); Sec->align = std::max(unsigned(Sec->align), Align); - Sec->size = (Sec->size + Align - 1) & ~(Align-1); - // Add alignment padding to buffer as well. - // FIXME: remove when we have unified size + output buffer - unsigned AlignedSize = Sec->size - OrigSize; - for (unsigned i = 0; i < AlignedSize; ++i) - SecDataOut.outbyte(0); + Sec->emitAlignment(Sec->align); } // Globals without external linkage apparently do not go in the symbol table. if (!GV->hasLocalLinkage()) { MachOSym Sym(GV, Mang->getValueName(GV), Sec->Index, TAI); - Sym.n_value = Sec->size; + Sym.n_value = Sec->size(); SymbolTable.push_back(Sym); } // Record the offset of the symbol, and then allocate space for it. // FIXME: remove when we have unified size + output buffer - Sec->size += Size; - - // Now that we know what section the GlovalVariable is going to be emitted + + // Now that we know what section the GlovalVariable is going to be emitted // into, update our mappings. // FIXME: We may also need to update this when outputting non-GlobalVariable // GlobalValues such as functions. - GVSection[GV] = Sec; - GVOffset[GV] = Sec->SectionData.size(); + GVSection[GV] = Sec; + GVOffset[GV] = Sec->size(); + // Allocate space in the section for the global. for (unsigned i = 0; i < Size; ++i) SecDataOut.outbyte(0); @@ -174,7 +169,7 @@ void MachOWriter::EmitGlobal(GlobalVariable *GV) { const Type *Ty = GV->getType()->getElementType(); unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); bool NoInit = !GV->hasInitializer(); - + // If this global has a zero initializer, it is part of the .bss or common // section. if (NoInit || GV->getInitializer()->isNullValue()) { @@ -183,8 +178,7 @@ void MachOWriter::EmitGlobal(GlobalVariable *GV) { // merged with other symbols. if (NoInit || GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() || GV->hasCommonLinkage()) { - MachOSym ExtOrCommonSym(GV, Mang->getValueName(GV), - MachOSym::NO_SECT, TAI); + MachOSym ExtOrCommonSym(GV, Mang->getValueName(GV), MachOSym::NO_SECT, TAI); // For undefined (N_UNDF) external (N_EXT) types, n_value is the size in // bytes of the symbol. ExtOrCommonSym.n_value = Size; @@ -198,15 +192,14 @@ void MachOWriter::EmitGlobal(GlobalVariable *GV) { AddSymbolToSection(BSS, GV); return; } - + // Scalar read-only data goes in a literal section if the scalar is 4, 8, or // 16 bytes, or a cstring. Other read only data goes into a regular const // section. Read-write data goes in the data section. - MachOSection *Sec = GV->isConstant() ? getConstSection(GV->getInitializer()) : + MachOSection *Sec = GV->isConstant() ? getConstSection(GV->getInitializer()) : getDataSection(); AddSymbolToSection(Sec, GV); - InitMem(GV->getInitializer(), &Sec->SectionData[0], GVOffset[GV], - TM.getTargetData(), Sec->Relocations); + InitMem(GV->getInitializer(), GVOffset[GV], TM.getTargetData(), Sec); } @@ -214,21 +207,22 @@ void MachOWriter::EmitGlobal(GlobalVariable *GV) { void MachOWriter::EmitHeaderAndLoadCommands() { // Step #0: Fill in the segment load command size, since we need it to figure // out the rest of the header fields + MachOSegment SEG("", is64Bit); SEG.nsects = SectionList.size(); - SEG.cmdsize = SEG.cmdSize(is64Bit) + + SEG.cmdsize = SEG.cmdSize(is64Bit) + SEG.nsects * SectionList[0]->cmdSize(is64Bit); - + // Step #1: calculate the number of load commands. We always have at least // one, for the LC_SEGMENT load command, plus two for the normal // and dynamic symbol tables, if there are any symbols. Header.ncmds = SymbolTable.empty() ? 1 : 3; - + // Step #2: calculate the size of the load commands Header.sizeofcmds = SEG.cmdsize; if (!SymbolTable.empty()) Header.sizeofcmds += SymTab.cmdsize + DySymTab.cmdsize; - + // Step #3: write the header to the file // Local alias to shortenify coming code. DataBuffer &FH = Header.HeaderData; @@ -243,15 +237,15 @@ void MachOWriter::EmitHeaderAndLoadCommands() { FHOut.outword(Header.flags); if (is64Bit) FHOut.outword(Header.reserved); - + // Step #4: Finish filling in the segment load command and write it out for (std::vector::iterator I = SectionList.begin(), E = SectionList.end(); I != E; ++I) - SEG.filesize += (*I)->size; + SEG.filesize += (*I)->size(); SEG.vmsize = SEG.filesize; SEG.fileoff = Header.cmdSize(is64Bit) + Header.sizeofcmds; - + FHOut.outword(SEG.cmd); FHOut.outword(SEG.cmdsize); FHOut.outstring(SEG.segname, 16); @@ -263,42 +257,42 @@ void MachOWriter::EmitHeaderAndLoadCommands() { FHOut.outword(SEG.initprot); FHOut.outword(SEG.nsects); FHOut.outword(SEG.flags); - - // Step #5: Finish filling in the fields of the MachOSections + + // Step #5: Finish filling in the fields of the MachOSections uint64_t currentAddr = 0; for (std::vector::iterator I = SectionList.begin(), E = SectionList.end(); I != E; ++I) { MachOSection *MOS = *I; MOS->addr = currentAddr; MOS->offset = currentAddr + SEG.fileoff; - // FIXME: do we need to do something with alignment here? - currentAddr += MOS->size; + currentAddr += MOS->size(); } - + // Step #6: Emit the symbol table to temporary buffers, so that we know the // size of the string table when we write the next load command. This also // sorts and assigns indices to each of the symbols, which is necessary for // emitting relocations to externally-defined objects. BufferSymbolAndStringTable(); - + // Step #7: Calculate the number of relocations for each section and write out // the section commands for each section currentAddr += SEG.fileoff; for (std::vector::iterator I = SectionList.begin(), E = SectionList.end(); I != E; ++I) { MachOSection *MOS = *I; + // Convert the relocations to target-specific relocations, and fill in the // relocation offset for this section. CalculateRelocations(*MOS); MOS->reloff = MOS->nreloc ? currentAddr : 0; currentAddr += MOS->nreloc * 8; - + // write the finalized section command to the output buffer FHOut.outstring(MOS->sectname, 16); FHOut.outstring(MOS->segname, 16); FHOut.outaddr(MOS->addr); - FHOut.outaddr(MOS->size); + FHOut.outaddr(MOS->size()); FHOut.outword(MOS->offset); FHOut.outword(MOS->align); FHOut.outword(MOS->reloff); @@ -309,7 +303,7 @@ void MachOWriter::EmitHeaderAndLoadCommands() { if (is64Bit) FHOut.outword(MOS->reserved3); } - + // Step #8: Emit LC_SYMTAB/LC_DYSYMTAB load commands SymTab.symoff = currentAddr; SymTab.nsyms = SymbolTable.size(); @@ -345,39 +339,40 @@ void MachOWriter::EmitHeaderAndLoadCommands() { FHOut.outword(DySymTab.nextrel); FHOut.outword(DySymTab.locreloff); FHOut.outword(DySymTab.nlocrel); - + O.write((char*)&FH[0], FH.size()); } /// EmitSections - Now that we have constructed the file header and load /// commands, emit the data for each section to the file. - void MachOWriter::EmitSections() { for (std::vector::iterator I = SectionList.begin(), E = SectionList.end(); I != E; ++I) // Emit the contents of each section - O.write((char*)&(*I)->SectionData[0], (*I)->size); + if ((*I)->size()) + O.write((char*)&(*I)->getData()[0], (*I)->size()); } + +/// EmitRelocations - emit relocation data from buffer. void MachOWriter::EmitRelocations() { for (std::vector::iterator I = SectionList.begin(), E = SectionList.end(); I != E; ++I) // Emit the relocation entry data for each section. - O.write((char*)&(*I)->RelocBuffer[0], (*I)->RelocBuffer.size()); + if ((*I)->RelocBuffer.size()) + O.write((char*)&(*I)->RelocBuffer[0], (*I)->RelocBuffer.size()); } /// BufferSymbolAndStringTable - Sort the symbols we encountered and assign them /// each a string table index so that they appear in the correct order in the /// output file. - void MachOWriter::BufferSymbolAndStringTable() { // The order of the symbol table is: // 1. local symbols // 2. defined external symbols (sorted by name) // 3. undefined external symbols (sorted by name) - + // Before sorting the symbols, check the PendingGlobals for any undefined // globals that need to be put in the symbol table. - for (std::vector::iterator I = PendingGlobals.begin(), E = PendingGlobals.end(); I != E; ++I) { if (GVOffset[*I] == 0 && GVSection[*I] == 0) { @@ -389,19 +384,15 @@ void MachOWriter::BufferSymbolAndStringTable() { // Sort the symbols by name, so that when we partition the symbols by scope // of definition, we won't have to sort by name within each partition. - std::sort(SymbolTable.begin(), SymbolTable.end(), MachOSym::SymCmp()); - // Parition the symbol table entries so that all local symbols come before + // Parition the symbol table entries so that all local symbols come before // all symbols with external linkage. { 1 | 2 3 } - - std::partition(SymbolTable.begin(), SymbolTable.end(), - MachOSym::PartitionByLocal); - + std::partition(SymbolTable.begin(), SymbolTable.end(), MachOSym::PartitionByLocal); + // Advance iterator to beginning of external symbols and partition so that // all external symbols defined in this module come before all external // symbols defined elsewhere. { 1 | 2 | 3 } - for (std::vector::iterator I = SymbolTable.begin(), E = SymbolTable.end(); I != E; ++I) { if (!MachOSym::PartitionByLocal(*I)) { @@ -410,10 +401,9 @@ void MachOWriter::BufferSymbolAndStringTable() { } } - // Calculate the starting index for each of the local, extern defined, and + // Calculate the starting index for each of the local, extern defined, and // undefined symbols, as well as the number of each to put in the LC_DYSYMTAB // load command. - for (std::vector::iterator I = SymbolTable.begin(), E = SymbolTable.end(); I != E; ++I) { if (MachOSym::PartitionByLocal(*I)) { @@ -427,10 +417,9 @@ void MachOWriter::BufferSymbolAndStringTable() { ++DySymTab.nundefsym; } } - + // Write out a leading zero byte when emitting string table, for n_strx == 0 // which means an empty string. - OutputBuffer StrTOut(StrT, is64Bit, isLittleEndian); StrTOut.outbyte(0); @@ -439,7 +428,6 @@ void MachOWriter::BufferSymbolAndStringTable() { // 2. strings for local symbols // Since this is the opposite order from the symbol table, which we have just // sorted, we can walk the symbol table backwards to output the string table. - for (std::vector::reverse_iterator I = SymbolTable.rbegin(), E = SymbolTable.rend(); I != E; ++I) { if (I->GVName == "") { @@ -463,7 +451,7 @@ void MachOWriter::BufferSymbolAndStringTable() { I->n_value += GVSection[GV]->addr; if (GV && (GVOffset[GV] == -1)) GVOffset[GV] = index; - + // Emit nlist to buffer SymTOut.outword(I->n_strx); SymTOut.outbyte(I->n_type); @@ -478,32 +466,29 @@ void MachOWriter::BufferSymbolAndStringTable() { /// and the offset into that section. From this information, create the /// appropriate target-specific MachORelocation type and add buffer it to be /// written out after we are finished writing out sections. - void MachOWriter::CalculateRelocations(MachOSection &MOS) { - for (unsigned i = 0, e = MOS.Relocations.size(); i != e; ++i) { - MachineRelocation &MR = MOS.Relocations[i]; + std::vector Relocations = MOS.getRelocations(); + for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { + MachineRelocation &MR = Relocations[i]; unsigned TargetSection = MR.getConstantVal(); unsigned TargetAddr = 0; unsigned TargetIndex = 0; // This is a scattered relocation entry if it points to a global value with // a non-zero offset. - bool Scattered = false; bool Extern = false; // Since we may not have seen the GlobalValue we were interested in yet at // the time we emitted the relocation for it, fix it up now so that it // points to the offset into the correct section. - if (MR.isGlobalValue()) { GlobalValue *GV = MR.getGlobalValue(); MachOSection *MOSPtr = GVSection[GV]; intptr_t Offset = GVOffset[GV]; - + // If we have never seen the global before, it must be to a symbol // defined in another module (N_UNDF). - if (!MOSPtr) { // FIXME: need to append stub suffix Extern = true; @@ -515,10 +500,9 @@ void MachOWriter::CalculateRelocations(MachOSection &MOS) { } MR.setResultPointer((void*)Offset); } - + // If the symbol is locally defined, pass in the address of the section and // the section index to the code which will generate the target relocation. - if (!Extern) { MachOSection &To = *SectionList[TargetSection - 1]; TargetAddr = To.addr; @@ -526,7 +510,7 @@ void MachOWriter::CalculateRelocations(MachOSection &MOS) { } OutputBuffer RelocOut(MOS.RelocBuffer, is64Bit, isLittleEndian); - OutputBuffer SecOut(MOS.SectionData, is64Bit, isLittleEndian); + OutputBuffer SecOut(MOS.getData(), is64Bit, isLittleEndian); MOS.nreloc += GetTargetRelocation(MR, MOS.Index, TargetAddr, TargetIndex, RelocOut, SecOut, Scattered, Extern); @@ -535,22 +519,21 @@ void MachOWriter::CalculateRelocations(MachOSection &MOS) { // InitMem - Write the value of a Constant to the specified memory location, // converting it into bytes and relocations. - -void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, - const TargetData *TD, - std::vector &MRs) { +void MachOWriter::InitMem(const Constant *C, uintptr_t Offset, + const TargetData *TD, MachOSection* mos) { typedef std::pair CPair; std::vector WorkList; - + uint8_t *Addr = &mos->getData()[0]; + WorkList.push_back(CPair(C,(intptr_t)Addr + Offset)); - + intptr_t ScatteredOffset = 0; - + while (!WorkList.empty()) { const Constant *PC = WorkList.back().first; intptr_t PA = WorkList.back().second; WorkList.pop_back(); - + if (isa(PC)) { continue; } else if (const ConstantVector *CP = dyn_cast(PC)) { @@ -643,7 +626,7 @@ void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, memset(ptr, 0, TD->getPointerSize()); else if (const GlobalValue* GV = dyn_cast(PC)) { // FIXME: what about function stubs? - MRs.push_back(MachineRelocation::getGV(PA-(intptr_t)Addr, + mos->addRelocation(MachineRelocation::getGV(PA-(intptr_t)Addr, MachineRelocation::VANILLA, const_cast(GV), ScatteredOffset)); diff --git a/lib/CodeGen/MachOWriter.h b/lib/CodeGen/MachOWriter.h index 3af2b0af4b7..9f5b7c5ad31 100644 --- a/lib/CodeGen/MachOWriter.h +++ b/lib/CodeGen/MachOWriter.h @@ -15,17 +15,24 @@ #define MACHOWRITER_H #include "MachO.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/ObjectCodeEmitter.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachOWriterInfo.h" +#include #include namespace llvm { class GlobalVariable; class Mangler; - class MachineCodeEmitter; + class MachineRelocation; + class ObjectCodeEmitter; class MachOCodeEmitter; + class TargetData; + class TargetMachine; class OutputBuffer; class raw_ostream; @@ -38,8 +45,9 @@ namespace llvm { friend class MachOCodeEmitter; public: static char ID; - MachineCodeEmitter &getMachineCodeEmitter() const { - return *(MachineCodeEmitter*)MCE; + + ObjectCodeEmitter *getObjectCodeEmitter() { + return reinterpret_cast(MachOCE); } MachOWriter(raw_ostream &O, TargetMachine &TM); @@ -62,10 +70,10 @@ namespace llvm { /// Mangler *Mang; - /// MCE - The MachineCodeEmitter object that we are exposing to emit machine + /// MachOCE - The MachineCodeEmitter object that we are exposing to emit machine /// code for functions to the .o file. - MachOCodeEmitter *MCE; + MachOCodeEmitter *MachOCE; /// is64Bit/isLittleEndian - This information is inferred from the target /// machine directly, indicating what header values and flags to set. @@ -225,9 +233,10 @@ namespace llvm { /// SymbolTable to aid in emitting the DYSYMTAB load command. std::vector DynamicSymbolTable; - static void InitMem(const Constant *C, void *Addr, intptr_t Offset, + static void InitMem(const Constant *C, + uintptr_t Offset, const TargetData *TD, - std::vector &MRs); + MachOSection* mos); private: void AddSymbolToSection(MachOSection *MOS, GlobalVariable *GV); diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h index 08dc07c6415..12c26e8c795 100644 --- a/lib/Target/ARM/ARM.h +++ b/lib/Target/ARM/ARM.h @@ -24,6 +24,7 @@ class ARMBaseTargetMachine; class FunctionPass; class MachineCodeEmitter; class JITCodeEmitter; +class ObjectCodeEmitter; class raw_ostream; // Enums corresponding to ARM condition codes @@ -101,6 +102,8 @@ FunctionPass *createARMCodeEmitterPass(ARMBaseTargetMachine &TM, MachineCodeEmitter &MCE); FunctionPass *createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM, JITCodeEmitter &JCE); +FunctionPass *createARMObjectCodeEmitterPass(ARMBaseTargetMachine &TM, + ObjectCodeEmitter &OCE); FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false); FunctionPass *createARMConstantIslandPass(); diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index f29576148b3..4732700f515 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -26,6 +26,7 @@ #include "llvm/PassManager.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/ObjectCodeEmitter.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" @@ -174,18 +175,18 @@ namespace { /// createARMCodeEmitterPass - Return a pass that emits the collected ARM code /// to the specified MCE object. -namespace llvm { - -FunctionPass *createARMCodeEmitterPass(ARMBaseTargetMachine &TM, - MachineCodeEmitter &MCE) { +FunctionPass *llvm::createARMCodeEmitterPass(ARMBaseTargetMachine &TM, + MachineCodeEmitter &MCE) { return new Emitter(TM, MCE); } -FunctionPass *createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM, - JITCodeEmitter &JCE) { +FunctionPass *llvm::createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM, + JITCodeEmitter &JCE) { return new Emitter(TM, JCE); } - -} // end namespace llvm +FunctionPass *llvm::createARMObjectCodeEmitterPass(ARMBaseTargetMachine &TM, + ObjectCodeEmitter &OCE) { + return new Emitter(TM, OCE); +} template bool Emitter::runOnMachineFunction(MachineFunction &MF) { diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index 23447332198..b3faadafc5a 100644 --- a/lib/Target/ARM/ARMTargetMachine.cpp +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -228,6 +228,25 @@ bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM, return false; } +bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool DumpAsm, + ObjectCodeEmitter &OCE) { + // FIXME: Move this to TargetJITInfo! + if (DefRelocModel == Reloc::Default) + setRelocationModel(Reloc::Static); + + // Machine code emitter pass for ARM. + PM.add(createARMObjectCodeEmitterPass(*this, OCE)); + if (DumpAsm) { + assert(AsmPrinterCtor && "AsmPrinter was not linked in"); + if (AsmPrinterCtor) + PM.add(AsmPrinterCtor(errs(), *this, true)); + } + + return false; +} + bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, bool DumpAsm, @@ -258,4 +277,18 @@ bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, return false; } +bool ARMBaseTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool DumpAsm, + ObjectCodeEmitter &OCE) { + // Machine code emitter pass for ARM. + PM.add(createARMObjectCodeEmitterPass(*this, OCE)); + if (DumpAsm) { + assert(AsmPrinterCtor && "AsmPrinter was not linked in"); + if (AsmPrinterCtor) + PM.add(AsmPrinterCtor(errs(), *this, true)); + } + + return false; +} diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h index a0df54d6d52..a67471c04de 100644 --- a/lib/Target/ARM/ARMTargetMachine.h +++ b/lib/Target/ARM/ARMTargetMachine.h @@ -77,6 +77,8 @@ public: bool DumpAsm, MachineCodeEmitter &MCE); virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, bool DumpAsm, JITCodeEmitter &MCE); + virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, + bool DumpAsm, ObjectCodeEmitter &OCE); virtual bool addSimpleCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, bool DumpAsm, @@ -85,6 +87,10 @@ public: CodeGenOpt::Level OptLevel, bool DumpAsm, JITCodeEmitter &MCE); + virtual bool addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool DumpAsm, + ObjectCodeEmitter &OCE); }; /// ARMTargetMachine - ARM target machine. diff --git a/lib/Target/Alpha/Alpha.h b/lib/Target/Alpha/Alpha.h index 0818e25b33a..071257a428f 100644 --- a/lib/Target/Alpha/Alpha.h +++ b/lib/Target/Alpha/Alpha.h @@ -22,6 +22,7 @@ namespace llvm { class AlphaTargetMachine; class FunctionPass; class MachineCodeEmitter; + class ObjectCodeEmitter; class raw_ostream; FunctionPass *createAlphaISelDag(AlphaTargetMachine &TM); @@ -32,7 +33,9 @@ namespace llvm { FunctionPass *createAlphaCodeEmitterPass(AlphaTargetMachine &TM, MachineCodeEmitter &MCE); FunctionPass *createAlphaJITCodeEmitterPass(AlphaTargetMachine &TM, - JITCodeEmitter &JCE); + JITCodeEmitter &JCE); + FunctionPass *createAlphaObjectCodeEmitterPass(AlphaTargetMachine &TM, + ObjectCodeEmitter &OCE); FunctionPass *createAlphaLLRPPass(AlphaTargetMachine &tm); FunctionPass *createAlphaBranchSelectionPass(); diff --git a/lib/Target/Alpha/AlphaCodeEmitter.cpp b/lib/Target/Alpha/AlphaCodeEmitter.cpp index f50f007c207..3d3a32bf1d9 100644 --- a/lib/Target/Alpha/AlphaCodeEmitter.cpp +++ b/lib/Target/Alpha/AlphaCodeEmitter.cpp @@ -19,6 +19,7 @@ #include "llvm/PassManager.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/ObjectCodeEmitter.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/Passes.h" @@ -91,6 +92,10 @@ FunctionPass *llvm::createAlphaJITCodeEmitterPass(AlphaTargetMachine &TM, JITCodeEmitter &JCE) { return new Emitter(TM, JCE); } +FunctionPass *llvm::createAlphaObjectCodeEmitterPass(AlphaTargetMachine &TM, + ObjectCodeEmitter &OCE) { + return new Emitter(TM, OCE); +} template bool Emitter::runOnMachineFunction(MachineFunction &MF) { diff --git a/lib/Target/Alpha/AlphaTargetMachine.cpp b/lib/Target/Alpha/AlphaTargetMachine.cpp index 060089cbb6d..9b0f8d06951 100644 --- a/lib/Target/Alpha/AlphaTargetMachine.cpp +++ b/lib/Target/Alpha/AlphaTargetMachine.cpp @@ -119,6 +119,17 @@ bool AlphaTargetMachine::addCodeEmitter(PassManagerBase &PM, } return false; } +bool AlphaTargetMachine::addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool DumpAsm, ObjectCodeEmitter &OCE) { + PM.add(createAlphaObjectCodeEmitterPass(*this, OCE)); + if (DumpAsm) { + assert(AsmPrinterCtor && "AsmPrinter was not linked in"); + if (AsmPrinterCtor) + PM.add(AsmPrinterCtor(errs(), *this, true)); + } + return false; +} bool AlphaTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, bool DumpAsm, @@ -131,4 +142,10 @@ bool AlphaTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, JITCodeEmitter &JCE) { return addCodeEmitter(PM, OptLevel, DumpAsm, JCE); } +bool AlphaTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool DumpAsm, + ObjectCodeEmitter &OCE) { + return addCodeEmitter(PM, OptLevel, DumpAsm, OCE); +} diff --git a/lib/Target/Alpha/AlphaTargetMachine.h b/lib/Target/Alpha/AlphaTargetMachine.h index 26684c7778a..40ba4b33af6 100644 --- a/lib/Target/Alpha/AlphaTargetMachine.h +++ b/lib/Target/Alpha/AlphaTargetMachine.h @@ -74,6 +74,8 @@ public: bool DumpAsm, MachineCodeEmitter &MCE); virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, bool DumpAsm, JITCodeEmitter &JCE); + virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, + bool DumpAsm, ObjectCodeEmitter &JCE); virtual bool addSimpleCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, bool DumpAsm, @@ -82,6 +84,10 @@ public: CodeGenOpt::Level OptLevel, bool DumpAsm, JITCodeEmitter &JCE); + virtual bool addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool DumpAsm, + ObjectCodeEmitter &OCE); static void registerAsmPrinter(AsmPrinterCtorFn F) { AsmPrinterCtor = F; diff --git a/lib/Target/PowerPC/PPC.h b/lib/Target/PowerPC/PPC.h index f6c3469908b..b364e3f809d 100644 --- a/lib/Target/PowerPC/PPC.h +++ b/lib/Target/PowerPC/PPC.h @@ -24,6 +24,7 @@ namespace llvm { class PPCTargetMachine; class FunctionPass; class MachineCodeEmitter; + class ObjectCodeEmitter; class raw_ostream; FunctionPass *createPPCBranchSelectionPass(); @@ -33,7 +34,9 @@ FunctionPass *createPPCAsmPrinterPass(raw_ostream &OS, PPCTargetMachine &TM, FunctionPass *createPPCCodeEmitterPass(PPCTargetMachine &TM, MachineCodeEmitter &MCE); FunctionPass *createPPCJITCodeEmitterPass(PPCTargetMachine &TM, - JITCodeEmitter &MCE); + JITCodeEmitter &MCE); +FunctionPass *createPPCObjectCodeEmitterPass(PPCTargetMachine &TM, + ObjectCodeEmitter &OCE); } // end namespace llvm; // Defines symbolic names for PowerPC registers. This defines a mapping from diff --git a/lib/Target/PowerPC/PPCCodeEmitter.cpp b/lib/Target/PowerPC/PPCCodeEmitter.cpp index cd6018de490..eaa8269499d 100644 --- a/lib/Target/PowerPC/PPCCodeEmitter.cpp +++ b/lib/Target/PowerPC/PPCCodeEmitter.cpp @@ -19,6 +19,7 @@ #include "llvm/PassManager.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/ObjectCodeEmitter.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" @@ -91,6 +92,7 @@ namespace { /// createPPCCodeEmitterPass - Return a pass that emits the collected PPC code /// to the specified MCE object. + FunctionPass *llvm::createPPCCodeEmitterPass(PPCTargetMachine &TM, MachineCodeEmitter &MCE) { return new Emitter(TM, MCE); @@ -101,6 +103,11 @@ FunctionPass *llvm::createPPCJITCodeEmitterPass(PPCTargetMachine &TM, return new Emitter(TM, JCE); } +FunctionPass *llvm::createPPCObjectCodeEmitterPass(PPCTargetMachine &TM, + ObjectCodeEmitter &OCE) { + return new Emitter(TM, OCE); +} + template bool Emitter::runOnMachineFunction(MachineFunction &MF) { assert((MF.getTarget().getRelocationModel() != Reloc::Default || @@ -252,6 +259,7 @@ unsigned PPCCodeEmitter::getMachineOpValue(const MachineInstr &MI, Reloc = PPC::reloc_pcrel_bx; else // BCC instruction Reloc = PPC::reloc_pcrel_bcx; + MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), Reloc, MO.getMBB())); } else { diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp index e9073d63a15..6e30df49aea 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -221,6 +221,38 @@ bool PPCTargetMachine::addCodeEmitter(PassManagerBase &PM, return false; } +bool PPCTargetMachine::addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool DumpAsm, ObjectCodeEmitter &OCE) { + // The JIT should use the static relocation model in ppc32 mode, PIC in ppc64. + // FIXME: This should be moved to TargetJITInfo!! + if (Subtarget.isPPC64()) { + // We use PIC codegen in ppc64 mode, because otherwise we'd have to use many + // instructions to materialize arbitrary global variable + function + + // constant pool addresses. + setRelocationModel(Reloc::PIC_); + // Temporary workaround for the inability of PPC64 JIT to handle jump + // tables. + DisableJumpTables = true; + } else { + setRelocationModel(Reloc::Static); + } + + // Inform the subtarget that we are in JIT mode. FIXME: does this break macho + // writing? + Subtarget.SetJITMode(); + + // Machine code emitter pass for PowerPC. + PM.add(createPPCObjectCodeEmitterPass(*this, OCE)); + if (DumpAsm) { + assert(AsmPrinterCtor && "AsmPrinter was not linked in"); + if (AsmPrinterCtor) + PM.add(AsmPrinterCtor(errs(), *this, true)); + } + + return false; +} + bool PPCTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, bool DumpAsm, @@ -251,3 +283,19 @@ bool PPCTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, return false; } +bool PPCTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool DumpAsm, + ObjectCodeEmitter &OCE) { + // Machine code emitter pass for PowerPC. + PM.add(createPPCObjectCodeEmitterPass(*this, OCE)); + if (DumpAsm) { + assert(AsmPrinterCtor && "AsmPrinter was not linked in"); + if (AsmPrinterCtor) + PM.add(AsmPrinterCtor(errs(), *this, true)); + } + + return false; +} + + diff --git a/lib/Target/PowerPC/PPCTargetMachine.h b/lib/Target/PowerPC/PPCTargetMachine.h index c693bf42a3e..9f5ff573a4a 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.h +++ b/lib/Target/PowerPC/PPCTargetMachine.h @@ -85,12 +85,17 @@ public: bool DumpAsm, MachineCodeEmitter &MCE); virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, bool DumpAsm, JITCodeEmitter &JCE); + virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, + bool DumpAsm, ObjectCodeEmitter &OCE); virtual bool addSimpleCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, bool DumpAsm, MachineCodeEmitter &MCE); virtual bool addSimpleCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, bool DumpAsm, JITCodeEmitter &JCE); + virtual bool addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool DumpAsm, ObjectCodeEmitter &OCE); virtual bool getEnableTailMergeDefault() const; }; diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h index 22de3f64256..9b1fcedb963 100644 --- a/lib/Target/X86/X86.h +++ b/lib/Target/X86/X86.h @@ -56,6 +56,8 @@ FunctionPass *createX86CodeEmitterPass(X86TargetMachine &TM, MachineCodeEmitter &MCE); FunctionPass *createX86JITCodeEmitterPass(X86TargetMachine &TM, JITCodeEmitter &JCE); +FunctionPass *createX86ObjectCodeEmitterPass(X86TargetMachine &TM, + ObjectCodeEmitter &OCE); /// createX86EmitCodeToMemory - Returns a pass that converts a register /// allocated function into raw machine code in a dynamically diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp index d5846a049af..fffbf1fcdcc 100644 --- a/lib/Target/X86/X86CodeEmitter.cpp +++ b/lib/Target/X86/X86CodeEmitter.cpp @@ -22,6 +22,7 @@ #include "llvm/PassManager.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/ObjectCodeEmitter.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineModuleInfo.h" @@ -106,18 +107,18 @@ template /// createX86CodeEmitterPass - Return a pass that emits the collected X86 code /// to the specified templated MachineCodeEmitter object. -namespace llvm { - -FunctionPass *createX86CodeEmitterPass(X86TargetMachine &TM, - MachineCodeEmitter &MCE) { +FunctionPass *llvm::createX86CodeEmitterPass(X86TargetMachine &TM, + MachineCodeEmitter &MCE) { return new Emitter(TM, MCE); } -FunctionPass *createX86JITCodeEmitterPass(X86TargetMachine &TM, - JITCodeEmitter &JCE) { +FunctionPass *llvm::createX86JITCodeEmitterPass(X86TargetMachine &TM, + JITCodeEmitter &JCE) { return new Emitter(TM, JCE); } - -} // end namespace llvm +FunctionPass *llvm::createX86ObjectCodeEmitterPass(X86TargetMachine &TM, + ObjectCodeEmitter &OCE) { + return new Emitter(TM, OCE); +} template bool Emitter::runOnMachineFunction(MachineFunction &MF) { diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index b000914c920..5cf18a02ebd 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -290,6 +290,36 @@ bool X86TargetMachine::addCodeEmitter(PassManagerBase &PM, return false; } +bool X86TargetMachine::addCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool DumpAsm, + ObjectCodeEmitter &OCE) { + // FIXME: Move this to TargetJITInfo! + // On Darwin, do not override 64-bit setting made in X86TargetMachine(). + if (DefRelocModel == Reloc::Default && + (!Subtarget.isTargetDarwin() || !Subtarget.is64Bit())) + setRelocationModel(Reloc::Static); + + // 64-bit JIT places everything in the same buffer except external functions. + // On Darwin, use small code model but hack the call instruction for + // externals. Elsewhere, do not assume globals are in the lower 4G. + if (Subtarget.is64Bit()) { + if (Subtarget.isTargetDarwin()) + setCodeModel(CodeModel::Small); + else + setCodeModel(CodeModel::Large); + } + + PM.add(createX86ObjectCodeEmitterPass(*this, OCE)); + if (DumpAsm) { + assert(AsmPrinterCtor && "AsmPrinter was not linked in"); + if (AsmPrinterCtor) + PM.add(AsmPrinterCtor(errs(), *this, true)); + } + + return false; +} + bool X86TargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, bool DumpAsm, @@ -318,3 +348,16 @@ bool X86TargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, return false; } +bool X86TargetMachine::addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool DumpAsm, + ObjectCodeEmitter &OCE) { + PM.add(createX86ObjectCodeEmitterPass(*this, OCE)); + if (DumpAsm) { + assert(AsmPrinterCtor && "AsmPrinter was not linked in"); + if (AsmPrinterCtor) + PM.add(AsmPrinterCtor(errs(), *this, true)); + } + + return false; +} diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h index 90a5cc243d2..f38a4695c0f 100644 --- a/lib/Target/X86/X86TargetMachine.h +++ b/lib/Target/X86/X86TargetMachine.h @@ -84,12 +84,17 @@ public: bool DumpAsm, MachineCodeEmitter &MCE); virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, bool DumpAsm, JITCodeEmitter &JCE); + virtual bool addCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, + bool DumpAsm, ObjectCodeEmitter &OCE); virtual bool addSimpleCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, bool DumpAsm, MachineCodeEmitter &MCE); virtual bool addSimpleCodeEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel, bool DumpAsm, JITCodeEmitter &JCE); + virtual bool addSimpleCodeEmitter(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool DumpAsm, ObjectCodeEmitter &OCE); }; /// X86_32TargetMachine - X86 32-bit target machine. diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index ae03c1e0c03..42d158cf5ec 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -17,6 +17,7 @@ #include "llvm/CodeGen/FileWriters.h" #include "llvm/CodeGen/LinkAllCodegenComponents.h" #include "llvm/CodeGen/LinkAllAsmWriterComponents.h" +#include "llvm/CodeGen/ObjectCodeEmitter.h" #include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" @@ -312,7 +313,7 @@ int main(int argc, char **argv) { #endif // Ask the target to add backend passes as necessary. - MachineCodeEmitter *MCE = 0; + ObjectCodeEmitter *OCE = 0; // Override default to generate verbose assembly. Target.setAsmVerbosityDefault(true); @@ -331,14 +332,14 @@ int main(int argc, char **argv) { case FileModel::AsmFile: break; case FileModel::MachOFile: - MCE = AddMachOWriter(Passes, *Out, Target); + OCE = AddMachOWriter(Passes, *Out, Target); break; case FileModel::ElfFile: - MCE = AddELFWriter(Passes, *Out, Target); + OCE = AddELFWriter(Passes, *Out, Target); break; } - if (Target.addPassesToEmitFileFinish(Passes, MCE, OLvl)) { + if (Target.addPassesToEmitFileFinish(Passes, OCE, OLvl)) { std::cerr << argv[0] << ": target does not support generation of this" << " file type!\n"; if (Out != &outs()) delete Out; diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index 1a21132ef2f..801707f8d98 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -430,16 +430,16 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out, codeGenPasses->add(new TargetData(*_target->getTargetData())); - MachineCodeEmitter* mce = NULL; + ObjectCodeEmitter* oce = NULL; switch (_target->addPassesToEmitFile(*codeGenPasses, out, TargetMachine::AssemblyFile, CodeGenOpt::Aggressive)) { case FileModel::MachOFile: - mce = AddMachOWriter(*codeGenPasses, out, *_target); + oce = AddMachOWriter(*codeGenPasses, out, *_target); break; case FileModel::ElfFile: - mce = AddELFWriter(*codeGenPasses, out, *_target); + oce = AddELFWriter(*codeGenPasses, out, *_target); break; case FileModel::AsmFile: break; @@ -449,7 +449,7 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out, return true; } - if (_target->addPassesToEmitFileFinish(*codeGenPasses, mce, + if (_target->addPassesToEmitFileFinish(*codeGenPasses, oce, CodeGenOpt::Aggressive)) { errMsg = "target does not support generation of this file type"; return true; -- 2.34.1