aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNate Begeman <natebegeman@mac.com>2006-09-08 22:42:09 +0000
committerNate Begeman <natebegeman@mac.com>2006-09-08 22:42:09 +0000
commit94be248dbb2d2a44e8f4d47f161b93704d33d279 (patch)
treeabcb89fb4085d6e568c5ab258f2b04da3790b62b
parent6f34b43292fe478b28ac4b1c6f7c0162cda71c5f (diff)
First pass at supporting relocations. Relocations are written correctly to
the file now, however the relocated address is currently wrong. Fixing that will require some deep pondering. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30207 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/CodeGen/MachOWriter.h140
-rw-r--r--lib/CodeGen/MachOWriter.cpp118
-rw-r--r--lib/Target/PowerPC/PPCJITInfo.cpp5
-rw-r--r--lib/Target/PowerPC/PPCMachOWriter.cpp88
-rw-r--r--lib/Target/PowerPC/PPCRelocations.h16
5 files changed, 249 insertions, 118 deletions
diff --git a/include/llvm/CodeGen/MachOWriter.h b/include/llvm/CodeGen/MachOWriter.h
index b26b4d97f4..bb20f7bbbc 100644
--- a/include/llvm/CodeGen/MachOWriter.h
+++ b/include/llvm/CodeGen/MachOWriter.h
@@ -16,6 +16,7 @@
#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 <list>
@@ -26,6 +27,53 @@ namespace llvm {
class MachineCodeEmitter;
class MachOCodeEmitter;
+ /// MachOSym - This struct contains information about each symbol that is
+ /// added to logical symbol table for the module. This is eventually
+ /// turned into a real symbol table in the file.
+ struct MachOSym {
+ const GlobalValue *GV; // The global value this corresponds to.
+ std::string GVName; // The mangled name of the global value.
+ uint32_t n_strx; // index into the string table
+ uint8_t n_type; // type flag
+ uint8_t n_sect; // section number or NO_SECT
+ int16_t n_desc; // see <mach-o/stab.h>
+ uint64_t n_value; // value for this symbol (or stab offset)
+
+ // Constants for the n_sect field
+ // see <mach-o/nlist.h>
+ enum { NO_SECT = 0 }; // symbol is not in any section
+
+ // Constants for the n_type field
+ // see <mach-o/nlist.h>
+ enum { N_UNDF = 0x0, // undefined, n_sect == NO_SECT
+ N_ABS = 0x2, // absolute, n_sect == NO_SECT
+ N_SECT = 0xe, // defined in section number n_sect
+ N_PBUD = 0xc, // prebound undefined (defined in a dylib)
+ N_INDR = 0xa // indirect
+ };
+ // The following bits are OR'd into the types above. For example, a type
+ // of 0x0f would be an external N_SECT symbol (0x0e | 0x01).
+ enum { N_EXT = 0x01, // external symbol bit
+ N_PEXT = 0x10 // private external symbol bit
+ };
+
+ // Constants for the n_desc field
+ // see <mach-o/loader.h>
+ enum { REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0,
+ REFERENCE_FLAG_UNDEFINED_LAZY = 1,
+ REFERENCE_FLAG_DEFINED = 2,
+ REFERENCE_FLAG_PRIVATE_DEFINED = 3,
+ REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4,
+ REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5
+ };
+ enum { N_NO_DEAD_STRIP = 0x0020, // symbol is not to be dead stripped
+ N_WEAK_REF = 0x0040, // symbol is weak referenced
+ N_WEAK_DEF = 0x0080 // coalesced symbol is a weak definition
+ };
+
+ MachOSym(const GlobalValue *gv, std::string name, uint8_t sect);
+ };
+
/// MachOWriter - This class implements the common target-independent code for
/// writing Mach-O files. Targets should derive a class from this to
/// parameterize the output format.
@@ -55,7 +103,7 @@ namespace llvm {
/// Mang - The object used to perform name mangling for this module.
///
Mangler *Mang;
-
+
/// MCE - The MachineCodeEmitter object that we are exposing to emit machine
/// code for functions to the .o file.
MachOCodeEmitter *MCE;
@@ -249,6 +297,28 @@ namespace llvm {
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
@@ -275,6 +345,11 @@ namespace llvm {
/// up for emission to the file.
DataBuffer SectionData;
+ /// 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,
@@ -467,57 +542,6 @@ namespace llvm {
/// DySymTab - symbol table info for the dynamic link editor
MachODySymTab DySymTab;
- /// MachOSym - This struct contains information about each symbol that is
- /// added to logical symbol table for the module. This is eventually
- /// turned into a real symbol table in the file.
- struct MachOSym {
- const GlobalValue *GV; // The global value this corresponds to.
- std::string GVName; // The mangled name of the global value.
- uint32_t n_strx; // index into the string table
- uint8_t n_type; // type flag
- uint8_t n_sect; // section number or NO_SECT
- int16_t n_desc; // see <mach-o/stab.h>
- uint64_t n_value; // value for this symbol (or stab offset)
-
- // Constants for the n_sect field
- // see <mach-o/nlist.h>
- enum { NO_SECT = 0 }; // symbol is not in any section
-
- // Constants for the n_type field
- // see <mach-o/nlist.h>
- enum { N_UNDF = 0x0, // undefined, n_sect == NO_SECT
- N_ABS = 0x2, // absolute, n_sect == NO_SECT
- N_SECT = 0xe, // defined in section number n_sect
- N_PBUD = 0xc, // prebound undefined (defined in a dylib)
- N_INDR = 0xa // indirect
- };
- // The following bits are OR'd into the types above. For example, a type
- // of 0x0f would be an external N_SECT symbol (0x0e | 0x01).
- enum { N_EXT = 0x01, // external symbol bit
- N_PEXT = 0x10 // private external symbol bit
- };
-
- // Constants for the n_desc field
- // see <mach-o/loader.h>
- enum { REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0,
- REFERENCE_FLAG_UNDEFINED_LAZY = 1,
- REFERENCE_FLAG_DEFINED = 2,
- REFERENCE_FLAG_PRIVATE_DEFINED = 3,
- REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4,
- REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5
- };
- enum { N_NO_DEAD_STRIP = 0x0020, // symbol is not to be dead stripped
- N_WEAK_REF = 0x0040, // symbol is weak referenced
- N_WEAK_DEF = 0x0080 // coalesced symbol is a weak definition
- };
-
- MachOSym(const GlobalValue *gv, std::string name, uint8_t sect) : GV(gv),
- GVName(name), n_strx(0), n_type(sect == NO_SECT ? N_UNDF : N_SECT),
- n_sect(sect), n_desc(0), n_value(0) {
- // FIXME: names aren't getting the proper global/local prefix
- }
- };
-
struct MachOSymCmp {
bool operator()(const MachOSym &LHS, const MachOSym &RHS) {
return LHS.GVName < RHS.GVName;
@@ -530,13 +554,19 @@ namespace llvm {
/// PartitionByDefined - Simple boolean predicate that returns true if Sym
/// is defined in this module.
- static bool PartitionByDefined(const MachOWriter::MachOSym &Sym);
+ static bool PartitionByDefined(const MachOSym &Sym);
+ protected:
+
/// SymbolTable - This is the list of symbols we have emitted to the file.
/// This actually gets rearranged before emission to the file (to put the
/// local symbols first in the list).
std::vector<MachOSym> SymbolTable;
+ /// RelocBuffer - A buffer to hold the mach-o relocations before we write
+ /// them out at the appropriate location in the file.
+ DataBuffer RelocBuffer;
+
/// SymT - A buffer to hold the symbol table before we write it out at the
/// appropriate location in the file.
DataBuffer SymT;
@@ -641,8 +671,10 @@ namespace llvm {
void EmitGlobal(GlobalVariable *GV);
void EmitHeaderAndLoadCommands();
void EmitSections();
- void EmitRelocations();
void BufferSymbolAndStringTable();
+
+ virtual void GetTargetRelocation(MachOSection &MOS, MachineRelocation &MR,
+ uint64_t Addr) = 0;
};
}
diff --git a/lib/CodeGen/MachOWriter.cpp b/lib/CodeGen/MachOWriter.cpp
index 0f6820eddf..5ffd978f34 100644
--- a/lib/CodeGen/MachOWriter.cpp
+++ b/lib/CodeGen/MachOWriter.cpp
@@ -25,8 +25,8 @@
#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/ExecutionEngine/ExecutionEngine.h"
#include "llvm/Target/TargetJITInfo.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
@@ -130,19 +130,10 @@ bool MachOCodeEmitter::finishFunction(MachineFunction &F) {
// Get a symbol for the function to add to the symbol table
const GlobalValue *FuncV = F.getFunction();
- MachOWriter::MachOSym FnSym(FuncV, MOW.Mang->getValueName(FuncV), MOS->Index);
-
- // Figure out the binding (linkage) of the symbol.
- switch (FuncV->getLinkage()) {
- default:
- // appending linkage is illegal for functions.
- assert(0 && "Unknown linkage type!");
- case GlobalValue::ExternalLinkage:
- FnSym.n_type |= MachOWriter::MachOSym::N_EXT;
- break;
- case GlobalValue::InternalLinkage:
- break;
- }
+ MachOSym FnSym(FuncV, MOW.Mang->getValueName(FuncV), MOS->Index);
+
+ // FIXME: emit constant pool to appropriate section(s)
+ // FIXME: emit jump table to appropriate section
// Resolve the function's relocations either to concrete pointers in the case
// of branches from one block to another, or to target relocation entries.
@@ -152,15 +143,14 @@ bool MachOCodeEmitter::finishFunction(MachineFunction &F) {
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 if (MR.isConstantPoolIndex() || MR.isJumpTableIndex()) {
+ // Get the address of the index.
+ uint64_t Addr = 0;
+ // Generate the relocation(s) for the index.
+ MOW.GetTargetRelocation(*MOS, MR, Addr);
} 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?
+ // Handle other types later once we've finalized the sections in the file.
+ MOS->Relocations.push_back(MR);
}
}
Relocations.clear();
@@ -175,7 +165,6 @@ bool MachOCodeEmitter::finishFunction(MachineFunction &F) {
//===----------------------------------------------------------------------===//
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();
@@ -228,9 +217,7 @@ void MachOWriter::EmitGlobal(GlobalVariable *GV) {
// part of the common block if they are zero initialized and allowed to be
// merged with other symbols.
if (NoInit || GV->hasLinkOnceLinkage() || GV->hasWeakLinkage()) {
- MachOWriter::MachOSym ExtOrCommonSym(GV, Mang->getValueName(GV),
- MachOSym::NO_SECT);
- ExtOrCommonSym.n_type |= MachOSym::N_EXT;
+ MachOSym ExtOrCommonSym(GV, Mang->getValueName(GV), MachOSym::NO_SECT);
// For undefined (N_UNDF) external (N_EXT) types, n_value is the size in
// bytes of the symbol.
ExtOrCommonSym.n_value = Size;
@@ -254,9 +241,20 @@ void MachOWriter::EmitGlobal(GlobalVariable *GV) {
MachOSection &Sec = GV->isConstant() ? getConstSection(Ty) : getDataSection();
AddSymbolToSection(Sec, GV);
- // FIXME: actually write out the initializer to the section. This will
- // require ExecutionEngine's InitializeMemory() function, which will need to
- // be enhanced to support relocations.
+ // FIXME: A couple significant changes are required for this to work, even for
+ // trivial cases such as a constant integer:
+ // 0. InitializeMemory needs to be split out of ExecutionEngine. We don't
+ // want to have to create an ExecutionEngine such as JIT just to write
+ // some bytes into a buffer. The only thing necessary for
+ // InitializeMemory to function properly should be TargetData.
+ //
+ // 1. InitializeMemory needs to be enhanced to return MachineRelocations
+ // rather than accessing the address of objects such basic blocks,
+ // constant pools, and jump tables. The client of InitializeMemory such
+ // as an object writer or jit emitter should then handle these relocs
+ // appropriately.
+ //
+ // FIXME: need to allocate memory for the global initializer.
}
@@ -292,7 +290,7 @@ bool MachOWriter::doFinalization(Module &M) {
// Emit the symbol table to temporary buffers, so that we know the size of
// the string table when we write the load commands in the next phase.
BufferSymbolAndStringTable();
-
+
// Emit the header and load commands.
EmitHeaderAndLoadCommands();
@@ -300,9 +298,7 @@ bool MachOWriter::doFinalization(Module &M) {
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();
+ O.write((char*)&RelocBuffer[0], RelocBuffer.size());
// Write the symbol table and the string table to the end of the file.
O.write((char*)&SymT[0], SymT.size());
@@ -368,10 +364,32 @@ void MachOWriter::EmitHeaderAndLoadCommands() {
outword(FH, SEG.nsects);
outword(FH, SEG.flags);
- // Step #5: Write out the section commands for each section
+ // Step #5: Finish filling in the fields of the MachOSections
+ uint64_t currentAddr = 0;
for (std::list<MachOSection>::iterator I = SectionList.begin(),
E = SectionList.end(); I != E; ++I) {
- I->offset = SEG.fileoff; // FIXME: separate offset
+ I->addr = currentAddr;
+ I->offset = currentAddr + SEG.fileoff;
+ // FIXME: do we need to do something with alignment here?
+ currentAddr += I->size;
+ }
+
+ // Step #6: Calculate the number of relocations for each section and write out
+ // the section commands for each section
+ currentAddr += SEG.fileoff;
+ for (std::list<MachOSection>::iterator I = SectionList.begin(),
+ E = SectionList.end(); I != E; ++I) {
+ // calculate the relocation info for this section command
+ // FIXME: this could get complicated calculating the address argument, we
+ // should probably split this out into its own function.
+ for (unsigned i = 0, e = I->Relocations.size(); i != e; ++i)
+ GetTargetRelocation(*I, I->Relocations[i], 0);
+ if (I->nreloc != 0) {
+ I->reloff = currentAddr;
+ currentAddr += I->nreloc * 8;
+ }
+
+ // write the finalized section command to the output buffer
outstring(FH, I->sectname, 16);
outstring(FH, I->segname, 16);
outaddr(FH, I->addr);
@@ -387,9 +405,9 @@ void MachOWriter::EmitHeaderAndLoadCommands() {
outword(FH, I->reserved3);
}
- // Step #6: Emit LC_SYMTAB/LC_DYSYMTAB load commands
+ // Step #7: Emit LC_SYMTAB/LC_DYSYMTAB load commands
// FIXME: add size of relocs
- SymTab.symoff = SEG.fileoff + SEG.filesize;
+ SymTab.symoff = currentAddr;
SymTab.nsyms = SymbolTable.size();
SymTab.stroff = SymTab.symoff + SymT.size();
SymTab.strsize = StrT.size();
@@ -436,12 +454,6 @@ void MachOWriter::EmitSections() {
}
}
-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.
-}
-
/// PartitionByLocal - Simple boolean predicate that returns true if Sym is
/// a local symbol rather than an external symbol.
bool MachOWriter::PartitionByLocal(const MachOSym &Sym) {
@@ -513,3 +525,23 @@ void MachOWriter::BufferSymbolAndStringTable() {
outaddr(SymT, I->n_value);
}
}
+
+MachOSym::MachOSym(const GlobalValue *gv, std::string name, uint8_t sect) :
+ GV(gv), GVName(name), n_strx(0), n_type(sect == NO_SECT ? N_UNDF : N_SECT),
+ n_sect(sect), n_desc(0), n_value(0) {
+ // FIXME: take a target machine, and then add the appropriate prefix for
+ // the linkage type based on the TargetAsmInfo
+ switch (GV->getLinkage()) {
+ default:
+ assert(0 && "Unexpected linkage type!");
+ break;
+ case GlobalValue::WeakLinkage:
+ case GlobalValue::LinkOnceLinkage:
+ assert(!isa<Function>(gv) && "Unexpected linkage type for Function!");
+ case GlobalValue::ExternalLinkage:
+ n_type |= N_EXT;
+ break;
+ case GlobalValue::InternalLinkage:
+ break;
+ }
+}
diff --git a/lib/Target/PowerPC/PPCJITInfo.cpp b/lib/Target/PowerPC/PPCJITInfo.cpp
index a3ca3c52f8..7c1d2a4f49 100644
--- a/lib/Target/PowerPC/PPCJITInfo.cpp
+++ b/lib/Target/PowerPC/PPCJITInfo.cpp
@@ -312,15 +312,12 @@ void PPCJITInfo::relocate(void *Function, MachineRelocation *MR,
"Relocation out of range!");
*RelocPos |= (ResultPtr & ((1 << 14)-1)) << 2;
break;
- case PPC::reloc_absolute_ptr_high: // Pointer relocations.
- case PPC::reloc_absolute_ptr_low:
case PPC::reloc_absolute_high: // high bits of ref -> low 16 of instr
case PPC::reloc_absolute_low: { // low bits of ref -> low 16 of instr
ResultPtr += MR->getConstantVal();
// If this is a high-part access, get the high-part.
- if (MR->getRelocationType() == PPC::reloc_absolute_high ||
- MR->getRelocationType() == PPC::reloc_absolute_ptr_high) {
+ if (MR->getRelocationType() == PPC::reloc_absolute_high) {
// If the low part will have a carry (really a borrow) from the low
// 16-bits into the high 16, add a bit to borrow from.
if (((int)ResultPtr << 16) < 0)
diff --git a/lib/Target/PowerPC/PPCMachOWriter.cpp b/lib/Target/PowerPC/PPCMachOWriter.cpp
index a7da37127d..f82ee340e1 100644
--- a/lib/Target/PowerPC/PPCMachOWriter.cpp
+++ b/lib/Target/PowerPC/PPCMachOWriter.cpp
@@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//
+#include "PPCRelocations.h"
#include "PPCTargetMachine.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/MachOWriter.h"
@@ -22,11 +23,28 @@ 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;
+ if (TM.getTargetData()->getPointerSizeInBits() == 64) {
+ Header.cputype = MachOHeader::CPU_TYPE_POWERPC64;
+ } else {
+ Header.cputype = MachOHeader::CPU_TYPE_POWERPC;
+ }
Header.cpusubtype = MachOHeader::CPU_SUBTYPE_POWERPC_ALL;
}
+ virtual void GetTargetRelocation(MachOSection &MOS, MachineRelocation &MR,
+ uint64_t Addr);
+
+ // Constants for the relocation r_type field.
+ // see <mach-o/ppc/reloc.h>
+ enum { PPC_RELOC_VANILLA, // generic relocation
+ PPC_RELOC_PAIR, // the second relocation entry of a pair
+ PPC_RELOC_BR14, // 14 bit branch displacement to word address
+ PPC_RELOC_BR24, // 24 bit branch displacement to word address
+ PPC_RELOC_HI16, // a PAIR follows with the low 16 bits
+ PPC_RELOC_LO16, // a PAIR follows with the high 16 bits
+ PPC_RELOC_HA16, // a PAIR follows, which is sign extended to 32b
+ PPC_RELOC_LO14 // LO16 with low 2 bits implicitly zero
+ };
};
}
@@ -39,3 +57,69 @@ void llvm::addPPCMachOObjectWriterPass(FunctionPassManager &FPM,
FPM.add(EW);
FPM.add(createPPCCodeEmitterPass(TM, EW->getMachineCodeEmitter()));
}
+
+/// GetTargetRelocation - For the MachineRelocation MR, convert it to one or
+/// more PowerPC MachORelocation(s), add the new relocations to the
+/// MachOSection, and rewrite the instruction at the section offset if required
+/// by that relocation type.
+void PPCMachOWriter::GetTargetRelocation(MachOSection &MOS,
+ MachineRelocation &MR,
+ uint64_t Addr) {
+ // Keep track of whether or not this is an externally defined relocation.
+ uint32_t index = MOS.Index;
+ bool isExtern = false;
+
+ // Get the address of the instruction to rewrite
+ unsigned char *RelocPos = &MOS.SectionData[0] + MR.getMachineCodeOffset();
+
+ // Get the address of whatever it is we're relocating, if possible.
+ if (MR.isGlobalValue()) {
+ // determine whether or not its external and then figure out what section
+ // we put it in if it's a locally defined symbol.
+ } else if (MR.isString()) {
+ // lookup in global values?
+ } else {
+ assert((MR.isConstantPoolIndex() || MR.isJumpTableIndex()) &&
+ "Unhandled MachineRelocation type!");
+ }
+
+ switch ((PPC::RelocationType)MR.getRelocationType()) {
+ default: assert(0 && "Unknown PPC relocation type!");
+ case PPC::reloc_pcrel_bx:
+ case PPC::reloc_pcrel_bcx:
+ case PPC::reloc_absolute_low_ix:
+ assert(0 && "Unhandled PPC relocation type!");
+ break;
+ case PPC::reloc_absolute_high:
+ {
+ MachORelocation HA16(MR.getMachineCodeOffset(), index, false, 2, isExtern,
+ PPC_RELOC_HA16);
+ MachORelocation PAIR(Addr & 0xFFFF, 0xFFFFFF, false, 2, isExtern,
+ PPC_RELOC_PAIR);
+ outword(RelocBuffer, HA16.r_address);
+ outword(RelocBuffer, HA16.getPackedFields());
+ outword(RelocBuffer, PAIR.r_address);
+ outword(RelocBuffer, PAIR.getPackedFields());
+ }
+ MOS.nreloc += 2;
+ Addr += 0x8000;
+ *(unsigned *)RelocPos &= 0xFFFF0000;
+ *(unsigned *)RelocPos |= ((Addr >> 16) & 0xFFFF);
+ break;
+ case PPC::reloc_absolute_low:
+ {
+ MachORelocation LO16(MR.getMachineCodeOffset(), index, false, 2, isExtern,
+ PPC_RELOC_LO16);
+ MachORelocation PAIR(Addr >> 16, 0xFFFFFF, false, 2, isExtern,
+ PPC_RELOC_PAIR);
+ outword(RelocBuffer, LO16.r_address);
+ outword(RelocBuffer, LO16.getPackedFields());
+ outword(RelocBuffer, PAIR.r_address);
+ outword(RelocBuffer, PAIR.getPackedFields());
+ }
+ MOS.nreloc += 2;
+ *(unsigned *)RelocPos &= 0xFFFF0000;
+ *(unsigned *)RelocPos |= (Addr & 0xFFFF);
+ break;
+ }
+}
diff --git a/lib/Target/PowerPC/PPCRelocations.h b/lib/Target/PowerPC/PPCRelocations.h
index 8cb2859d1f..21c688de2c 100644
--- a/lib/Target/PowerPC/PPCRelocations.h
+++ b/lib/Target/PowerPC/PPCRelocations.h
@@ -44,21 +44,7 @@ namespace llvm {
// reloc_absolute_low_ix - Absolute relocation for the 64-bit load/store
// instruction which have two implicit zero bits.
- reloc_absolute_low_ix,
-
- // reloc_absolute_ptr_high - Absolute relocation for references to lazy
- // pointer stubs. In this case, the relocated instruction should be
- // relocated to point to a POINTER to the indicated global. The low-16
- // bits of the instruction are rewritten with the high 16-bits of the
- // address of the pointer.
- reloc_absolute_ptr_high,
-
- // reloc_absolute_ptr_low - Absolute relocation for references to lazy
- // pointer stubs. In this case, the relocated instruction should be
- // relocated to point to a POINTER to the indicated global. The low-16
- // bits of the instruction are rewritten with the low 16-bits of the
- // address of the pointer.
- reloc_absolute_ptr_low
+ reloc_absolute_low_ix
};
}
}