diff options
author | Nate Begeman <natebegeman@mac.com> | 2006-08-23 21:08:52 +0000 |
---|---|---|
committer | Nate Begeman <natebegeman@mac.com> | 2006-08-23 21:08:52 +0000 |
commit | eb883af3903286ac20f5bbf549c555c9ef961e14 (patch) | |
tree | 876fc716e1d1cfc6c0341ffd7a5a750b17c4d136 /lib | |
parent | 81bc5088dd783421456c298b5fcc741c45acbea0 (diff) | |
download | external_llvm-eb883af3903286ac20f5bbf549c555c9ef961e14.zip external_llvm-eb883af3903286ac20f5bbf549c555c9ef961e14.tar.gz external_llvm-eb883af3903286ac20f5bbf549c555c9ef961e14.tar.bz2 |
Initial checkin of the Mach-O emitter. There's plenty of fixmes, but it
does emit linkable .o files in very simple cases.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29850 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/MachOWriter.cpp | 428 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPC.h | 9 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCCodeEmitter.cpp | 56 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCMachOWriter.cpp | 41 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCTargetMachine.cpp | 26 | ||||
-rw-r--r-- | lib/Target/X86/X86TargetMachine.cpp | 2 |
6 files changed, 518 insertions, 44 deletions
diff --git a/lib/CodeGen/MachOWriter.cpp b/lib/CodeGen/MachOWriter.cpp new file mode 100644 index 0000000..e3228cb --- /dev/null +++ b/lib/CodeGen/MachOWriter.cpp @@ -0,0 +1,428 @@ +//===-- MachOWriter.cpp - Target-independent Mach-O Writer code -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Nate Begeman and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the target-independent Mach-O writer. This file writes +// out the Mach-O file in the following order: +// +// #1 FatHeader (universal-only) +// #2 FatArch (universal-only, 1 per universal arch) +// Per arch: +// #3 Header +// #4 Load Commands +// #5 Sections +// #6 Relocations +// #7 Symbols +// #8 Strings +// +//===----------------------------------------------------------------------===// + +#include "llvm/Module.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/CodeGen/MachOWriter.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetJITInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Mangler.h" +#include <iostream> +using namespace llvm; + +//===----------------------------------------------------------------------===// +// MachOCodeEmitter Implementation +//===----------------------------------------------------------------------===// + +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 { + MachOWriter &MOW; + + /// MOS - The current section we're writing to + MachOWriter::MachOSection *MOS; + + /// Relocations - These are the relocations that the function needs, as + /// emitted. + std::vector<MachineRelocation> Relocations; + + /// 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<intptr_t> MBBLocations; + + public: + MachOCodeEmitter(MachOWriter &mow) : MOW(mow) {} + + void startFunction(MachineFunction &F); + bool finishFunction(MachineFunction &F); + + void addRelocation(const MachineRelocation &MR) { + Relocations.push_back(MR); + } + + virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { + if (MBBLocations.size() <= (unsigned)MBB->getNumber()) + MBBLocations.resize((MBB->getNumber()+1)*2); + MBBLocations[MBB->getNumber()] = getCurrentPCValue(); + } + + virtual intptr_t getConstantPoolEntryAddress(unsigned Index) const { + assert(0 && "CP not implementated yet!"); + return 0; + } + virtual intptr_t getJumpTableEntryAddress(unsigned Index) const { + assert(0 && "JT not implementated yet!"); + return 0; + } + + virtual intptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { + assert(MBBLocations.size() > (unsigned)MBB->getNumber() && + MBBLocations[MBB->getNumber()] && "MBB not emitted!"); + return MBBLocations[MBB->getNumber()]; + } + + /// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE! + void startFunctionStub(unsigned StubSize) { + assert(0 && "JIT specific function called!"); + abort(); + } + void *finishFunctionStub(const Function *F) { + assert(0 && "JIT specific function called!"); + abort(); + return 0; + } + }; +} + +/// startFunction - This callback is invoked when a new machine function is +/// about to be emitted. +void MachOCodeEmitter::startFunction(MachineFunction &F) { + // Align the output buffer to the appropriate alignment, power of 2. + // FIXME: GENERICIZE!! + unsigned Align = 4; + + // Get the Mach-O Section that this function belongs in. + MOS = &MOW.getTextSection(); + + // FIXME: better memory management + MOS->SectionData.reserve(4096); + BufferBegin = &(MOS->SectionData[0]); + BufferEnd = BufferBegin + MOS->SectionData.capacity(); + CurBufferPtr = BufferBegin + MOS->size; + + // Upgrade the section alignment if required. + if (MOS->align < Align) MOS->align = Align; + + // Make sure we only relocate to this function's MBBs. + MBBLocations.clear(); +} + +/// finishFunction - This callback is invoked after the function is completely +/// finished. +bool MachOCodeEmitter::finishFunction(MachineFunction &F) { + MOS->size += CurBufferPtr - BufferBegin; + + // Get a symbol for the function to add to the symbol table + MachOWriter::MachOSym FnSym(F.getFunction(), MOS->Index); + + // Figure out the binding (linkage) of the symbol. + switch (F.getFunction()->getLinkage()) { + default: + // appending linkage is illegal for functions. + assert(0 && "Unknown linkage type!"); + case GlobalValue::ExternalLinkage: + FnSym.n_type = MachOWriter::MachOSym::N_SECT | MachOWriter::MachOSym::N_EXT; + break; + case GlobalValue::InternalLinkage: + FnSym.n_type = MachOWriter::MachOSym::N_SECT; + break; + } + + // Resolve the function's relocations either to concrete pointers in the case + // of branches from one block to another, or to target relocation entries. + for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { + MachineRelocation &MR = Relocations[i]; + if (MR.isBasicBlock()) { + void *MBBAddr = (void *)getMachineBasicBlockAddress(MR.getBasicBlock()); + MR.setResultPointer(MBBAddr); + MOW.TM.getJITInfo()->relocate(BufferBegin, &MR, 1, 0); + // FIXME: we basically want the JITInfo relocate() function to rewrite + // this guy right now, so we just write the correct displacement + // to the file. + } else { + // isString | isGV | isCPI | isJTI + // FIXME: do something smart here. We won't be able to relocate these + // until the sections are all layed out, but we still need to + // record them. Maybe emit TargetRelocations and then resolve + // those at file writing time? + std::cerr << "whee!\n"; + } + } + Relocations.clear(); + + // Finally, add it to the symtab. + MOW.SymbolTable.push_back(FnSym); + return false; +} + +//===----------------------------------------------------------------------===// +// MachOWriter Implementation +//===----------------------------------------------------------------------===// + +MachOWriter::MachOWriter(std::ostream &o, TargetMachine &tm) : O(o), TM(tm) { + // FIXME: set cpu type and cpu subtype somehow from TM + is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; + isLittleEndian = TM.getTargetData()->isLittleEndian(); + + // Create the machine code emitter object for this target. + MCE = new MachOCodeEmitter(*this); +} + +MachOWriter::~MachOWriter() { + delete MCE; +} + +void MachOWriter::EmitGlobal(GlobalVariable *GV) { + // FIXME: do something smart here. +} + + +bool MachOWriter::runOnMachineFunction(MachineFunction &MF) { + // Nothing to do here, this is all done through the MCE object. + return false; +} + +bool MachOWriter::doInitialization(Module &M) { + // Set the magic value, now that we know the pointer size and endianness + Header.setMagic(isLittleEndian, is64Bit); + + // Set the file type + // FIXME: this only works for object files, we do not support the creation + // of dynamic libraries or executables at this time. + Header.filetype = MachOHeader::MH_OBJECT; + + Mang = new Mangler(M); + return false; +} + +/// doFinalization - Now that the module has been completely processed, emit +/// the Mach-O file to 'O'. +bool MachOWriter::doFinalization(Module &M) { + // 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(); + + // Emit the text and data sections. + EmitSections(); + + // Emit the relocation entry data for each section. + // FIXME: presumably this should be a virtual method, since different targets + // have different relocation types. + EmitRelocations(); + + // Emit the symbol table. + // FIXME: we don't handle debug info yet, we should probably do that. + EmitSymbolTable(); + + // Emit the string table for the sections we have. + EmitStringTable(); + + // We are done with the abstract symbols. + SectionList.clear(); + SymbolTable.clear(); + DynamicSymbolTable.clear(); + + // Release the name mangler object. + delete Mang; Mang = 0; + return false; +} + +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.nsects * SectionList.begin()->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; + outword(FH, Header.magic); + outword(FH, Header.cputype); + outword(FH, Header.cpusubtype); + outword(FH, Header.filetype); + outword(FH, Header.ncmds); + outword(FH, Header.sizeofcmds); + outword(FH, Header.flags); + if (is64Bit) + outword(FH, Header.reserved); + + // Step #4: Finish filling in the segment load command and write it out + for (std::list<MachOSection>::iterator I = SectionList.begin(), + E = SectionList.end(); I != E; ++I) + SEG.filesize += I->size; + SEG.vmsize = SEG.filesize; + SEG.fileoff = Header.cmdSize(is64Bit) + Header.sizeofcmds; + + outword(FH, SEG.cmd); + outword(FH, SEG.cmdsize); + outstring(FH, SEG.segname, 16); + outaddr(FH, SEG.vmaddr); + outaddr(FH, SEG.vmsize); + outaddr(FH, SEG.fileoff); + outaddr(FH, SEG.filesize); + outword(FH, SEG.maxprot); + outword(FH, SEG.initprot); + outword(FH, SEG.nsects); + outword(FH, SEG.flags); + + // Step #5: Write out the section commands for each section + for (std::list<MachOSection>::iterator I = SectionList.begin(), + E = SectionList.end(); I != E; ++I) { + I->offset = SEG.fileoff; // FIXME: separate offset + outstring(FH, I->sectname, 16); + outstring(FH, I->segname, 16); + outaddr(FH, I->addr); + outaddr(FH, I->size); + outword(FH, I->offset); + outword(FH, I->align); + outword(FH, I->reloff); + outword(FH, I->nreloc); + outword(FH, I->flags); + outword(FH, I->reserved1); + outword(FH, I->reserved2); + if (is64Bit) + outword(FH, I->reserved3); + } + + // Step #6: Emit LC_SYMTAB/LC_DYSYMTAB load commands + // FIXME: We'll need to scan over the symbol table and possibly do the sort + // here so that we can set the proper indices in the dysymtab load command for + // the index and number of external symbols defined in this module. + // FIXME: We'll also need to scan over all the symbols so that we can + // calculate the size of the string table. + // FIXME: add size of relocs + SymTab.symoff = SEG.fileoff + SEG.filesize; + SymTab.nsyms = SymbolTable.size(); + SymTab.stroff = SymTab.symoff + SymTab.nsyms * MachOSym::entrySize(); + SymTab.strsize = 10; + outword(FH, SymTab.cmd); + outword(FH, SymTab.cmdsize); + outword(FH, SymTab.symoff); + outword(FH, SymTab.nsyms); + outword(FH, SymTab.stroff); + outword(FH, SymTab.strsize); + + // FIXME: set DySymTab fields appropriately + outword(FH, DySymTab.cmd); + outword(FH, DySymTab.cmdsize); + outword(FH, DySymTab.ilocalsym); + outword(FH, DySymTab.nlocalsym); + outword(FH, DySymTab.iextdefsym); + outword(FH, DySymTab.nextdefsym); + outword(FH, DySymTab.iundefsym); + outword(FH, DySymTab.nundefsym); + outword(FH, DySymTab.tocoff); + outword(FH, DySymTab.ntoc); + outword(FH, DySymTab.modtaboff); + outword(FH, DySymTab.nmodtab); + outword(FH, DySymTab.extrefsymoff); + outword(FH, DySymTab.nextrefsyms); + outword(FH, DySymTab.indirectsymoff); + outword(FH, DySymTab.nindirectsyms); + outword(FH, DySymTab.extreloff); + outword(FH, DySymTab.nextrel); + outword(FH, DySymTab.locreloff); + outword(FH, 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::list<MachOSection>::iterator I = SectionList.begin(), + E = SectionList.end(); I != E; ++I) { + O.write((char*)&I->SectionData[0], I->size); + } +} + +void MachOWriter::EmitRelocations() { + // FIXME: this should probably be a pure virtual function, since the + // relocation types and layout of the relocations themselves are target + // specific. +} + +/// EmitSymbolTable - 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::EmitSymbolTable() { + // The order of the symbol table is: + // local symbols + // defined external symbols (sorted by name) + // undefined external symbols (sorted by name) + DataBuffer ST; + + // FIXME: enforce the above ordering, presumably by sorting by name, + // then partitioning twice. + unsigned stringIndex; + for (std::vector<MachOSym>::iterator I = SymbolTable.begin(), + E = SymbolTable.end(); I != E; ++I) { + // FIXME: remove when we actually calculate these correctly + I->n_strx = 1; + StringTable.push_back(Mang->getValueName(I->GV)); + // Emit nlist to buffer + outword(ST, I->n_strx); + outbyte(ST, I->n_type); + outbyte(ST, I->n_sect); + outhalf(ST, I->n_desc); + outaddr(ST, I->n_value); + } + + O.write((char*)&ST[0], ST.size()); +} + +/// EmitStringTable - This method adds and emits a section for the Mach-O +/// string table. +void MachOWriter::EmitStringTable() { + // The order of the string table is: + // strings for external symbols + // strings for local symbols + // This is the symbol table, but backwards. This allows us to avoid a sorting + // the symbol table again; all we have to do is use a reverse iterator. + DataBuffer ST; + + // Write out a leading zero byte when emitting string table, for n_strx == 0 + // which means an empty string. + outbyte(ST, 0); + + for (std::vector<std::string>::iterator I = StringTable.begin(), + E = StringTable.end(); I != E; ++I) { + // FIXME: do not arbitrarily cap symbols to 16 characters + // FIXME: do something more efficient than outstring + outstring(ST, *I, 16); + } + O.write((char*)&ST[0], ST.size()); +} diff --git a/lib/Target/PowerPC/PPC.h b/lib/Target/PowerPC/PPC.h index 5e8e15c..f34b9b0 100644 --- a/lib/Target/PowerPC/PPC.h +++ b/lib/Target/PowerPC/PPC.h @@ -19,11 +19,18 @@ namespace llvm { -class FunctionPass; class PPCTargetMachine; +class PassManager; +class FunctionPass; +class MachineCodeEmitter; + FunctionPass *createPPCBranchSelectionPass(); FunctionPass *createPPCISelDag(PPCTargetMachine &TM); FunctionPass *createDarwinAsmPrinter(std::ostream &OS, PPCTargetMachine &TM); +FunctionPass *createPPCCodeEmitterPass(PPCTargetMachine &TM, + MachineCodeEmitter &MCE); +void addPPCMachOObjectWriterPass(PassManager &FPM, std::ostream &o, + PPCTargetMachine &tm); } // end namespace llvm; // GCC #defines PPC on Linux but we use it as our namespace name diff --git a/lib/Target/PowerPC/PPCCodeEmitter.cpp b/lib/Target/PowerPC/PPCCodeEmitter.cpp index 49d3f25..85697f9 100644 --- a/lib/Target/PowerPC/PPCCodeEmitter.cpp +++ b/lib/Target/PowerPC/PPCCodeEmitter.cpp @@ -21,7 +21,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/Support/Debug.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/Visibility.h" #include "llvm/Target/TargetOptions.h" #include <iostream> @@ -62,19 +62,11 @@ namespace { }; } -/// 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 -/// of functions. This method should returns true if machine code emission is -/// not supported. -/// -bool PPCTargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM, - MachineCodeEmitter &MCE) { - // Machine code emitter pass for PowerPC - PM.add(new PPCCodeEmitter(*this, MCE)); - // Delete machine code for this function after emitting it - PM.add(createMachineCodeDeleter()); - return false; +/// createPPCCodeEmitterPass - Return a pass that emits the collected PPC code +/// to the specified MCE object. +FunctionPass *llvm::createPPCCodeEmitterPass(PPCTargetMachine &TM, + MachineCodeEmitter &MCE) { + return new PPCCodeEmitter(TM, MCE); } #ifdef __APPLE__ @@ -132,7 +124,8 @@ int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) { } } else if (MO.isImmediate()) { rv = MO.getImmedValue(); - } else if (MO.isGlobalAddress() || MO.isExternalSymbol()) { + } else if (MO.isGlobalAddress() || MO.isExternalSymbol() || + MO.isConstantPoolIndex() || MO.isJumpTableIndex()) { unsigned Reloc = 0; if (MI.getOpcode() == PPC::BL) Reloc = PPC::reloc_pcrel_bx; @@ -141,6 +134,7 @@ int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) { default: DEBUG(MI.dump()); assert(0 && "Unknown instruction for relocation!"); case PPC::LIS: case PPC::LIS8: + case PPC::ADDIS: case PPC::ADDIS8: Reloc = PPC::reloc_absolute_high; // Pointer to symbol break; @@ -176,9 +170,17 @@ int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) { if (MO.isGlobalAddress()) MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, MO.getGlobal(), 0)); - else + else if (MO.isExternalSymbol()) MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), Reloc, MO.getSymbolName(), 0)); + else if (MO.isConstantPoolIndex()) + MCE.addRelocation(MachineRelocation::getConstPool( + MCE.getCurrentPCOffset(), + Reloc, MO.getConstantPoolIndex(), 0)); + else // isJumpTableIndex + MCE.addRelocation(MachineRelocation::getJumpTable( + MCE.getCurrentPCOffset(), + Reloc, MO.getJumpTableIndex(), 0)); } else if (MO.isMachineBasicBlock()) { unsigned Reloc = 0; unsigned Opcode = MI.getOpcode(); @@ -190,28 +192,6 @@ int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) { MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), Reloc, MO.getMachineBasicBlock())); - } else if (MO.isConstantPoolIndex() || MO.isJumpTableIndex()) { - if (MO.isConstantPoolIndex()) - rv = MCE.getConstantPoolEntryAddress(MO.getConstantPoolIndex()); - else - rv = MCE.getJumpTableEntryAddress(MO.getJumpTableIndex()); - - unsigned Opcode = MI.getOpcode(); - if (Opcode == PPC::LIS || Opcode == PPC::LIS8 || - Opcode == PPC::ADDIS || Opcode == PPC::ADDIS8) { - // lis wants hi16(addr) - if ((short)rv < 0) rv += 1 << 16; - rv >>= 16; - } else if (Opcode == PPC::LWZ || Opcode == PPC::LWZ8 || - Opcode == PPC::LA || - Opcode == PPC::LI || Opcode == PPC::LI8 || - Opcode == PPC::LFS || Opcode == PPC::LFD) { - // These load opcodes want lo16(addr) - rv &= 0xffff; - } else { - MI.dump(); - assert(0 && "Unknown constant pool or jump table using instruction!"); - } } else { std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n"; abort(); diff --git a/lib/Target/PowerPC/PPCMachOWriter.cpp b/lib/Target/PowerPC/PPCMachOWriter.cpp new file mode 100644 index 0000000..29f8238 --- /dev/null +++ b/lib/Target/PowerPC/PPCMachOWriter.cpp @@ -0,0 +1,41 @@ +//===-- PPCMachOWriter.cpp - Emit a Mach-O file for the PowerPC backend ---===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Nate Begeman and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a Mach-O writer for the PowerPC backend. The public +// interface to this file is the createPPCMachOObjectWriterPass function. +// +//===----------------------------------------------------------------------===// + +#include "PPCTargetMachine.h" +#include "llvm/PassManager.h" +#include "llvm/CodeGen/MachOWriter.h" +#include "llvm/Support/Visibility.h" +using namespace llvm; + +namespace { + class VISIBILITY_HIDDEN PPCMachOWriter : public MachOWriter { + public: + PPCMachOWriter(std::ostream &O, PPCTargetMachine &TM) : MachOWriter(O, TM) { + // FIMXE: choose ppc64 when appropriate + Header.cputype = MachOHeader::CPU_TYPE_POWERPC; + Header.cpusubtype = MachOHeader::CPU_SUBTYPE_POWERPC_ALL; + } + + }; +} + +/// addPPCMachOObjectWriterPass - Returns a pass that outputs the generated code +/// as a Mach-O object file. +/// +void llvm::addPPCMachOObjectWriterPass(PassManager &FPM, + std::ostream &O, PPCTargetMachine &TM) { + PPCMachOWriter *EW = new PPCMachOWriter(O, TM); + FPM.add(EW); + FPM.add(createPPCCodeEmitterPass(TM, EW->getMachineCodeEmitter())); +} diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp index deb479a..e360f37 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -109,11 +109,11 @@ PPC64TargetMachine::PPC64TargetMachine(const Module &M, const std::string &FS) /// addPassesToEmitFile - Add passes to the specified pass manager to implement /// a static compiler for this target. /// -bool PPCTargetMachine::addPassesToEmitFile(PassManager &PM, - std::ostream &Out, +bool PPCTargetMachine::addPassesToEmitFile(PassManager &PM, std::ostream &Out, CodeGenFileType FileType, bool Fast) { - if (FileType != TargetMachine::AssemblyFile) return true; + if (FileType != TargetMachine::AssemblyFile && + FileType != TargetMachine::ObjectFile) return true; // Run loop strength reduction before anything else. if (!Fast) PM.add(createLoopStrengthReducePass(&TLInfo)); @@ -146,7 +146,11 @@ bool PPCTargetMachine::addPassesToEmitFile(PassManager &PM, // Must run branch selection immediately preceding the asm printer PM.add(createPPCBranchSelectionPass()); - PM.add(createDarwinAsmPrinter(Out, *this)); + if (FileType == TargetMachine::AssemblyFile) + PM.add(createDarwinAsmPrinter(Out, *this)); + else + // FIXME: support PPC ELF files at some point + addPPCMachOObjectWriterPass(PM, Out, *this); PM.add(createMachineCodeDeleter()); return false; @@ -184,3 +188,17 @@ void PPCJITInfo::addPassesToJITCompile(FunctionPassManager &PM) { PM.add(createMachineFunctionPrinterPass(&std::cerr)); } +/// 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 +/// of functions. This method should returns true if machine code emission is +/// not supported. +/// +bool PPCTargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM, + MachineCodeEmitter &MCE) { + // Machine code emitter pass for PowerPC + PM.add(createPPCCodeEmitterPass(*this, MCE)); + // Delete machine code for this function after emitting it + PM.add(createMachineCodeDeleter()); + return false; +} diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index 90175ac..9616dc1 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -136,7 +136,7 @@ bool X86TargetMachine::addPassesToEmitFile(PassManager &PM, std::ostream &Out, case TargetMachine::ObjectFile: // FIXME: We only support emission of ELF files for now, this should check // the target triple and decide on the format to write (e.g. COFF on - // win32). + // win32 or Mach-O on darwin). addX86ELFObjectWriterPass(PM, Out, *this); break; } |