forked from OSchip/llvm-project
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. llvm-svn: 74813
This commit is contained in:
parent
1fb1cf4e26
commit
5661ea68e7
|
@ -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; i<PadSize; ++i)
|
||||
Data.push_back(0);
|
||||
Data.push_back(fill);
|
||||
}
|
||||
|
||||
/// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be
|
||||
|
|
|
@ -17,14 +17,14 @@
|
|||
namespace llvm {
|
||||
|
||||
class PassManagerBase;
|
||||
class MachineCodeEmitter;
|
||||
class ObjectCodeEmitter;
|
||||
class TargetMachine;
|
||||
class raw_ostream;
|
||||
|
||||
MachineCodeEmitter *AddELFWriter(PassManagerBase &FPM, raw_ostream &O,
|
||||
TargetMachine &TM);
|
||||
MachineCodeEmitter *AddMachOWriter(PassManagerBase &FPM, raw_ostream &O,
|
||||
TargetMachine &TM);
|
||||
ObjectCodeEmitter *AddELFWriter(PassManagerBase &FPM, raw_ostream &O,
|
||||
TargetMachine &TM);
|
||||
ObjectCodeEmitter *AddMachOWriter(PassManagerBase &FPM, raw_ostream &O,
|
||||
TargetMachine &TM);
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
|
|
|
@ -74,24 +74,6 @@ public:
|
|||
/// false.
|
||||
///
|
||||
virtual bool finishFunction(MachineFunction &F) = 0;
|
||||
|
||||
/// startGVStub - This callback is invoked when the JIT needs the
|
||||
/// address of a GV (e.g. function) that has not been code generated yet.
|
||||
/// The StubSize specifies the total size required by the stub.
|
||||
///
|
||||
virtual void startGVStub(const GlobalValue* GV, unsigned StubSize,
|
||||
unsigned Alignment = 1) = 0;
|
||||
|
||||
/// startGVStub - This callback is invoked when the JIT needs the address of a
|
||||
/// GV (e.g. function) that has not been code generated yet. Buffer points to
|
||||
/// memory already allocated for this stub.
|
||||
///
|
||||
virtual void startGVStub(const GlobalValue* GV, void *Buffer,
|
||||
unsigned StubSize) = 0;
|
||||
|
||||
/// finishGVStub - This callback is invoked to terminate a GV stub.
|
||||
///
|
||||
virtual void *finishGVStub(const GlobalValue* F) = 0;
|
||||
|
||||
/// emitByte - This callback is invoked when a byte needs to be written to the
|
||||
/// output stream.
|
||||
|
@ -288,14 +270,13 @@ public:
|
|||
|
||||
/// getCurrentPCOffset - Return the offset from the start of the emitted
|
||||
/// buffer that we are currently writing to.
|
||||
uintptr_t getCurrentPCOffset() const {
|
||||
virtual uintptr_t getCurrentPCOffset() const {
|
||||
return CurBufferPtr-BufferBegin;
|
||||
}
|
||||
|
||||
/// addRelocation - Whenever a relocatable address is needed, it should be
|
||||
/// noted with this interface.
|
||||
virtual void addRelocation(const MachineRelocation &MR) = 0;
|
||||
|
||||
|
||||
/// FIXME: These should all be handled with relocations!
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ class TargetLowering;
|
|||
class TargetFrameInfo;
|
||||
class MachineCodeEmitter;
|
||||
class JITCodeEmitter;
|
||||
class ObjectCodeEmitter;
|
||||
class TargetRegisterInfo;
|
||||
class Module;
|
||||
class PassManagerBase;
|
||||
|
@ -257,6 +258,16 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
virtual bool addPassesToEmitFileFinish(PassManagerBase &,
|
||||
ObjectCodeEmitter *,
|
||||
CodeGenOpt::Level) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
@ -335,7 +346,15 @@ public:
|
|||
/// used to finish up adding passes to emit the file, if necessary.
|
||||
///
|
||||
virtual bool addPassesToEmitFileFinish(PassManagerBase &PM,
|
||||
JITCodeEmitter *MCE,
|
||||
JITCodeEmitter *JCE,
|
||||
CodeGenOpt::Level);
|
||||
|
||||
/// 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.
|
||||
///
|
||||
virtual bool addPassesToEmitFileFinish(PassManagerBase &PM,
|
||||
ObjectCodeEmitter *OCE,
|
||||
CodeGenOpt::Level);
|
||||
|
||||
/// addPassesToEmitMachineCode - Add passes to the specified pass manager to
|
||||
|
@ -432,6 +451,15 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
/// addSimpleCodeEmitter - This pass should be overridden by the target to add
|
||||
/// a code emitter (without setting flags), if supported. If this is not
|
||||
/// supported, 'true' should be returned. If DumpAsm is true, the generated
|
||||
/// assembly is printed to cerr.
|
||||
virtual bool addSimpleCodeEmitter(PassManagerBase &, CodeGenOpt::Level,
|
||||
bool /*DumpAsm*/, ObjectCodeEmitter &) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// getEnableTailMergeDefault - the default setting for -enable-tail-merge
|
||||
/// on this target. User flag overrides.
|
||||
virtual bool getEnableTailMergeDefault() const { return true; }
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#include "llvm/CodeGen/BinaryObject.h"
|
||||
#include "llvm/CodeGen/FileWriters.h"
|
||||
#include "llvm/CodeGen/MachineCodeEmitter.h"
|
||||
#include "llvm/CodeGen/ObjectCodeEmitter.h"
|
||||
#include "llvm/CodeGen/MachineCodeEmitter.h"
|
||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||
#include "llvm/Target/TargetAsmInfo.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
|
@ -54,12 +56,12 @@ using namespace llvm;
|
|||
char ELFWriter::ID = 0;
|
||||
/// AddELFWriter - Concrete function to add the ELF writer to the function pass
|
||||
/// manager.
|
||||
MachineCodeEmitter *llvm::AddELFWriter(PassManagerBase &PM,
|
||||
ObjectCodeEmitter *llvm::AddELFWriter(PassManagerBase &PM,
|
||||
raw_ostream &O,
|
||||
TargetMachine &TM) {
|
||||
ELFWriter *EW = new ELFWriter(O, TM);
|
||||
PM.add(EW);
|
||||
return &EW->getMachineCodeEmitter();
|
||||
return (ObjectCodeEmitter*) &EW->getMachineCodeEmitter();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <string>
|
||||
#include <vector>
|
||||
|
@ -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<MachineRelocation> Relocations;
|
||||
|
||||
// Constants for the section types (low 8 bits of flags field)
|
||||
// see <mach-o/loader.h>
|
||||
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 <mach-o/loader.h>
|
||||
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 <mach-o/loader.h>
|
||||
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
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "llvm/Target/TargetAsmInfo.h"
|
||||
#include "llvm/Support/Mangler.h"
|
||||
#include "llvm/Support/OutputBuffer.h"
|
||||
#include <vector>
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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<MachineJumpTableEntry> &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<MachineBasicBlock*> &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
|
||||
|
|
|
@ -11,15 +11,13 @@
|
|||
#define MACHOCODEEMITTER_H
|
||||
|
||||
#include "MachOWriter.h"
|
||||
#include "llvm/CodeGen/MachineCodeEmitter.h"
|
||||
#include <vector>
|
||||
|
||||
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<MachineRelocation> 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<uintptr_t> CPLocations;
|
||||
|
||||
/// CPSections - This is a map of constant pool indices to the MachOSection
|
||||
/// containing the constant pool entry for that index.
|
||||
std::vector<unsigned> CPSections;
|
||||
std::map<uint64_t, uintptr_t> Labels;
|
||||
|
||||
/// JTLocations - This is a map of jump table indices to offsets from the
|
||||
/// start of the section for that jump table index.
|
||||
std::vector<uintptr_t> 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<uintptr_t> MBBLocations;
|
||||
|
||||
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
|
||||
|
|
|
@ -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<MachOSection*>::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<MachOSection*>::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<MachOSection*>::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<MachOSection*>::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<MachOSection*>::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<GlobalValue*>::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<MachOSym>::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<MachOSym>::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<MachOSym>::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<MachineRelocation> 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<MachineRelocation> &MRs) {
|
||||
void MachOWriter::InitMem(const Constant *C, uintptr_t Offset,
|
||||
const TargetData *TD, MachOSection* mos) {
|
||||
typedef std::pair<const Constant*, intptr_t> CPair;
|
||||
std::vector<CPair> 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<UndefValue>(PC)) {
|
||||
continue;
|
||||
} else if (const ConstantVector *CP = dyn_cast<ConstantVector>(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<GlobalValue>(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<GlobalValue*>(GV),
|
||||
ScatteredOffset));
|
||||
|
|
|
@ -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 <vector>
|
||||
#include <map>
|
||||
|
||||
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<ObjectCodeEmitter*>(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<unsigned> 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<MachineRelocation> &MRs);
|
||||
MachOSection* mos);
|
||||
|
||||
private:
|
||||
void AddSymbolToSection(MachOSection *MOS, GlobalVariable *GV);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<MachineCodeEmitter>(TM, MCE);
|
||||
}
|
||||
FunctionPass *createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM,
|
||||
JITCodeEmitter &JCE) {
|
||||
FunctionPass *llvm::createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM,
|
||||
JITCodeEmitter &JCE) {
|
||||
return new Emitter<JITCodeEmitter>(TM, JCE);
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
FunctionPass *llvm::createARMObjectCodeEmitterPass(ARMBaseTargetMachine &TM,
|
||||
ObjectCodeEmitter &OCE) {
|
||||
return new Emitter<ObjectCodeEmitter>(TM, OCE);
|
||||
}
|
||||
|
||||
template<class CodeEmitter>
|
||||
bool Emitter<CodeEmitter>::runOnMachineFunction(MachineFunction &MF) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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<JITCodeEmitter>(TM, JCE);
|
||||
}
|
||||
FunctionPass *llvm::createAlphaObjectCodeEmitterPass(AlphaTargetMachine &TM,
|
||||
ObjectCodeEmitter &OCE) {
|
||||
return new Emitter<ObjectCodeEmitter>(TM, OCE);
|
||||
}
|
||||
|
||||
template <class CodeEmitter>
|
||||
bool Emitter<CodeEmitter>::runOnMachineFunction(MachineFunction &MF) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<MachineCodeEmitter>(TM, MCE);
|
||||
|
@ -101,6 +103,11 @@ FunctionPass *llvm::createPPCJITCodeEmitterPass(PPCTargetMachine &TM,
|
|||
return new Emitter<JITCodeEmitter>(TM, JCE);
|
||||
}
|
||||
|
||||
FunctionPass *llvm::createPPCObjectCodeEmitterPass(PPCTargetMachine &TM,
|
||||
ObjectCodeEmitter &OCE) {
|
||||
return new Emitter<ObjectCodeEmitter>(TM, OCE);
|
||||
}
|
||||
|
||||
template <class CodeEmitter>
|
||||
bool Emitter<CodeEmitter>::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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<class CodeEmitter>
|
|||
/// 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<MachineCodeEmitter>(TM, MCE);
|
||||
}
|
||||
FunctionPass *createX86JITCodeEmitterPass(X86TargetMachine &TM,
|
||||
JITCodeEmitter &JCE) {
|
||||
FunctionPass *llvm::createX86JITCodeEmitterPass(X86TargetMachine &TM,
|
||||
JITCodeEmitter &JCE) {
|
||||
return new Emitter<JITCodeEmitter>(TM, JCE);
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
FunctionPass *llvm::createX86ObjectCodeEmitterPass(X86TargetMachine &TM,
|
||||
ObjectCodeEmitter &OCE) {
|
||||
return new Emitter<ObjectCodeEmitter>(TM, OCE);
|
||||
}
|
||||
|
||||
template<class CodeEmitter>
|
||||
bool Emitter<CodeEmitter>::runOnMachineFunction(MachineFunction &MF) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue