#ifndef LLVM_CODEGEN_MACHOWRITER_H
#define LLVM_CODEGEN_MACHOWRITER_H
+#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineRelocation.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetMachOWriterInfo.h"
namespace llvm {
class GlobalVariable;
class Mangler;
class MachineCodeEmitter;
class MachOCodeEmitter;
+ class OutputBuffer;
/// MachOSym - This struct contains information about each symbol that is
/// added to logical symbol table for the module. This is eventually
MachineCodeEmitter &getMachineCodeEmitter() const {
return *(MachineCodeEmitter*)MCE;
}
+ virtual ~MachOWriter();
- ~MachOWriter();
+ virtual const char *getPassName() const {
+ return "Mach-O Writer";
+ }
typedef std::vector<unsigned char> DataBuffer;
-
protected:
MachOWriter(std::ostream &O, TargetMachine &TM);
/// specific architecture type/subtype pair that is emitted to the file.
struct MachOHeader {
uint32_t magic; // mach magic number identifier
- uint32_t cputype; // cpu specifier
- uint32_t cpusubtype; // machine specifier
uint32_t filetype; // type of file
uint32_t ncmds; // number of load commands
uint32_t sizeofcmds; // the size of all the load commands
/// up for emission to the file.
DataBuffer HeaderData;
- // The various CPU_TYPE_* constants are already defined by at least one
- // system header file and create compilation errors if not respected.
-#if !defined(CPU_TYPE_I386)
-#define CPU_TYPE_I386 7
-#endif
-#if !defined(CPU_TYPE_X86_64)
-#define CPU_TYPE_X86_64 (CPU_TYPE_I386 | 0x1000000)
-#endif
-#if !defined(CPU_TYPE_ARM)
-#define CPU_TYPE_ARM 12
-#endif
-#if !defined(CPU_TYPE_SPARC)
-#define CPU_TYPE_SPARC 14
-#endif
-#if !defined(CPU_TYPE_POWERPC)
-#define CPU_TYPE_POWERPC 18
-#endif
-#if !defined(CPU_TYPE_POWERPC64)
-#define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | 0x1000000)
-#endif
-
- // Constants for the cputype field
- // see <mach/machine.h>
- enum { HDR_CPU_TYPE_I386 = CPU_TYPE_I386,
- HDR_CPU_TYPE_X86_64 = CPU_TYPE_X86_64,
- HDR_CPU_TYPE_ARM = CPU_TYPE_ARM,
- HDR_CPU_TYPE_SPARC = CPU_TYPE_SPARC,
- HDR_CPU_TYPE_POWERPC = CPU_TYPE_POWERPC,
- HDR_CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC64
- };
-
-#if !defined(CPU_SUBTYPE_I386_ALL)
-#define CPU_SUBTYPE_I386_ALL 3
-#endif
-#if !defined(CPU_SUBTYPE_X86_64_ALL)
-#define CPU_SUBTYPE_X86_64_ALL 3
-#endif
-#if !defined(CPU_SUBTYPE_ARM_ALL)
-#define CPU_SUBTYPE_ARM_ALL 0
-#endif
-#if !defined(CPU_SUBTYPE_SPARC_ALL)
-#define CPU_SUBTYPE_SPARC_ALL 0
-#endif
-#if !defined(CPU_SUBTYPE_POWERPC_ALL)
-#define CPU_SUBTYPE_POWERPC_ALL 0
-
-#endif
- // Constants for the cpusubtype field
- // see <mach/machine.h>
- enum { HDR_CPU_SUBTYPE_I386_ALL = CPU_SUBTYPE_I386_ALL,
- HDR_CPU_SUBTYPE_X86_64_ALL = CPU_SUBTYPE_X86_64_ALL,
- HDR_CPU_SUBTYPE_ARM_ALL = CPU_SUBTYPE_ARM_ALL,
- HDR_CPU_SUBTYPE_SPARC_ALL = CPU_SUBTYPE_SPARC_ALL,
- HDR_CPU_SUBTYPE_POWERPC_ALL = CPU_SUBTYPE_POWERPC_ALL
- };
-
// Constants for the filetype field
// see <mach-o/loader.h> for additional info on the various types
enum { MH_OBJECT = 1, // relocatable object file
// stack execution privilege. Only used in MH_EXECUTE filetype
};
- MachOHeader() : magic(0), cputype(0), cpusubtype(0), filetype(0),
- ncmds(0), sizeofcmds(0), flags(0), reserved(0) { }
+ MachOHeader() : magic(0), filetype(0), ncmds(0), sizeofcmds(0), flags(0),
+ reserved(0) { }
/// cmdSize - This routine returns the size of the MachOSection as written
/// to disk, depending on whether the destination is a 64 bit Mach-O file.
initprot(VM_PROT_ALL), nsects(0), flags(0) { }
};
- /// MachORelocation - This struct contains information about each relocation
- /// that needs to be emitted to the file.
- /// see <mach-o/reloc.h>
- struct MachORelocation {
- uint32_t r_address; // offset in the section to what is being relocated
- uint32_t r_symbolnum; // symbol index if r_extern == 1 else section index
- bool r_pcrel; // was relocated pc-relative already
- uint8_t r_length; // length = 2 ^ r_length
- bool r_extern; //
- uint8_t r_type; // if not 0, machine-specific relocation type.
-
- uint32_t getPackedFields() {
- return (r_symbolnum << 8) | (r_pcrel << 7) | ((r_length & 3) << 5) |
- (r_extern << 4) | (r_type & 15);
- }
-
- MachORelocation(uint32_t addr, uint32_t index, bool pcrel, uint8_t len,
- bool ext, uint8_t type) : r_address(addr),
- r_symbolnum(index), r_pcrel(pcrel), r_length(len), r_extern(ext),
- r_type(type) {}
- };
-
/// MachOSection - This struct contains information about each section in a
/// particular segment that is emitted to the file. This is eventually
/// turned into the SectionCommand in the load command for a particlar
MachOSection *getDataSection() {
return getSection("__DATA", "__data");
}
- MachOSection *getConstSection(const Type *Ty) {
- // FIXME: support cstring literals and pointer literal
- if (Ty->isPrimitiveType() || Ty->isIntegral()) {
+ MachOSection *getConstSection(Constant *C) {
+ const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
+ if (CVA && CVA->isCString())
+ return getSection("__TEXT", "__cstring",
+ MachOSection::S_CSTRING_LITERALS);
+
+ const Type *Ty = C->getType();
+ if (Ty->isPrimitiveType() || Ty->isInteger()) {
unsigned Size = TM.getTargetData()->getTypeSize(Ty);
switch(Size) {
default: break; // Fall through to __TEXT,__const
/// SymbolTable to aid in emitting the DYSYMTAB load command.
std::vector<unsigned> DynamicSymbolTable;
- // align - Emit padding into the file until the current output position is
- // aligned to the specified power of two boundary.
- static void align(DataBuffer &Output, unsigned Boundary) {
- assert(Boundary && (Boundary & (Boundary-1)) == 0 &&
- "Must align to 2^k boundary");
- size_t Size = Output.size();
- if (Size & (Boundary-1)) {
- // Add padding to get alignment to the correct place.
- size_t Pad = Boundary-(Size & (Boundary-1));
- Output.resize(Size+Pad);
- }
- }
-
- void outbyte(DataBuffer &Output, unsigned char X) {
- Output.push_back(X);
- }
- void outhalf(DataBuffer &Output, unsigned short X) {
- if (isLittleEndian) {
- Output.push_back(X&255);
- Output.push_back(X >> 8);
- } else {
- Output.push_back(X >> 8);
- Output.push_back(X&255);
- }
- }
- void outword(DataBuffer &Output, unsigned X) {
- if (isLittleEndian) {
- Output.push_back((X >> 0) & 255);
- Output.push_back((X >> 8) & 255);
- Output.push_back((X >> 16) & 255);
- Output.push_back((X >> 24) & 255);
- } else {
- Output.push_back((X >> 24) & 255);
- Output.push_back((X >> 16) & 255);
- Output.push_back((X >> 8) & 255);
- Output.push_back((X >> 0) & 255);
- }
- }
- void outxword(DataBuffer &Output, uint64_t X) {
- if (isLittleEndian) {
- Output.push_back(unsigned(X >> 0) & 255);
- Output.push_back(unsigned(X >> 8) & 255);
- Output.push_back(unsigned(X >> 16) & 255);
- Output.push_back(unsigned(X >> 24) & 255);
- Output.push_back(unsigned(X >> 32) & 255);
- Output.push_back(unsigned(X >> 40) & 255);
- Output.push_back(unsigned(X >> 48) & 255);
- Output.push_back(unsigned(X >> 56) & 255);
- } else {
- Output.push_back(unsigned(X >> 56) & 255);
- Output.push_back(unsigned(X >> 48) & 255);
- Output.push_back(unsigned(X >> 40) & 255);
- Output.push_back(unsigned(X >> 32) & 255);
- Output.push_back(unsigned(X >> 24) & 255);
- Output.push_back(unsigned(X >> 16) & 255);
- Output.push_back(unsigned(X >> 8) & 255);
- Output.push_back(unsigned(X >> 0) & 255);
- }
- }
- void outaddr32(DataBuffer &Output, unsigned X) {
- outword(Output, X);
- }
- void outaddr64(DataBuffer &Output, uint64_t X) {
- outxword(Output, X);
- }
- void outaddr(DataBuffer &Output, uint64_t X) {
- if (!is64Bit)
- outword(Output, (unsigned)X);
- else
- outxword(Output, X);
- }
- void outstring(DataBuffer &Output, std::string &S, unsigned Length) {
- unsigned len_to_copy = S.length() < Length ? S.length() : Length;
- unsigned len_to_fill = S.length() < Length ? Length-S.length() : 0;
-
- for (unsigned i = 0; i < len_to_copy; ++i)
- outbyte(Output, S[i]);
-
- for (unsigned i = 0; i < len_to_fill; ++i)
- outbyte(Output, 0);
-
- }
- void fixhalf(DataBuffer &Output, unsigned short X, unsigned Offset) {
- unsigned char *P = &Output[Offset];
- P[0] = (X >> (isLittleEndian ? 0 : 8)) & 255;
- P[1] = (X >> (isLittleEndian ? 8 : 0)) & 255;
- }
- void fixword(DataBuffer &Output, unsigned X, unsigned Offset) {
- unsigned char *P = &Output[Offset];
- P[0] = (X >> (isLittleEndian ? 0 : 24)) & 255;
- P[1] = (X >> (isLittleEndian ? 8 : 16)) & 255;
- P[2] = (X >> (isLittleEndian ? 16 : 8)) & 255;
- P[3] = (X >> (isLittleEndian ? 24 : 0)) & 255;
- }
-
static void InitMem(const Constant *C, void *Addr, intptr_t Offset,
const TargetData *TD,
std::vector<MachineRelocation> &MRs);
void BufferSymbolAndStringTable();
void CalculateRelocations(MachOSection &MOS);
- virtual MachineRelocation GetJTRelocation(unsigned Offset,
- MachineBasicBlock *MBB) = 0;
- virtual void GetTargetRelocation(MachineRelocation &MR, MachOSection &From,
- MachOSection &To) = 0;
+ MachineRelocation GetJTRelocation(unsigned Offset,
+ MachineBasicBlock *MBB) const {
+ return TM.getMachOWriterInfo()->GetJTRelocation(Offset, MBB);
+ }
+
+ /// GetTargetRelocation - Returns the number of relocations.
+ unsigned GetTargetRelocation(MachineRelocation &MR,
+ unsigned FromIdx,
+ unsigned ToAddr,
+ unsigned ToIndex,
+ OutputBuffer &RelocOut,
+ OutputBuffer &SecOut,
+ bool Scattered) {
+ return TM.getMachOWriterInfo()->GetTargetRelocation(MR, FromIdx, ToAddr,
+ ToIndex, RelocOut,
+ SecOut, Scattered);
+ }
};
}