aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorNate Begeman <natebegeman@mac.com>2006-08-23 21:08:52 +0000
committerNate Begeman <natebegeman@mac.com>2006-08-23 21:08:52 +0000
commiteb883af3903286ac20f5bbf549c555c9ef961e14 (patch)
tree876fc716e1d1cfc6c0341ffd7a5a750b17c4d136 /lib
parent81bc5088dd783421456c298b5fcc741c45acbea0 (diff)
downloadexternal_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.cpp428
-rw-r--r--lib/Target/PowerPC/PPC.h9
-rw-r--r--lib/Target/PowerPC/PPCCodeEmitter.cpp56
-rw-r--r--lib/Target/PowerPC/PPCMachOWriter.cpp41
-rw-r--r--lib/Target/PowerPC/PPCTargetMachine.cpp26
-rw-r--r--lib/Target/X86/X86TargetMachine.cpp2
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;
}