From 752e928e6b87a2988588fed9cc224fd6ec02c5f6 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Mon, 6 Jul 2009 06:40:51 +0000 Subject: [PATCH] Cleanup MachO writer and code emitter. Fix 80 cols problems, remove extra spaces, shrink down includes and move some methods out-of-line git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74817 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachO.h | 31 +++--- lib/CodeGen/MachOCodeEmitter.cpp | 17 ++- lib/CodeGen/MachOCodeEmitter.h | 14 ++- lib/CodeGen/MachOWriter.cpp | 180 ++++++++++++++++++++++--------- lib/CodeGen/MachOWriter.h | 151 ++++++++------------------ 5 files changed, 206 insertions(+), 187 deletions(-) diff --git a/lib/CodeGen/MachO.h b/lib/CodeGen/MachO.h index 76c869992c4..247b4a6c0c4 100644 --- a/lib/CodeGen/MachO.h +++ b/lib/CodeGen/MachO.h @@ -14,18 +14,15 @@ #ifndef MACHO_H #define MACHO_H -#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 namespace llvm { -typedef std::vector DataBuffer; - +class GlobalValue; +class TargetAsmInfo; + /// MachOSym - This struct contains information about each symbol that is /// added to logical symbol table for the module. This is eventually /// turned into a real symbol table in the file. @@ -111,7 +108,7 @@ struct MachOHeader { /// HeaderData - The actual data for the header which we are building /// up for emission to the file. - DataBuffer HeaderData; + std::vector HeaderData; // Constants for the filetype field // see for additional info on the various types @@ -181,8 +178,8 @@ struct MachOHeader { }; MachOHeader() : magic(0), filetype(0), ncmds(0), sizeofcmds(0), flags(0), - reserved(0) { } - + reserved(0) {} + /// cmdSize - This routine returns the size of the MachOSection as written /// to disk, depending on whether the destination is a 64 bit Mach-O file. unsigned cmdSize(bool is64Bit) const { @@ -204,7 +201,7 @@ struct MachOHeader { } }; // end struct MachOHeader - + /// MachOSegment - This struct contains the necessary information to /// emit the load commands for each section in the file. struct MachOSegment { @@ -246,13 +243,13 @@ struct MachOSegment { SEG_VM_PROT_EXECUTE = VM_PROT_EXECUTE, SEG_VM_PROT_ALL = VM_PROT_ALL }; - + // Constants for the cmd field // see enum { LC_SEGMENT = 0x01, // segment of this file to be mapped LC_SEGMENT_64 = 0x19 // 64-bit segment of this file to be mapped }; - + /// cmdSize - This routine returns the size of the MachOSection as written /// to disk, depending on whether the destination is a 64 bit Mach-O file. unsigned cmdSize(bool is64Bit) const { @@ -285,15 +282,15 @@ struct MachOSection : public BinaryObject { uint32_t reserved1; // reserved (for offset or index) uint32_t reserved2; // reserved (for count or sizeof) uint32_t reserved3; // reserved (64 bit only) - + /// A unique number for this section, which will be used to match symbols /// to the correct section. uint32_t Index; - + /// RelocBuffer - A buffer to hold the mach-o relocations before we write /// them out at the appropriate location in the file. - DataBuffer RelocBuffer; - + std::vector RelocBuffer; + // Constants for the section types (low 8 bits of flags field) // see enum { S_REGULAR = 0, @@ -405,7 +402,7 @@ struct MachODySymTab { 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) { } + nindirectsyms(0), extreloff(0), nextrel(0), locreloff(0), nlocrel(0) {} }; // end struct MachODySymTab diff --git a/lib/CodeGen/MachOCodeEmitter.cpp b/lib/CodeGen/MachOCodeEmitter.cpp index 52b50923673..fccbf657057 100644 --- a/lib/CodeGen/MachOCodeEmitter.cpp +++ b/lib/CodeGen/MachOCodeEmitter.cpp @@ -7,13 +7,18 @@ // //===----------------------------------------------------------------------===// +#include "MachO.h" +#include "MachOWriter.h" #include "MachOCodeEmitter.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineRelocation.h" #include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Support/Mangler.h" #include "llvm/Support/OutputBuffer.h" #include @@ -23,7 +28,14 @@ //===----------------------------------------------------------------------===// namespace llvm { - + +MachOCodeEmitter::MachOCodeEmitter(MachOWriter &mow, MachOSection &mos) : + ObjectCodeEmitter(&mos), MOW(mow), TM(MOW.TM) { + is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; + isLittleEndian = TM.getTargetData()->isLittleEndian(); + TAI = TM.getTargetAsmInfo(); +} + /// startFunction - This callback is invoked when a new machine function is /// about to be emitted. @@ -141,7 +153,8 @@ void MachOCodeEmitter::emitConstantPool(MachineConstantPool *MCP) { for (unsigned j = 0; j < Size; ++j) SecDataOut.outbyte(0); - MachOWriter::InitMem(CP[i].Val.ConstVal, CPLocations[i], TM.getTargetData(), Sec); + MachOWriter::InitMem(CP[i].Val.ConstVal, CPLocations[i], + TM.getTargetData(), Sec); } } diff --git a/lib/CodeGen/MachOCodeEmitter.h b/lib/CodeGen/MachOCodeEmitter.h index c280706e488..96ba68f1dbf 100644 --- a/lib/CodeGen/MachOCodeEmitter.h +++ b/lib/CodeGen/MachOCodeEmitter.h @@ -10,10 +10,13 @@ #ifndef MACHOCODEEMITTER_H #define MACHOCODEEMITTER_H -#include "MachOWriter.h" +#include "llvm/CodeGen/ObjectCodeEmitter.h" +#include namespace llvm { +class MachOWriter; + /// MachOCodeEmitter - This class is used by the MachOWriter to emit the code /// for functions to the Mach-O file. @@ -36,12 +39,7 @@ class MachOCodeEmitter : public ObjectCodeEmitter { std::map Labels; public: - MachOCodeEmitter(MachOWriter &mow, MachOSection &mos) : - ObjectCodeEmitter(&mos), MOW(mow), TM(MOW.TM) { - is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; - isLittleEndian = TM.getTargetData()->isLittleEndian(); - TAI = TM.getTargetAsmInfo(); - } + MachOCodeEmitter(MachOWriter &mow, MachOSection &mos); virtual void startFunction(MachineFunction &MF); virtual bool finishFunction(MachineFunction &MF); @@ -49,7 +47,7 @@ public: virtual void addRelocation(const MachineRelocation &MR) { Relocations.push_back(MR); } - + void emitConstantPool(MachineConstantPool *MCP); void emitJumpTables(MachineJumpTableInfo *MJTI); diff --git a/lib/CodeGen/MachOWriter.cpp b/lib/CodeGen/MachOWriter.cpp index 1dbbf15d9d7..3ad03a4eee1 100644 --- a/lib/CodeGen/MachOWriter.cpp +++ b/lib/CodeGen/MachOWriter.cpp @@ -22,25 +22,20 @@ // //===----------------------------------------------------------------------===// +#include "MachO.h" #include "MachOWriter.h" #include "MachOCodeEmitter.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.h" #include "llvm/PassManager.h" -#include "llvm/CodeGen/FileWriters.h" -#include "llvm/CodeGen/MachineCodeEmitter.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetJITInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetMachOWriterInfo.h" #include "llvm/Support/Mangler.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/OutputBuffer.h" -#include "llvm/Support/Streams.h" #include "llvm/Support/raw_ostream.h" -#include -#include namespace llvm { @@ -60,16 +55,14 @@ ObjectCodeEmitter *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(); TAI = TM.getTargetAsmInfo(); // Create the machine code emitter object for this target. - MachOCE = new MachOCodeEmitter(*this, *getTextSection(true)); } @@ -98,13 +91,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(); @@ -126,6 +119,89 @@ bool MachOWriter::doFinalization(Module &M) { return false; } +// getConstSection - Get constant section for Constant 'C' +MachOSection *MachOWriter::getConstSection(Constant *C) { + const ConstantArray *CVA = dyn_cast(C); + if (CVA && CVA->isCString()) + return getSection("__TEXT", "__cstring", + MachOSection::S_CSTRING_LITERALS); + + const Type *Ty = C->getType(); + if (Ty->isPrimitiveType() || Ty->isInteger()) { + unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); + switch(Size) { + default: break; // Fall through to __TEXT,__const + case 4: + return getSection("__TEXT", "__literal4", + MachOSection::S_4BYTE_LITERALS); + case 8: + return getSection("__TEXT", "__literal8", + MachOSection::S_8BYTE_LITERALS); + case 16: + return getSection("__TEXT", "__literal16", + MachOSection::S_16BYTE_LITERALS); + } + } + return getSection("__TEXT", "__const"); +} + +// getJumpTableSection - Select the Jump Table section +MachOSection *MachOWriter::getJumpTableSection() { + if (TM.getRelocationModel() == Reloc::PIC_) + return getTextSection(false); + else + return getSection("__TEXT", "__const"); +} + +// getSection - Return the section with the specified name, creating a new +// section if one does not already exist. +MachOSection *MachOWriter::getSection(const std::string &seg, + const std::string §, + unsigned Flags /* = 0 */ ) { + MachOSection *MOS = SectionLookup[seg+sect]; + if (MOS) return MOS; + + MOS = new MachOSection(seg, sect); + SectionList.push_back(MOS); + MOS->Index = SectionList.size(); + MOS->flags = MachOSection::S_REGULAR | Flags; + SectionLookup[seg+sect] = MOS; + return MOS; +} + +// getTextSection - Return text section with different flags for code/data +MachOSection *MachOWriter::getTextSection(bool isCode /* = true */ ) { + if (isCode) + return getSection("__TEXT", "__text", + MachOSection::S_ATTR_PURE_INSTRUCTIONS | + MachOSection::S_ATTR_SOME_INSTRUCTIONS); + else + return getSection("__TEXT", "__text"); +} + +MachOSection *MachOWriter::getBSSSection() { + return getSection("__DATA", "__bss", MachOSection::S_ZEROFILL); +} + +// GetJTRelocation - Get a relocation a new BB relocation based +// on target information. +MachineRelocation MachOWriter::GetJTRelocation(unsigned Offset, + MachineBasicBlock *MBB) const { + return TM.getMachOWriterInfo()->GetJTRelocation(Offset, MBB); +} + +// GetTargetRelocation - Returns the number of relocations. +unsigned MachOWriter::GetTargetRelocation(MachineRelocation &MR, + unsigned FromIdx, unsigned ToAddr, + unsigned ToIndex, OutputBuffer &RelocOut, + OutputBuffer &SecOut, bool Scattered, + bool Extern) { + return TM.getMachOWriterInfo()->GetTargetRelocation(MR, FromIdx, ToAddr, + ToIndex, RelocOut, + SecOut, Scattered, + Extern); +} + void MachOWriter::AddSymbolToSection(MachOSection *Sec, GlobalVariable *GV) { const Type *Ty = GV->getType()->getElementType(); unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); @@ -151,15 +227,15 @@ void MachOWriter::AddSymbolToSection(MachOSection *Sec, GlobalVariable *GV) { // Record the offset of the symbol, and then allocate space for it. // FIXME: remove when we have unified size + output buffer - - // 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->size(); - + // Allocate space in the section for the global. for (unsigned i = 0; i < Size; ++i) SecDataOut.outbyte(0); @@ -169,7 +245,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()) { @@ -178,7 +254,8 @@ 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; @@ -192,11 +269,11 @@ 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(), GVOffset[GV], TM.getTargetData(), Sec); @@ -210,22 +287,22 @@ void MachOWriter::EmitHeaderAndLoadCommands() { 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; + std::vector &FH = Header.HeaderData; OutputBuffer FHOut(FH, is64Bit, isLittleEndian); FHOut.outword(Header.magic); @@ -237,7 +314,7 @@ 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) @@ -245,7 +322,7 @@ void MachOWriter::EmitHeaderAndLoadCommands() { SEG.vmsize = SEG.filesize; SEG.fileoff = Header.cmdSize(is64Bit) + Header.sizeofcmds; - + FHOut.outword(SEG.cmd); FHOut.outword(SEG.cmdsize); FHOut.outstring(SEG.segname, 16); @@ -257,8 +334,8 @@ 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) { @@ -268,13 +345,13 @@ void MachOWriter::EmitHeaderAndLoadCommands() { // FIXME: do we need to do something with alignment here? 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; @@ -287,7 +364,7 @@ void MachOWriter::EmitHeaderAndLoadCommands() { 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); @@ -303,7 +380,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(); @@ -339,7 +416,7 @@ void MachOWriter::EmitHeaderAndLoadCommands() { FHOut.outword(DySymTab.nextrel); FHOut.outword(DySymTab.locreloff); FHOut.outword(DySymTab.nlocrel); - + O.write((char*)&FH[0], FH.size()); } @@ -370,7 +447,7 @@ void MachOWriter::BufferSymbolAndStringTable() { // 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(), @@ -386,10 +463,11 @@ void MachOWriter::BufferSymbolAndStringTable() { // 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 } @@ -401,7 +479,7 @@ 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(), @@ -417,7 +495,7 @@ 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); @@ -451,7 +529,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); @@ -486,7 +564,7 @@ void MachOWriter::CalculateRelocations(MachOSection &MOS) { 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) { @@ -500,7 +578,7 @@ 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) { @@ -519,21 +597,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, uintptr_t Offset, +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)) { @@ -626,7 +704,7 @@ void MachOWriter::InitMem(const Constant *C, uintptr_t Offset, memset(ptr, 0, TD->getPointerSize()); else if (const GlobalValue* GV = dyn_cast(PC)) { // FIXME: what about function stubs? - mos->addRelocation(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 9f5b7c5ad31..3067ff12299 100644 --- a/lib/CodeGen/MachOWriter.h +++ b/lib/CodeGen/MachOWriter.h @@ -14,29 +14,27 @@ #ifndef MACHOWRITER_H #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 Constant; class GlobalVariable; class Mangler; class MachineRelocation; - class ObjectCodeEmitter; class MachOCodeEmitter; + class MachODySymTab; + class MachOHeader; + class MachOSection; + class MachOSym; class TargetData; class TargetMachine; + class TargetAsmInfo; + class ObjectCodeEmitter; class OutputBuffer; class raw_ostream; - /// MachOWriter - This class implements the common target-independent code for /// writing Mach-O files. Targets should derive a class from this to /// parameterize the output format. @@ -69,36 +67,30 @@ namespace llvm { /// Mang - The object used to perform name mangling for this module. /// Mangler *Mang; - - /// MachOCE - The MachineCodeEmitter object that we are exposing to emit machine - /// code for functions to the .o file. + /// MachOCE - The MachineCodeEmitter object that we are exposing to emit + /// machine code for functions to the .o file. MachOCodeEmitter *MachOCE; /// is64Bit/isLittleEndian - This information is inferred from the target /// machine directly, indicating what header values and flags to set. - bool is64Bit, isLittleEndian; // Target Asm Info - const TargetAsmInfo *TAI; /// Header - An instance of MachOHeader that we will update while we build /// the file, and then emit during finalization. - MachOHeader Header; /// doInitialization - Emit the file header and all of the global variables /// for the module to the Mach-O file. - bool doInitialization(Module &M); bool runOnMachineFunction(MachineFunction &MF); /// doFinalization - Now that the module has been completely processed, emit /// the Mach-O file to 'O'. - bool doFinalization(Module &M); private: @@ -106,85 +98,37 @@ namespace llvm { /// SectionList - This is the list of sections that we have emitted to the /// file. Once the file has been completely built, the segment load command /// SectionCommands are constructed from this info. - std::vector SectionList; /// SectionLookup - This is a mapping from section name to SectionList entry - std::map SectionLookup; - + /// GVSection - This is a mapping from a GlobalValue to a MachOSection, /// to aid in emitting relocations. - std::map GVSection; - /// GVOffset - This is a mapping from a GlobalValue to an offset from the + /// GVOffset - This is a mapping from a GlobalValue to an offset from the /// start of the section in which the GV resides, to aid in emitting /// relocations. - std::map GVOffset; /// getSection - Return the section with the specified name, creating a new /// section if one does not already exist. - MachOSection *getSection(const std::string &seg, const std::string §, - unsigned Flags = 0) { - MachOSection *MOS = SectionLookup[seg+sect]; - if (MOS) return MOS; - - MOS = new MachOSection(seg, sect); - SectionList.push_back(MOS); - MOS->Index = SectionList.size(); - MOS->flags = MachOSection::S_REGULAR | Flags; - SectionLookup[seg+sect] = MOS; - return MOS; - } - MachOSection *getTextSection(bool isCode = true) { - if (isCode) - return getSection("__TEXT", "__text", - MachOSection::S_ATTR_PURE_INSTRUCTIONS | - MachOSection::S_ATTR_SOME_INSTRUCTIONS); - else - return getSection("__TEXT", "__text"); - } - MachOSection *getBSSSection() { - return getSection("__DATA", "__bss", MachOSection::S_ZEROFILL); - } + unsigned Flags = 0); + + /// getTextSection - Return text section with different flags for code/data + MachOSection *getTextSection(bool isCode = true); + MachOSection *getDataSection() { return getSection("__DATA", "__data"); } - MachOSection *getConstSection(Constant *C) { - const ConstantArray *CVA = dyn_cast(C); - if (CVA && CVA->isCString()) - return getSection("__TEXT", "__cstring", - MachOSection::S_CSTRING_LITERALS); - - const Type *Ty = C->getType(); - if (Ty->isPrimitiveType() || Ty->isInteger()) { - unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); - switch(Size) { - default: break; // Fall through to __TEXT,__const - case 4: - return getSection("__TEXT", "__literal4", - MachOSection::S_4BYTE_LITERALS); - case 8: - return getSection("__TEXT", "__literal8", - MachOSection::S_8BYTE_LITERALS); - case 16: - return getSection("__TEXT", "__literal16", - MachOSection::S_16BYTE_LITERALS); - } - } - return getSection("__TEXT", "__const"); - } - MachOSection *getJumpTableSection() { - if (TM.getRelocationModel() == Reloc::PIC_) - return getTextSection(false); - else - return getSection("__TEXT", "__const"); - } - - /// MachOSymTab - This struct contains information about the offsets and + + MachOSection *getBSSSection(); + MachOSection *getConstSection(Constant *C); + MachOSection *getJumpTableSection(); + + /// MachOSymTab - This struct contains information about the offsets and /// size of symbol table information. /// segment. struct MachOSymTab { @@ -199,44 +143,42 @@ namespace llvm { // see enum { LC_SYMTAB = 0x02 // link-edit stab symbol table info }; - + MachOSymTab() : cmd(LC_SYMTAB), cmdsize(6 * sizeof(uint32_t)), symoff(0), nsyms(0), stroff(0), strsize(0) { } }; - + /// SymTab - The "stab" style symbol table information - MachOSymTab SymTab; + MachOSymTab SymTab; /// DySymTab - symbol table info for the dynamic link editor MachODySymTab DySymTab; protected: - + /// SymbolTable - This is the list of symbols we have emitted to the file. /// This actually gets rearranged before emission to the file (to put the /// local symbols first in the list). std::vector SymbolTable; - + /// SymT - A buffer to hold the symbol table before we write it out at the /// appropriate location in the file. - DataBuffer SymT; - + std::vector SymT; + /// StrT - A buffer to hold the string table before we write it out at the /// appropriate location in the file. - DataBuffer StrT; - + std::vector StrT; + /// PendingSyms - This is a list of externally defined symbols that we have /// been asked to emit, but have not seen a reference to. When a reference /// is seen, the symbol will move from this list to the SymbolTable. std::vector PendingGlobals; - + /// DynamicSymbolTable - This is just a vector of indices into /// SymbolTable to aid in emitting the DYSYMTAB load command. std::vector DynamicSymbolTable; - - static void InitMem(const Constant *C, - uintptr_t Offset, - const TargetData *TD, - MachOSection* mos); + + static void InitMem(const Constant *C, uintptr_t Offset, + const TargetData *TD, MachOSection* mos); private: void AddSymbolToSection(MachOSection *MOS, GlobalVariable *GV); @@ -247,25 +189,16 @@ namespace llvm { void BufferSymbolAndStringTable(); void CalculateRelocations(MachOSection &MOS); + // GetJTRelocation - Get a relocation a new BB relocation based + // on target information. MachineRelocation GetJTRelocation(unsigned Offset, - MachineBasicBlock *MBB) const { - return TM.getMachOWriterInfo()->GetJTRelocation(Offset, MBB); - } + MachineBasicBlock *MBB) const; /// GetTargetRelocation - Returns the number of relocations. - unsigned GetTargetRelocation(MachineRelocation &MR, - unsigned FromIdx, - unsigned ToAddr, - unsigned ToIndex, - OutputBuffer &RelocOut, - OutputBuffer &SecOut, - bool Scattered, - bool Extern) { - return TM.getMachOWriterInfo()->GetTargetRelocation(MR, FromIdx, ToAddr, - ToIndex, RelocOut, - SecOut, Scattered, - Extern); - } + unsigned GetTargetRelocation(MachineRelocation &MR, unsigned FromIdx, + unsigned ToAddr, unsigned ToIndex, + OutputBuffer &RelocOut, OutputBuffer &SecOut, + bool Scattered, bool Extern); }; } -- 2.34.1