[PowerPC, Mach-O] PPCMachObjectWriter.cpp, at long last
David Fang
fang at csl.cornell.edu
Fri Jul 26 14:38:00 PDT 2013
Hi,
> On 25 July 2013 17:20, David Fang <fang at csl.cornell.edu> wrote:
>> I tried the following sed-transformation to turn darwin-asm to linux-asm:
>>
>> "darwin-to-linux-asm.sed":
>> #!/sw/bin/sed -f
>> s|\<r\([0-9]\+\)\>|\1|g
>> s|\<ha16\>\(([^(]*)\)|\1 at ha|g
>> s|\<lo16\>\(([^(]*)\)|\1 at l|g
>> s|\<L[A-Za-z0-9.$_]\+\>|.&|g
>>
>> 1) strip 'r' from register names
>> 2,3) transform ha16/lo16 operators
>> 4) prepend . to local symbols
Turns out step 4) wasn't needed.
>> % darwin-to-linux-asm.sed hello-puts.s > hello-puts-linux.s
>>
>> % llvm-mc -triple=powerpc-apple-darwin8 -mcpu=g4 -relocation-model=pic
>> -filetype=obj hello-puts-linux.s -o hello-puts-linux.o
>>
>> I'm not partcularly comfortable going down this path with hacks.
>> I'd need to be advised on all the syntactic transformations needed.
>> Can't we just keep the llc -filetype=obj test for now until proper
>> darwin-asm syntax is supported?
>
> Please don't. If you, the author, finds it hard to figure out what is
> difference, imagine someone doing refactoring and hitting problems
> with llc -filetype=obj. Tests like that are a maintenance nightmare.
Patch updated.
This now contains an llvm-mc test using syntactically transformed
darwin-to-linux asm. I've confirmed that the object files produced by
llvm-mc and llc -filetype=obj are identical, but have left the llc -> .o
test commented out as you've requested.
The two tests are in test/CodeGen/PowerPC, but can be relocated anywhere
that might seem more appropriate.
Fang
--
David Fang
http://www.csl.cornell.edu/~fang/
-------------- next part --------------
commit a16d6440d721ff65ea9265386fa1d142468a5949
Author: David Fang <fang at csl.cornell.edu>
Date: Thu Jul 25 15:02:39 2013 -0700
mach-o/PPC relocation writer, taken from powerpc-darwin8 branch
diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h
index 96ee8a7..b632a89 100644
--- a/include/llvm/Object/MachOFormat.h
+++ b/include/llvm/Object/MachOFormat.h
@@ -425,6 +425,53 @@ namespace macho {
};
+/**
+ * PPC relocation types from <mach-o/ppc/reloc.h>
+ * (renamed, following conventions in this header)
+ *
+ * Relocation types used in the ppc implementation. Relocation entries for
+ * things other than instructions use the same generic relocation as discribed
+ * above and their r_type is RELOC_VANILLA. The rest of the relocation types
+ * are for instructions. Since they are for instructions the r_address field
+ * indicates the 32 bit instruction that the relocation is to be preformed on.
+ * The fields r_pcrel and r_length are ignored for non-RELOC_VANILLA r_types
+ * except for PPC_RELOC_BR14.
+ *
+ * For PPC_RELOC_BR14 if the r_length is the unused value 3, then the branch was
+ * statically predicted setting or clearing the Y-bit based on the sign of the
+ * displacement or the opcode. If this is the case the static linker must flip
+ * the value of the Y-bit if the sign of the displacement changes for non-branch
+ * always conditions.
+ */
+ enum RelocationInfoTypePPC {
+ RIT_PPC_VANILLA, /* generic relocation as discribed above */
+ RIT_PPC_PAIR, /* the second relocation entry of a pair */
+ RIT_PPC_BR14, /* 14 bit branch displacement (to a word address) */
+ RIT_PPC_BR24, /* 24 bit branch displacement (to a word address) */
+ RIT_PPC_HI16, /* a PAIR follows with the low half */
+ RIT_PPC_LO16, /* a PAIR follows with the high half */
+ RIT_PPC_HA16, /* Same as the RELOC_HI16 except the low 16 bits and the
+ * high 16 bits are added together with the low 16 bits
+ * sign extened first. This means if bit 15 of the low
+ * 16 bits is set the high 16 bits stored in the
+ * instruction will be adjusted.
+ */
+ RIT_PPC_LO14, /* Same as the LO16 except that the low 2 bits are not
+ * stored in the instruction and are always zero. This
+ * is used in double word load/store instructions.
+ */
+ RIT_PPC_SECTDIFF, /* a PAIR follows with subtract symbol value */
+ RIT_PPC_PB_LA_PTR,/* prebound lazy pointer */
+ RIT_PPC_HI16_SECTDIFF, /* section difference forms of above. a PAIR */
+ RIT_PPC_LO16_SECTDIFF, /* follows these with subtract symbol value */
+ RIT_PPC_HA16_SECTDIFF,
+ RIT_PPC_JBSR,
+ RIT_PPC_LO14_SECTDIFF,
+ RIT_PPC_LOCAL_SECTDIFF, /* like PPC_SECTDIFF, but the symbol
+ referenced was local. */
+ RIT_PPC_TLV
+ };
+
} // end namespace macho
} // end namespace object
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index 19c8421..2f498b8 100644
--- a/lib/Object/MachOObjectFile.cpp
+++ b/lib/Object/MachOObjectFile.cpp
@@ -1059,7 +1059,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
break;
}
// X86 and ARM share some relocation types in common.
- } else if (Arch == Triple::x86 || Arch == Triple::arm) {
+ } else if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
// Generic relocation types...
switch (Type) {
case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
@@ -1084,7 +1084,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
}
}
- if (Arch == Triple::x86) {
+ if (Arch == Triple::x86 || Arch == Triple::ppc) {
// All X86 relocations that need special printing were already
// handled in the generic code.
switch (Type) {
@@ -1177,7 +1177,7 @@ MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const {
// On arches that use the generic relocations, GENERIC_RELOC_PAIR
// is always hidden.
- if (Arch == Triple::x86 || Arch == Triple::arm) {
+ if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) {
if (Type == macho::RIT_Pair) Result = true;
} else if (Arch == Triple::x86_64) {
// On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
diff --git a/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt b/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt
index 45be471..3efa5ec 100644
--- a/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt
@@ -5,6 +5,7 @@ add_llvm_library(LLVMPowerPCDesc
PPCMCCodeEmitter.cpp
PPCMCExpr.cpp
PPCPredicates.cpp
+ PPCMachObjectWriter.cpp
PPCELFObjectWriter.cpp
)
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
index 4f999a1..f423710 100644
--- a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
@@ -20,6 +20,7 @@
#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
+
using namespace llvm;
static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
@@ -69,19 +70,6 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
}
namespace {
-class PPCMachObjectWriter : public MCMachObjectTargetWriter {
-public:
- PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType,
- uint32_t CPUSubtype)
- : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {}
-
- void RecordRelocation(MachObjectWriter *Writer,
- const MCAssembler &Asm, const MCAsmLayout &Layout,
- const MCFragment *Fragment, const MCFixup &Fixup,
- MCValue Target, uint64_t &FixedValue) {
- llvm_unreachable("Relocation emission for MachO/PPC unimplemented!");
- }
-};
class PPCAsmBackend : public MCAsmBackend {
const Target &TheTarget;
@@ -174,12 +162,11 @@ namespace {
MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
bool is64 = getPointerSize() == 8;
- return createMachObjectWriter(new PPCMachObjectWriter(
+ return createPPCMachObjectWriter(OS,
/*Is64Bit=*/is64,
(is64 ? object::mach::CTM_PowerPC64 :
object::mach::CTM_PowerPC),
- object::mach::CSPPC_ALL),
- OS, /*IsLittleEndian=*/false);
+ object::mach::CSPPC_ALL);
}
virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
index 38a7420..1240988 100644
--- a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
@@ -45,6 +45,11 @@ MCAsmBackend *createPPCAsmBackend(const Target &T, StringRef TT, StringRef CPU);
MCObjectWriter *createPPCELFObjectWriter(raw_ostream &OS,
bool Is64Bit,
uint8_t OSABI);
+/// createPPCELFObjectWriter - Construct a PPC Mach-O object writer.
+MCObjectWriter *createPPCMachObjectWriter(raw_ostream &OS,
+ bool Is64Bit,
+ uint32_t CPUType,
+ uint32_t CPUSubtype);
} // End llvm namespace
// Generated files will use "namespace PPC". To avoid symbol clash,
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp
new file mode 100644
index 0000000..eae6494
--- /dev/null
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp
@@ -0,0 +1,472 @@
+//===-- PPCMachObjectWriter.cpp - PPC Mach-O Writer -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/PPCMCTargetDesc.h"
+#include "MCTargetDesc/PPCFixupKinds.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/MC/MCAsmLayout.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCMachObjectWriter.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Object/MachOFormat.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+using namespace llvm::object;
+
+namespace {
+class PPCMachObjectWriter : public MCMachObjectTargetWriter {
+ bool RecordScatteredRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ unsigned Log2Size,
+ uint64_t &FixedValue);
+
+ void RecordPPCRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ uint64_t &FixedValue);
+public:
+ PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType,
+ uint32_t CPUSubtype)
+ : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
+ /*UseAggressiveSymbolFolding=*/Is64Bit) {}
+
+ void RecordRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm, const MCAsmLayout &Layout,
+ const MCFragment *Fragment, const MCFixup &Fixup,
+ MCValue Target, uint64_t &FixedValue) {
+ if (Writer->is64Bit()) {
+ llvm_unreachable("Relocation emission for MachO/PPC64 unimplemented, until Fang gets around to hacking...");
+ } else
+ RecordPPCRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
+ FixedValue);
+ }
+};
+}
+
+/**
+ Log2Size is used for relocation_info::r_length.
+ See "include/llvm/MC/MCFixup.h"
+ and "lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h"
+ See "lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp":
+ adjustFixupValue() for cases of handling fixups.
+ getFixupKindInfo() for sizes.
+ */
+static unsigned getFixupKindLog2Size(unsigned Kind) {
+ switch (Kind) {
+ default:
+ llvm_unreachable("invalid fixup kind!");
+ case FK_PCRel_1:
+ case FK_Data_1: return 0;
+ case FK_PCRel_2:
+ case FK_Data_2: return 1;
+ case FK_PCRel_4:
+ case PPC::fixup_ppc_brcond14:
+ case PPC::fixup_ppc_half16:
+ case PPC::fixup_ppc_br24:
+ case FK_Data_4: return 2;
+ case FK_PCRel_8:
+ case FK_Data_8: return 3;
+ }
+ return 0;
+}
+
+/**
+ Translates generic PPC fixup kind to Mach-O/PPC relocation type enum.
+ Outline based on PPCELFObjectWriter::getRelocTypeInner().
+ */
+static
+unsigned
+getRelocType(
+ const MCValue &Target,
+ const MCFixupKind FixupKind, // from Fixup.getKind()
+ const bool IsPCRel) {
+ const MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
+ MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
+ // determine the type of the relocation
+ unsigned Type = macho::RIT_PPC_VANILLA;
+ if (IsPCRel) { // relative to PC
+ switch (FixupKind) {
+ default:
+ llvm_unreachable("Unimplemented (relative)");
+ case PPC::fixup_ppc_br24:
+ Type = macho::RIT_PPC_BR24; // R_PPC_REL24
+ break;
+ case PPC::fixup_ppc_brcond14:
+ Type = macho::RIT_PPC_BR14;
+ break;
+ case PPC::fixup_ppc_half16:
+ switch (Modifier) {
+ default: llvm_unreachable("Unsupported Modifier");
+ case MCSymbolRefExpr::VK_PPC_HA:
+ Type = macho::RIT_PPC_HA16;
+ break;
+ case MCSymbolRefExpr::VK_PPC_LO:
+ Type = macho::RIT_PPC_LO16;
+ break;
+ case MCSymbolRefExpr::VK_PPC_HI:
+ Type = macho::RIT_PPC_HI16;
+ break;
+ }
+ break;
+ }
+ } else {
+ switch (FixupKind) {
+ default:
+ llvm_unreachable("invalid fixup kind (absolute)!");
+ case PPC::fixup_ppc_half16:
+ switch (Modifier) {
+ default: llvm_unreachable("Unsupported Modifier");
+ case MCSymbolRefExpr::VK_PPC_HA:
+ Type = macho::RIT_PPC_HA16_SECTDIFF;
+ break;
+ case MCSymbolRefExpr::VK_PPC_LO:
+ Type = macho::RIT_PPC_LO16_SECTDIFF;
+ break;
+ case MCSymbolRefExpr::VK_PPC_HI:
+ Type = macho::RIT_PPC_HI16_SECTDIFF;
+ break;
+ }
+ break;
+ // go with RIT_PPC_VANILLA
+ case FK_Data_4:
+ // Type = macho::RIT_PPC_ADDR32; // ELF: R_PPC_ADDR32
+ break;
+ case FK_Data_2:
+ // Type = macho::RIT_PPC_ADDR16; // ELF: R_PPC_ADDR16
+ break;
+ }
+ }
+ return Type;
+}
+
+static
+// inline
+void
+makeRelocationInfo(
+ macho::RelocationEntry& MRE,
+ const uint32_t FixupOffset,
+ const uint32_t Index,
+ const unsigned IsPCRel,
+ const unsigned Log2Size,
+ const unsigned IsExtern,
+ const unsigned Type) {
+ MRE.Word0 = FixupOffset;
+// experimenting with order (endian fishiness on PPC?)
+ MRE.Word1 = ((Index << 8) | // was << 0
+ (IsPCRel << 7) | // was << 24
+ (Log2Size << 5) | // was << 25
+ (IsExtern << 4) | // was << 27
+ (Type << 0)); // was << 28
+}
+
+static
+// inline
+void
+makeScatteredRelocationInfo(
+ macho::RelocationEntry& MRE,
+ const uint32_t Addr,
+ const unsigned Type,
+ const unsigned Log2Size,
+ const unsigned IsPCRel,
+ const uint32_t Value2) {
+ // FIXME: see <mach-o/reloc.h> for note on endianness
+ MRE.Word0 = ((Addr << 0) |
+ (Type << 24) |
+ (Log2Size << 28) |
+ (IsPCRel << 30) |
+ macho::RF_Scattered);
+ MRE.Word1 = Value2;
+}
+
+/**
+ Compute fixup offset (address).
+ */
+static
+uint32_t
+getFixupOffset(const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup) {
+ uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
+ // On Mach-O, ppc_fixup_half16 relocations must refer to the
+ // start of the instruction, not the second halfword, as ELF does
+ if (Fixup.getKind() == PPC::fixup_ppc_half16)
+ FixupOffset &= ~uint32_t(3);
+ return FixupOffset;
+}
+
+/**
+ \return false if falling back to using non-scattered relocation,
+ otherwise true for normal scattered relocation.
+ */
+// based on X86MachObjectWriter::RecordScatteredRelocation
+// and ARMMachObjectWriter::RecordScatteredRelocation
+bool PPCMachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ unsigned Log2Size,
+ uint64_t &FixedValue) {
+ // caller already computes these, can we just pass and reuse?
+ const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup);
+ const MCFixupKind FK = Fixup.getKind();
+ const unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, FK);
+// unsigned Type = macho::RIT_PPC_VANILLA;
+ const unsigned Type = getRelocType(Target, FK, IsPCRel);
+ /*
+ * odcctools-20090808:as/write_object.c:fix_to_relocation_entries():
+ * Determine if this is left as a local relocation entry or
+ * changed to a SECTDIFF relocation entry. If this comes from a fix
+ * that has a subtract symbol it is a SECTDIFF relocation. Which is
+ * "addsy - subsy + constant" where both symbols are defined in
+ * sections. To encode all this information two scattered
+ * relocation entries are used. The first has the add symbol value
+ * and the second has the subtract symbol value.
+ */
+
+
+ // See <reloc.h>.
+ const MCSymbol *A = &Target.getSymA()->getSymbol();
+ MCSymbolData *A_SD = &Asm.getSymbolData(*A);
+
+ if (!A_SD->getFragment())
+ report_fatal_error("symbol '" + A->getName() +
+ "' can not be undefined in a subtraction expression");
+
+ uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
+ uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent());
+ FixedValue += SecAddr;
+ uint32_t Value2 = 0;
+
+ if (const MCSymbolRefExpr *B = Target.getSymB()) {
+ MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
+
+ if (!B_SD->getFragment())
+ report_fatal_error("symbol '" + B->getSymbol().getName() +
+ "' can not be undefined in a subtraction expression");
+
+ // Select the appropriate difference relocation type.
+ //
+ // Note that there is no longer any semantic difference between these two
+ // relocation types from the linkers point of view, this is done solely for
+ // pedantic compatibility with 'as'.
+#if 0
+ Type = A_SD->isExternal() ? (unsigned)macho::RIT_PPC_SECTDIFF :
+ (unsigned)macho::RIT_PPC_LO16_SECTDIFF;
+// (unsigned)macho::RIT_PPC_LOCAL_SECTDIFF;
+// Type = A_SD->isExternal() ? (unsigned)macho::RIT_Difference :
+// (unsigned)macho::RIT_Generic_LocalDifference;
+#endif
+ // FIXME: is Type correct? see include/llvm/Object/MachOFormat.h
+ Value2 = Writer->getSymbolAddress(B_SD, Layout);
+ FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
+ }
+ // FIXME: does FixedValue get used??
+
+ // Relocations are written out in reverse order, so the PAIR comes first.
+ if (Type == macho::RIT_PPC_SECTDIFF ||
+ Type == macho::RIT_PPC_HI16_SECTDIFF ||
+ Type == macho::RIT_PPC_LO16_SECTDIFF ||
+ Type == macho::RIT_PPC_HA16_SECTDIFF ||
+ Type == macho::RIT_PPC_LO14_SECTDIFF ||
+ Type == macho::RIT_PPC_LOCAL_SECTDIFF)
+// if (Type == macho::RIT_Difference ||
+// Type == macho::RIT_Generic_LocalDifference)
+ {
+#if 1
+ // X86 had this piece, but ARM does not
+ // If the offset is too large to fit in a scattered relocation,
+ // we're hosed. It's an unfortunate limitation of the MachO format.
+ if (FixupOffset > 0xffffff) {
+ char Buffer[32];
+ format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer));
+ Asm.getContext().FatalError(Fixup.getLoc(),
+ Twine("Section too large, can't encode "
+ "r_address (") + Buffer +
+ ") into 24 bits of scattered "
+ "relocation entry.");
+ llvm_unreachable("fatal error returned?!");
+ }
+#endif
+
+ // Is this supposed to follow MCTarget/PPCAsmBackend.cpp:adjustFixupValue()?
+ // see PPCMCExpr::EvaluateAsRelocatableImpl()
+ uint32_t other_half = 0;
+ switch (Type) {
+ case macho::RIT_PPC_LO16_SECTDIFF:
+ other_half = (FixedValue >> 16) & 0xffff;
+// applyFixupOffset longer extracts the high part because it now assumes
+// this was already done.
+// It looks like this is not true for the FixedValue needed with Mach-O relocs.
+// So we need to adjust FixedValue again here.
+ FixedValue &= 0xffff;
+ break;
+ case macho::RIT_PPC_HA16_SECTDIFF:
+ other_half = FixedValue & 0xffff;
+ FixedValue = ((FixedValue >> 16) + ((FixedValue & 0x8000) ? 1 : 0)) & 0xffff;
+ break;
+ case macho::RIT_PPC_HI16_SECTDIFF:
+ other_half = FixedValue & 0xffff;
+ FixedValue = (FixedValue >> 16) & 0xffff;
+ break;
+ default:
+// llvm_unreachable("Unhandled PPC scattered relocation type.");
+ break;
+ }
+
+ macho::RelocationEntry MRE;
+ makeScatteredRelocationInfo(MRE,
+// 0,
+ other_half, // guessing by trial and error...
+ macho::RIT_PPC_PAIR, Log2Size, IsPCRel, Value2);
+ Writer->addRelocation(Fragment->getParent(), MRE);
+#if 1
+ } else {
+ // If the offset is more than 24-bits, it won't fit in a scattered
+ // relocation offset field, so we fall back to using a non-scattered
+ // relocation. This is a bit risky, as if the offset reaches out of
+ // the block and the linker is doing scattered loading on this
+ // symbol, things can go badly.
+ //
+ // Required for 'as' compatibility.
+ if (FixupOffset > 0xffffff)
+ return false;
+#endif
+ }
+ macho::RelocationEntry MRE;
+ makeScatteredRelocationInfo(MRE,
+ FixupOffset, Type, Log2Size, IsPCRel, Value);
+ Writer->addRelocation(Fragment->getParent(), MRE);
+ return true;
+}
+
+// see PPCELFObjectWriter for a general outline of cases
+void PPCMachObjectWriter::RecordPPCRelocation(MachObjectWriter *Writer,
+ const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup,
+ MCValue Target,
+ uint64_t &FixedValue) {
+ const MCFixupKind FK = Fixup.getKind(); // unsigned
+ const unsigned Log2Size = getFixupKindLog2Size(FK);
+ const bool IsPCRel = Writer->isFixupKindPCRel(Asm, FK);
+ const unsigned RelocType = getRelocType(Target, FK, IsPCRel);
+
+ // If this is a difference or a defined symbol plus an offset, then we need a
+ // scattered relocation entry. Differences always require scattered
+ // relocations.
+ if (Target.getSymB() &&
+// Q: are branch targets ever scattered?
+ RelocType != macho::RIT_PPC_BR24 &&
+ RelocType != macho::RIT_PPC_BR14
+ ) {
+ RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
+ Target, Log2Size, FixedValue);
+ return;
+ }
+
+ // this doesn't seem right for RIT_PPC_BR24
+ // Get the symbol data, if any.
+ MCSymbolData *SD = 0;
+ if (Target.getSymA())
+ SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
+
+if (0) {
+ // If this is an internal relocation with an offset, it also needs a scattered
+ // relocation entry.
+ uint32_t Offset = Target.getConstant();
+ if (IsPCRel)
+ Offset += 1 << Log2Size;
+ // Try to record the scattered relocation if needed. Fall back to non
+ // scattered if necessary (see comments in RecordScatteredRelocation()
+ // for details).
+ if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD) &&
+ RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
+ Target, Log2Size, FixedValue))
+ return;
+}
+
+ // See <reloc.h>.
+ const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup);
+ unsigned Index = 0;
+ unsigned IsExtern = 0;
+// unsigned Type = 0;
+ unsigned Type = RelocType;
+
+ if (Target.isAbsolute()) { // constant
+ // SymbolNum of 0 indicates the absolute section.
+ //
+ // FIXME: Currently, these are never generated (see code below). I cannot
+ // find a case where they are actually emitted.
+ report_fatal_error("FIXME: relocations to absolute targets "
+ "not yet implemented");
+ // the above line stolen from ARM, not sure
+// Type = macho::RIT_PPC_VANILLA;
+ } else {
+ // Resolve constant variables.
+ if (SD->getSymbol().isVariable()) {
+ int64_t Res;
+ if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
+ Res, Layout, Writer->getSectionAddressMap())) {
+ FixedValue = Res;
+ return;
+ }
+ }
+
+ // Check whether we need an external or internal relocation.
+ if (Writer->doesSymbolRequireExternRelocation(SD)) {
+ IsExtern = 1;
+ Index = SD->getIndex();
+ // For external relocations, make sure to offset the fixup value to
+ // compensate for the addend of the symbol address, if it was
+ // undefined. This occurs with weak definitions, for example.
+ if (!SD->Symbol->isUndefined())
+ FixedValue -= Layout.getSymbolOffset(SD);
+ } else {
+ // The index is the section ordinal (1-based).
+ const MCSectionData &SymSD = Asm.getSectionData(
+ SD->getSymbol().getSection());
+ Index = SymSD.getOrdinal() + 1;
+ FixedValue += Writer->getSectionAddress(&SymSD);
+ }
+ if (IsPCRel)
+ FixedValue -= Writer->getSectionAddress(Fragment->getParent());
+
+// Type = macho::RIT_PPC_VANILLA;
+ }
+
+ // struct relocation_info (8 bytes)
+ macho::RelocationEntry MRE;
+ makeRelocationInfo(MRE,
+ FixupOffset, Index, IsPCRel, Log2Size, IsExtern, Type);
+ Writer->addRelocation(Fragment->getParent(), MRE);
+}
+
+MCObjectWriter *llvm::createPPCMachObjectWriter(raw_ostream &OS,
+ bool Is64Bit,
+ uint32_t CPUType,
+ uint32_t CPUSubtype) {
+ return createMachObjectWriter(new PPCMachObjectWriter(Is64Bit,
+ CPUType,
+ CPUSubtype),
+ OS, /*IsLittleEndian=*/false);
+}
diff --git a/test/CodeGen/PowerPC/hello-reloc.ll b/test/CodeGen/PowerPC/hello-reloc.ll
new file mode 100644
index 0000000..0fda921
--- /dev/null
+++ b/test/CodeGen/PowerPC/hello-reloc.ll
@@ -0,0 +1,281 @@
+; This tests mach-O/PPC relocation entries.
+; This test is paired with test/CodeGen/PowerPC/hello-reloc.s,
+; which tests llvm-mc.
+
+; RUN: llc -filetype=asm -relocation-model=pic -mcpu=g4 -mtriple=powerpc-apple-darwin8 %s -o - | tee %t1 | FileCheck -check-prefix=DARWIN-G4-ASM %s
+; RUN-WORKS-BUT-SKIPPING: llc -filetype=obj -relocation-model=pic -mcpu=g4 -mtriple=powerpc-apple-darwin8 %s -o - | tee %t2 | macho-dump | tee %t3 | FileCheck -check-prefix=DARWIN-G4-DUMP %s
+
+; FIXME: validating .s->.o requires darwin asm syntax support in PPCAsmParser
+; RUN-XFAIL: llvm-mc -relocation-model=pic -mcpu=g4 -triple=powerpc-apple-darwin8 %t1 -o - | tee %t4 | macho-dump | tee %t5 | FileCheck -check-prefix=DARWIN-G4-DUMP %s
+; RUN-XFAIL: diff -u %t2 %t4 || diff -u %t3 %t5
+
+; ModuleID = 'hello-puts.c'
+; compiled with clang (-fno-common -DPIC -femit-all-decls) from:
+; extern int puts(const char*);
+; int main(int argc, char* argv[]) { puts("Hello, world!"); return 0; }
+
+target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v128:128:128-n32"
+target triple = "powerpc-apple-macosx10.4.0"
+
+ at .str = private unnamed_addr constant [14 x i8] c"Hello, world!\00", align 1
+
+; Function Attrs: nounwind
+define i32 @main(i32 %argc, i8** %argv) #0 {
+entry:
+ %retval = alloca i32, align 4
+ %argc.addr = alloca i32, align 4
+ %argv.addr = alloca i8**, align 4
+ store i32 0, i32* %retval
+ store i32 %argc, i32* %argc.addr, align 4
+ store i8** %argv, i8*** %argv.addr, align 4
+ %call = call i32 @puts(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0))
+ ret i32 0
+}
+
+declare i32 @puts(i8*) #1
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "ssp-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "ssp-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+; DARWIN-G4-ASM: .machine ppc7400
+; DARWIN-G4-ASM: .section __TEXT,__textcoal_nt,coalesced,pure_instructions
+; DARWIN-G4-ASM: .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+; DARWIN-G4-ASM: .section __TEXT,__text,regular,pure_instructions
+; DARWIN-G4-ASM: .globl _main
+; DARWIN-G4-ASM: .align 4
+; DARWIN-G4-ASM:_main: ; @main
+; DARWIN-G4-ASM:; BB#0: ; %entry
+; DARWIN-G4-ASM: mflr r0
+; DARWIN-G4-ASM: stw r31, -4(r1)
+; DARWIN-G4-ASM: stw r0, 8(r1)
+; DARWIN-G4-ASM: stwu r1, -80(r1)
+; DARWIN-G4-ASM: bl L0$pb
+; DARWIN-G4-ASM:L0$pb:
+; DARWIN-G4-ASM: mr r31, r1
+; DARWIN-G4-ASM: li [[REGA:r[0-9]+]], 0
+; DARWIN-G4-ASM: mflr [[REGC:r[0-9]+]]
+; DARWIN-G4-ASM: stw [[REGB:r[0-9]+]], 68(r31)
+; DARWIN-G4-ASM: stw [[REGA]], 72(r31)
+; DARWIN-G4-ASM: stw r4, 64(r31)
+; DARWIN-G4-ASM: addis [[REGC]], [[REGC]], ha16(L_.str-L0$pb)
+; DARWIN-G4-ASM: la [[REGB]], lo16(L_.str-L0$pb)([[REGC]])
+; DARWIN-G4-ASM: bl L_puts$stub
+; DARWIN-G4-ASM: li [[REGB]], 0
+; DARWIN-G4-ASM: addi r1, r1, 80
+; DARWIN-G4-ASM: lwz r0, 8(r1)
+; DARWIN-G4-ASM: lwz r31, -4(r1)
+; DARWIN-G4-ASM: mtlr r0
+; DARWIN-G4-ASM: blr
+; DARWIN-G4-ASM: .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+; DARWIN-G4-ASM: .align 4
+; DARWIN-G4-ASM:L_puts$stub:
+; DARWIN-G4-ASM: .indirect_symbol _puts
+; DARWIN-G4-ASM: mflr r0
+; DARWIN-G4-ASM: bcl 20, 31, L_puts$stub$tmp
+; DARWIN-G4-ASM:L_puts$stub$tmp:
+; DARWIN-G4-ASM: mflr [[REGD:r[0-9]+]]
+; DARWIN-G4-ASM: addis [[REGD]], [[REGD]], ha16(L_puts$lazy_ptr-L_puts$stub$tmp)
+; DARWIN-G4-ASM: mtlr r0
+; DARWIN-G4-ASM: lwzu [[REGE:r[0-9]+]], lo16(L_puts$lazy_ptr-L_puts$stub$tmp)([[REGD]])
+; DARWIN-G4-ASM: mtctr [[REGE]]
+; DARWIN-G4-ASM: bctr
+; DARWIN-G4-ASM: .section __DATA,__la_symbol_ptr,lazy_symbol_pointers
+; DARWIN-G4-ASM:L_puts$lazy_ptr:
+; DARWIN-G4-ASM: .indirect_symbol _puts
+; DARWIN-G4-ASM: .long dyld_stub_binding_helper
+; DARWIN-G4-ASM:.subsections_via_symbols
+; DARWIN-G4-ASM: .section __TEXT,__cstring,cstring_literals
+; DARWIN-G4-ASM:L_.str: ; @.str
+; DARWIN-G4-ASM: .asciz "Hello, world!"
+
+; DARWIN-G4-DUMP: ('cputype', 18)
+; DARWIN-G4-DUMP: ('cpusubtype', 0)
+; DARWIN-G4-DUMP: ('filetype', 1)
+; DARWIN-G4-DUMP: ('num_load_commands', 3)
+; DARWIN-G4-DUMP: ('load_commands_size', 500)
+; DARWIN-G4-DUMP: ('flag', 8192)
+; DARWIN-G4-DUMP: ('load_commands', [
+; DARWIN-G4-DUMP: # Load Command 0
+; DARWIN-G4-DUMP: (('command', 1)
+; DARWIN-G4-DUMP: ('size', 396)
+; DARWIN-G4-DUMP: ('segment_name', '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('vm_addr', 0)
+; DARWIN-G4-DUMP: ('vm_size', 130)
+; DARWIN-G4-DUMP: ('file_offset', 528)
+; DARWIN-G4-DUMP: ('file_size', 130)
+; DARWIN-G4-DUMP: ('maxprot', 7)
+; DARWIN-G4-DUMP: ('initprot', 7)
+; DARWIN-G4-DUMP: ('num_sections', 5)
+; DARWIN-G4-DUMP: ('flags', 0)
+; DARWIN-G4-DUMP: ('sections', [
+; DARWIN-G4-DUMP: # Section 0
+; DARWIN-G4-DUMP: (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('address', 0)
+; DARWIN-G4-DUMP: ('size', 80)
+; DARWIN-G4-DUMP: ('offset', 528)
+; DARWIN-G4-DUMP: ('alignment', 4)
+; DARWIN-G4-DUMP: ('reloc_offset', 660)
+; DARWIN-G4-DUMP: ('num_reloc', 5)
+; DARWIN-G4-DUMP: ('flags', 0x80000400)
+; DARWIN-G4-DUMP: ('reserved1', 0)
+; DARWIN-G4-DUMP: ('reserved2', 0)
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: ('_relocations', [
+; DARWIN-G4-DUMP: # Relocation 0
+; DARWIN-G4-DUMP: (('word-0', 0x34),
+; DARWIN-G4-DUMP: ('word-1', 0x3c3)),
+; DARWIN-G4-DUMP: # Relocation 1
+; DARWIN-G4-DUMP: (('word-0', 0xab000030),
+; DARWIN-G4-DUMP: ('word-1', 0x74)),
+; DARWIN-G4-DUMP: # Relocation 2
+; DARWIN-G4-DUMP: (('word-0', 0xa1000000),
+; DARWIN-G4-DUMP: ('word-1', 0x14)),
+; DARWIN-G4-DUMP: # Relocation 3
+; DARWIN-G4-DUMP: (('word-0', 0xac00002c),
+; DARWIN-G4-DUMP: ('word-1', 0x74)),
+; DARWIN-G4-DUMP: # Relocation 4
+; DARWIN-G4-DUMP: (('word-0', 0xa1000060),
+; DARWIN-G4-DUMP: ('word-1', 0x14)),
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: # Section 1
+; DARWIN-G4-DUMP: (('section_name', '__textcoal_nt\x00\x00\x00')
+; DARWIN-G4-DUMP: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('address', 80)
+; DARWIN-G4-DUMP: ('size', 0)
+; DARWIN-G4-DUMP: ('offset', 608)
+; DARWIN-G4-DUMP: ('alignment', 0)
+; DARWIN-G4-DUMP: ('reloc_offset', 0)
+; DARWIN-G4-DUMP: ('num_reloc', 0)
+; DARWIN-G4-DUMP: ('flags', 0x8000000b)
+; DARWIN-G4-DUMP: ('reserved1', 0)
+; DARWIN-G4-DUMP: ('reserved2', 0)
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: ('_relocations', [
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: # Section 2
+; DARWIN-G4-DUMP: (('section_name', '__picsymbolstub1')
+; DARWIN-G4-DUMP: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('address', 80)
+; DARWIN-G4-DUMP: ('size', 32)
+; DARWIN-G4-DUMP: ('offset', 608)
+; DARWIN-G4-DUMP: ('alignment', 4)
+; DARWIN-G4-DUMP: ('reloc_offset', 700)
+; DARWIN-G4-DUMP: ('num_reloc', 4)
+; DARWIN-G4-DUMP: ('flags', 0x80000408)
+; DARWIN-G4-DUMP: ('reserved1', 0)
+; DARWIN-G4-DUMP: ('reserved2', 32)
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: ('_relocations', [
+; DARWIN-G4-DUMP: # Relocation 0
+; DARWIN-G4-DUMP: (('word-0', 0xab000014),
+; DARWIN-G4-DUMP: ('word-1', 0x70)),
+; DARWIN-G4-DUMP: # Relocation 1
+; DARWIN-G4-DUMP: (('word-0', 0xa1000000),
+; DARWIN-G4-DUMP: ('word-1', 0x58)),
+; DARWIN-G4-DUMP: # Relocation 2
+; DARWIN-G4-DUMP: (('word-0', 0xac00000c),
+; DARWIN-G4-DUMP: ('word-1', 0x70)),
+; DARWIN-G4-DUMP: # Relocation 3
+; DARWIN-G4-DUMP: (('word-0', 0xa1000018),
+; DARWIN-G4-DUMP: ('word-1', 0x58)),
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: # Section 3
+; DARWIN-G4-DUMP: (('section_name', '__la_symbol_ptr\x00')
+; DARWIN-G4-DUMP: ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('address', 112)
+; DARWIN-G4-DUMP: ('size', 4)
+; DARWIN-G4-DUMP: ('offset', 640)
+; DARWIN-G4-DUMP: ('alignment', 0)
+; DARWIN-G4-DUMP: ('reloc_offset', 732)
+; DARWIN-G4-DUMP: ('num_reloc', 1)
+; DARWIN-G4-DUMP: ('flags', 0x7)
+; DARWIN-G4-DUMP: ('reserved1', 1)
+; DARWIN-G4-DUMP: ('reserved2', 0)
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: ('_relocations', [
+; DARWIN-G4-DUMP: # Relocation 0
+; DARWIN-G4-DUMP: (('word-0', 0x0),
+; DARWIN-G4-DUMP: ('word-1', 0x250)),
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: # Section 4
+; DARWIN-G4-DUMP: (('section_name', '__cstring\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('address', 116)
+; DARWIN-G4-DUMP: ('size', 14)
+; DARWIN-G4-DUMP: ('offset', 644)
+; DARWIN-G4-DUMP: ('alignment', 0)
+; DARWIN-G4-DUMP: ('reloc_offset', 0)
+; DARWIN-G4-DUMP: ('num_reloc', 0)
+; DARWIN-G4-DUMP: ('flags', 0x2)
+; DARWIN-G4-DUMP: ('reserved1', 0)
+; DARWIN-G4-DUMP: ('reserved2', 0)
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: ('_relocations', [
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: # Load Command 1
+; DARWIN-G4-DUMP: (('command', 2)
+; DARWIN-G4-DUMP: ('size', 24)
+; DARWIN-G4-DUMP: ('symoff', 748)
+; DARWIN-G4-DUMP: ('nsyms', 3)
+; DARWIN-G4-DUMP: ('stroff', 784)
+; DARWIN-G4-DUMP: ('strsize', 40)
+; DARWIN-G4-DUMP: ('_string_data', '\x00_main\x00dyld_stub_binding_helper\x00_puts\x00\x00\x00')
+; DARWIN-G4-DUMP: ('_symbols', [
+; DARWIN-G4-DUMP: # Symbol 0
+; DARWIN-G4-DUMP: (('n_strx', 1)
+; DARWIN-G4-DUMP: ('n_type', 0xf)
+; DARWIN-G4-DUMP: ('n_sect', 1)
+; DARWIN-G4-DUMP: ('n_desc', 0)
+; DARWIN-G4-DUMP: ('n_value', 0)
+; DARWIN-G4-DUMP: ('_string', '_main')
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: # Symbol 1
+; DARWIN-G4-DUMP: (('n_strx', 32)
+; DARWIN-G4-DUMP: ('n_type', 0x1)
+; DARWIN-G4-DUMP: ('n_sect', 0)
+; DARWIN-G4-DUMP: ('n_desc', 1)
+; DARWIN-G4-DUMP: ('n_value', 0)
+; DARWIN-G4-DUMP: ('_string', '_puts')
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: # Symbol 2
+; DARWIN-G4-DUMP: (('n_strx', 7)
+; DARWIN-G4-DUMP: ('n_type', 0x1)
+; DARWIN-G4-DUMP: ('n_sect', 0)
+; DARWIN-G4-DUMP: ('n_desc', 0)
+; DARWIN-G4-DUMP: ('n_value', 0)
+; DARWIN-G4-DUMP: ('_string', 'dyld_stub_binding_helper')
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: # Load Command 2
+; DARWIN-G4-DUMP: (('command', 11)
+; DARWIN-G4-DUMP: ('size', 80)
+; DARWIN-G4-DUMP: ('ilocalsym', 0)
+; DARWIN-G4-DUMP: ('nlocalsym', 0)
+; DARWIN-G4-DUMP: ('iextdefsym', 0)
+; DARWIN-G4-DUMP: ('nextdefsym', 1)
+; DARWIN-G4-DUMP: ('iundefsym', 1)
+; DARWIN-G4-DUMP: ('nundefsym', 2)
+; DARWIN-G4-DUMP: ('tocoff', 0)
+; DARWIN-G4-DUMP: ('ntoc', 0)
+; DARWIN-G4-DUMP: ('modtaboff', 0)
+; DARWIN-G4-DUMP: ('nmodtab', 0)
+; DARWIN-G4-DUMP: ('extrefsymoff', 0)
+; DARWIN-G4-DUMP: ('nextrefsyms', 0)
+; DARWIN-G4-DUMP: ('indirectsymoff', 740)
+; DARWIN-G4-DUMP: ('nindirectsyms', 2)
+; DARWIN-G4-DUMP: ('extreloff', 0)
+; DARWIN-G4-DUMP: ('nextrel', 0)
+; DARWIN-G4-DUMP: ('locreloff', 0)
+; DARWIN-G4-DUMP: ('nlocrel', 0)
+; DARWIN-G4-DUMP: ('_indirect_symbols', [
+; DARWIN-G4-DUMP: # Indirect Symbol 0
+; DARWIN-G4-DUMP: (('symbol_index', 0x1),),
+; DARWIN-G4-DUMP: # Indirect Symbol 1
+; DARWIN-G4-DUMP: (('symbol_index', 0x1),),
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: ])
diff --git a/test/CodeGen/PowerPC/hello-reloc.s b/test/CodeGen/PowerPC/hello-reloc.s
new file mode 100644
index 0000000..37e3eee
--- /dev/null
+++ b/test/CodeGen/PowerPC/hello-reloc.s
@@ -0,0 +1,257 @@
+; This test is paired with test/CodeGen/PowerPC/hello-reloc.ll,
+; which tests llc.
+; I took the asm produced by llc -filetype=asm and syntactically translated
+; it to the supported PPCAsmParser syntax for this case.
+
+; RUN: llvm-mc -filetype=obj -relocation-model=pic -mcpu=g4 -triple=powerpc-apple-darwin8 %s -o - | tee %t1 | macho-dump | tee %t2 | FileCheck -check-prefix=DARWIN-G4-DUMP %s
+
+; Ideally we'd like to combine this test with hello-reloc.ll, but automating
+; the assembly transformation would require GNU sed.
+; The asm transformation will no longer be needed once darwin-asm syntax
+; is supported in PPCAsmParser, at which point these tests can be combined.
+
+; .machine ppc7400
+ .section __TEXT,__textcoal_nt,coalesced,pure_instructions
+ .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+ .section __TEXT,__text,regular,pure_instructions
+ .globl _main
+ .align 4
+_main: ; @main
+; BB#0: ; %entry
+ mflr 0
+ stw 31, -4(1)
+ stw 0, 8(1)
+ stwu 1, -80(1)
+ bl L0$pb
+L0$pb:
+ mr 31, 1
+ li 5, 0
+ mflr 2
+ stw 3, 68(31)
+ stw 5, 72(31)
+ stw 4, 64(31)
+ addis 2, 2, (L_.str-L0$pb)@ha
+ la 3, (L_.str-L0$pb)@l(2)
+ bl L_puts$stub
+ li 3, 0
+ addi 1, 1, 80
+ lwz 0, 8(1)
+ lwz 31, -4(1)
+ mtlr 0
+ blr
+
+ .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+ .align 4
+L_puts$stub:
+ .indirect_symbol _puts
+ mflr 0
+ bcl 20, 31, L_puts$stub$tmp
+L_puts$stub$tmp:
+ mflr 11
+ addis 11, 11, (L_puts$lazy_ptr-L_puts$stub$tmp)@ha
+ mtlr 0
+ lwzu 12, (L_puts$lazy_ptr-L_puts$stub$tmp)@l(11)
+ mtctr 12
+ bctr
+ .section __DATA,__la_symbol_ptr,lazy_symbol_pointers
+L_puts$lazy_ptr:
+ .indirect_symbol _puts
+ .long dyld_stub_binding_helper
+
+.subsections_via_symbols
+ .section __TEXT,__cstring,cstring_literals
+L_.str: ; @.str
+ .asciz "Hello, world!"
+
+
+; DARWIN-G4-DUMP: ('cputype', 18)
+; DARWIN-G4-DUMP: ('cpusubtype', 0)
+; DARWIN-G4-DUMP: ('filetype', 1)
+; DARWIN-G4-DUMP: ('num_load_commands', 3)
+; DARWIN-G4-DUMP: ('load_commands_size', 500)
+; DARWIN-G4-DUMP: ('flag', 8192)
+; DARWIN-G4-DUMP: ('load_commands', [
+; DARWIN-G4-DUMP: # Load Command 0
+; DARWIN-G4-DUMP: (('command', 1)
+; DARWIN-G4-DUMP: ('size', 396)
+; DARWIN-G4-DUMP: ('segment_name', '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('vm_addr', 0)
+; DARWIN-G4-DUMP: ('vm_size', 130)
+; DARWIN-G4-DUMP: ('file_offset', 528)
+; DARWIN-G4-DUMP: ('file_size', 130)
+; DARWIN-G4-DUMP: ('maxprot', 7)
+; DARWIN-G4-DUMP: ('initprot', 7)
+; DARWIN-G4-DUMP: ('num_sections', 5)
+; DARWIN-G4-DUMP: ('flags', 0)
+; DARWIN-G4-DUMP: ('sections', [
+; DARWIN-G4-DUMP: # Section 0
+; DARWIN-G4-DUMP: (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('address', 0)
+; DARWIN-G4-DUMP: ('size', 80)
+; DARWIN-G4-DUMP: ('offset', 528)
+; DARWIN-G4-DUMP: ('alignment', 4)
+; DARWIN-G4-DUMP: ('reloc_offset', 660)
+; DARWIN-G4-DUMP: ('num_reloc', 5)
+; DARWIN-G4-DUMP: ('flags', 0x80000400)
+; DARWIN-G4-DUMP: ('reserved1', 0)
+; DARWIN-G4-DUMP: ('reserved2', 0)
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: ('_relocations', [
+; DARWIN-G4-DUMP: # Relocation 0
+; DARWIN-G4-DUMP: (('word-0', 0x34),
+; DARWIN-G4-DUMP: ('word-1', 0x3c3)),
+; DARWIN-G4-DUMP: # Relocation 1
+; DARWIN-G4-DUMP: (('word-0', 0xab000030),
+; DARWIN-G4-DUMP: ('word-1', 0x74)),
+; DARWIN-G4-DUMP: # Relocation 2
+; DARWIN-G4-DUMP: (('word-0', 0xa1000000),
+; DARWIN-G4-DUMP: ('word-1', 0x14)),
+; DARWIN-G4-DUMP: # Relocation 3
+; DARWIN-G4-DUMP: (('word-0', 0xac00002c),
+; DARWIN-G4-DUMP: ('word-1', 0x74)),
+; DARWIN-G4-DUMP: # Relocation 4
+; DARWIN-G4-DUMP: (('word-0', 0xa1000060),
+; DARWIN-G4-DUMP: ('word-1', 0x14)),
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: # Section 1
+; DARWIN-G4-DUMP: (('section_name', '__textcoal_nt\x00\x00\x00')
+; DARWIN-G4-DUMP: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('address', 80)
+; DARWIN-G4-DUMP: ('size', 0)
+; DARWIN-G4-DUMP: ('offset', 608)
+; DARWIN-G4-DUMP: ('alignment', 0)
+; DARWIN-G4-DUMP: ('reloc_offset', 0)
+; DARWIN-G4-DUMP: ('num_reloc', 0)
+; DARWIN-G4-DUMP: ('flags', 0x8000000b)
+; DARWIN-G4-DUMP: ('reserved1', 0)
+; DARWIN-G4-DUMP: ('reserved2', 0)
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: ('_relocations', [
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: # Section 2
+; DARWIN-G4-DUMP: (('section_name', '__picsymbolstub1')
+; DARWIN-G4-DUMP: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('address', 80)
+; DARWIN-G4-DUMP: ('size', 32)
+; DARWIN-G4-DUMP: ('offset', 608)
+; DARWIN-G4-DUMP: ('alignment', 4)
+; DARWIN-G4-DUMP: ('reloc_offset', 700)
+; DARWIN-G4-DUMP: ('num_reloc', 4)
+; DARWIN-G4-DUMP: ('flags', 0x80000408)
+; DARWIN-G4-DUMP: ('reserved1', 0)
+; DARWIN-G4-DUMP: ('reserved2', 32)
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: ('_relocations', [
+; DARWIN-G4-DUMP: # Relocation 0
+; DARWIN-G4-DUMP: (('word-0', 0xab000014),
+; DARWIN-G4-DUMP: ('word-1', 0x70)),
+; DARWIN-G4-DUMP: # Relocation 1
+; DARWIN-G4-DUMP: (('word-0', 0xa1000000),
+; DARWIN-G4-DUMP: ('word-1', 0x58)),
+; DARWIN-G4-DUMP: # Relocation 2
+; DARWIN-G4-DUMP: (('word-0', 0xac00000c),
+; DARWIN-G4-DUMP: ('word-1', 0x70)),
+; DARWIN-G4-DUMP: # Relocation 3
+; DARWIN-G4-DUMP: (('word-0', 0xa1000018),
+; DARWIN-G4-DUMP: ('word-1', 0x58)),
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: # Section 3
+; DARWIN-G4-DUMP: (('section_name', '__la_symbol_ptr\x00')
+; DARWIN-G4-DUMP: ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('address', 112)
+; DARWIN-G4-DUMP: ('size', 4)
+; DARWIN-G4-DUMP: ('offset', 640)
+; DARWIN-G4-DUMP: ('alignment', 0)
+; DARWIN-G4-DUMP: ('reloc_offset', 732)
+; DARWIN-G4-DUMP: ('num_reloc', 1)
+; DARWIN-G4-DUMP: ('flags', 0x7)
+; DARWIN-G4-DUMP: ('reserved1', 1)
+; DARWIN-G4-DUMP: ('reserved2', 0)
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: ('_relocations', [
+; DARWIN-G4-DUMP: # Relocation 0
+; DARWIN-G4-DUMP: (('word-0', 0x0),
+; DARWIN-G4-DUMP: ('word-1', 0x250)),
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: # Section 4
+; DARWIN-G4-DUMP: (('section_name', '__cstring\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+; DARWIN-G4-DUMP: ('address', 116)
+; DARWIN-G4-DUMP: ('size', 14)
+; DARWIN-G4-DUMP: ('offset', 644)
+; DARWIN-G4-DUMP: ('alignment', 0)
+; DARWIN-G4-DUMP: ('reloc_offset', 0)
+; DARWIN-G4-DUMP: ('num_reloc', 0)
+; DARWIN-G4-DUMP: ('flags', 0x2)
+; DARWIN-G4-DUMP: ('reserved1', 0)
+; DARWIN-G4-DUMP: ('reserved2', 0)
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: ('_relocations', [
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: # Load Command 1
+; DARWIN-G4-DUMP: (('command', 2)
+; DARWIN-G4-DUMP: ('size', 24)
+; DARWIN-G4-DUMP: ('symoff', 748)
+; DARWIN-G4-DUMP: ('nsyms', 3)
+; DARWIN-G4-DUMP: ('stroff', 784)
+; DARWIN-G4-DUMP: ('strsize', 40)
+; DARWIN-G4-DUMP: ('_string_data', '\x00_main\x00dyld_stub_binding_helper\x00_puts\x00\x00\x00')
+; DARWIN-G4-DUMP: ('_symbols', [
+; DARWIN-G4-DUMP: # Symbol 0
+; DARWIN-G4-DUMP: (('n_strx', 1)
+; DARWIN-G4-DUMP: ('n_type', 0xf)
+; DARWIN-G4-DUMP: ('n_sect', 1)
+; DARWIN-G4-DUMP: ('n_desc', 0)
+; DARWIN-G4-DUMP: ('n_value', 0)
+; DARWIN-G4-DUMP: ('_string', '_main')
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: # Symbol 1
+; DARWIN-G4-DUMP: (('n_strx', 32)
+; DARWIN-G4-DUMP: ('n_type', 0x1)
+; DARWIN-G4-DUMP: ('n_sect', 0)
+; DARWIN-G4-DUMP: ('n_desc', 1)
+; DARWIN-G4-DUMP: ('n_value', 0)
+; DARWIN-G4-DUMP: ('_string', '_puts')
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: # Symbol 2
+; DARWIN-G4-DUMP: (('n_strx', 7)
+; DARWIN-G4-DUMP: ('n_type', 0x1)
+; DARWIN-G4-DUMP: ('n_sect', 0)
+; DARWIN-G4-DUMP: ('n_desc', 0)
+; DARWIN-G4-DUMP: ('n_value', 0)
+; DARWIN-G4-DUMP: ('_string', 'dyld_stub_binding_helper')
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: # Load Command 2
+; DARWIN-G4-DUMP: (('command', 11)
+; DARWIN-G4-DUMP: ('size', 80)
+; DARWIN-G4-DUMP: ('ilocalsym', 0)
+; DARWIN-G4-DUMP: ('nlocalsym', 0)
+; DARWIN-G4-DUMP: ('iextdefsym', 0)
+; DARWIN-G4-DUMP: ('nextdefsym', 1)
+; DARWIN-G4-DUMP: ('iundefsym', 1)
+; DARWIN-G4-DUMP: ('nundefsym', 2)
+; DARWIN-G4-DUMP: ('tocoff', 0)
+; DARWIN-G4-DUMP: ('ntoc', 0)
+; DARWIN-G4-DUMP: ('modtaboff', 0)
+; DARWIN-G4-DUMP: ('nmodtab', 0)
+; DARWIN-G4-DUMP: ('extrefsymoff', 0)
+; DARWIN-G4-DUMP: ('nextrefsyms', 0)
+; DARWIN-G4-DUMP: ('indirectsymoff', 740)
+; DARWIN-G4-DUMP: ('nindirectsyms', 2)
+; DARWIN-G4-DUMP: ('extreloff', 0)
+; DARWIN-G4-DUMP: ('nextrel', 0)
+; DARWIN-G4-DUMP: ('locreloff', 0)
+; DARWIN-G4-DUMP: ('nlocrel', 0)
+; DARWIN-G4-DUMP: ('_indirect_symbols', [
+; DARWIN-G4-DUMP: # Indirect Symbol 0
+; DARWIN-G4-DUMP: (('symbol_index', 0x1),),
+; DARWIN-G4-DUMP: # Indirect Symbol 1
+; DARWIN-G4-DUMP: (('symbol_index', 0x1),),
+; DARWIN-G4-DUMP: ])
+; DARWIN-G4-DUMP: ),
+; DARWIN-G4-DUMP: ])
More information about the llvm-commits
mailing list