From a3967b6844f4be588c724ada3692e734bba65cf1 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Wed, 8 May 2013 17:50:07 +0000 Subject: [PowerPC] Fix regression in generating @ha/@l relocs The patch I committed as revision 167864 introduced a regression that causes LLVM to no longer generate appropriate relocs for @ha/@l symbol references (but fail an assertion instead). This is fixed here by re-enabling support for the VK_PPC_GAS_HA16/ VK_PPC_GAS_LO16 variant kinds (and their Darwin variants) in PPCELFObjectWriter.cpp. Tested by running projects/test-suite in -m32 mode with the integrated assembler forced on. A standalone test case will be committed shortly as well. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181450 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp') diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index 81a86dc..7a84723 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -107,7 +107,8 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_PPC_DTPREL16_HA: Type = ELF::R_PPC64_DTPREL16_HA; break; - case MCSymbolRefExpr::VK_None: + case MCSymbolRefExpr::VK_PPC_GAS_HA16: + case MCSymbolRefExpr::VK_PPC_DARWIN_HA16: Type = ELF::R_PPC_ADDR16_HA; break; case MCSymbolRefExpr::VK_PPC_TOC16_HA: @@ -134,6 +135,10 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, Type = ELF::R_PPC64_DTPREL16_LO; break; case MCSymbolRefExpr::VK_None: + Type = ELF::R_PPC_ADDR16; + break; + case MCSymbolRefExpr::VK_PPC_GAS_LO16: + case MCSymbolRefExpr::VK_PPC_DARWIN_LO16: Type = ELF::R_PPC_ADDR16_LO; break; case MCSymbolRefExpr::VK_PPC_TOC_ENTRY: @@ -156,6 +161,10 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_None: Type = ELF::R_PPC64_ADDR16_DS; break; + case MCSymbolRefExpr::VK_PPC_GAS_LO16: + case MCSymbolRefExpr::VK_PPC_DARWIN_LO16: + Type = ELF::R_PPC64_ADDR16_LO_DS; + break; case MCSymbolRefExpr::VK_PPC_TOC_ENTRY: Type = ELF::R_PPC64_TOC16_DS; break; -- cgit v1.1 From 9122396a4dea52cf917062782fc2f39c7dc698bb Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Wed, 15 May 2013 15:07:06 +0000 Subject: [PowerPC] Remove need for adjustFixupOffst hack Now that applyFixup understands differently-sized fixups, we can define fixup_ppc_lo16/fixup_ppc_lo16_ds/fixup_ppc_ha16 to properly be 2-byte fixups, applied at an offset of 2 relative to the start of the instruction text. This has the benefit that if we actually need to generate a real relocation record, its address will come out correctly automatically, without having to fiddle with the offset in adjustFixupOffset. Tested on both 64-bit and 32-bit PowerPC, using external and integrated assembler. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181894 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp') diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index 7a84723..c09ae0e 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -33,7 +33,6 @@ namespace { virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const; - virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset); virtual void sortRelocs(const MCAssembler &Asm, std::vector &Relocs); @@ -240,19 +239,6 @@ const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Targe return NULL; } -void PPCELFObjectWriter:: -adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) { - switch ((unsigned)Fixup.getKind()) { - case PPC::fixup_ppc_ha16: - case PPC::fixup_ppc_lo16: - case PPC::fixup_ppc_lo16_ds: - RelocOffset += 2; - break; - default: - break; - } -} - // The standard sorter only sorts on the r_offset field, but PowerPC can // have multiple relocations at the same offset. Sort secondarily on the // relocation type to avoid nondeterminism. -- cgit v1.1 From 4ef61f2ad4ff509ee05c7051d359009511f81226 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 15 May 2013 18:22:01 +0000 Subject: Cleanup relocation sorting for ELF. We want the order to be deterministic on all platforms. NAKAMURA Takumi fixed that in r181864. This patch is just two small cleanups: * Move the function to the cpp file. It is only passed to array_pod_sort. * Remove the ppc implementation which is now redundant git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181910 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp | 44 ---------------------- 1 file changed, 44 deletions(-) (limited to 'lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp') diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index c09ae0e..2508cc2 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -33,25 +33,9 @@ namespace { virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const; - - virtual void sortRelocs(const MCAssembler &Asm, - std::vector &Relocs); - }; - - class PPCELFRelocationEntry : public ELFRelocationEntry { - public: - PPCELFRelocationEntry(const ELFRelocationEntry &RE); - bool operator<(const PPCELFRelocationEntry &RE) const { - return (RE.r_offset < r_offset || - (RE.r_offset == r_offset && RE.Type > Type)); - } }; } -PPCELFRelocationEntry::PPCELFRelocationEntry(const ELFRelocationEntry &RE) - : ELFRelocationEntry(RE.r_offset, RE.Index, RE.Type, RE.Symbol, - RE.r_addend, *RE.Fixup) {} - PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) : MCELFObjectTargetWriter(Is64Bit, OSABI, Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC, @@ -239,34 +223,6 @@ const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Targe return NULL; } -// The standard sorter only sorts on the r_offset field, but PowerPC can -// have multiple relocations at the same offset. Sort secondarily on the -// relocation type to avoid nondeterminism. -void PPCELFObjectWriter::sortRelocs(const MCAssembler &Asm, - std::vector &Relocs) { - - // Copy to a temporary vector of relocation entries having a different - // sort function. - std::vector TmpRelocs; - - for (std::vector::iterator R = Relocs.begin(); - R != Relocs.end(); ++R) { - TmpRelocs.push_back(PPCELFRelocationEntry(*R)); - } - - // Sort in place by ascending r_offset and descending r_type. - array_pod_sort(TmpRelocs.begin(), TmpRelocs.end()); - - // Copy back to the original vector. - unsigned I = 0; - for (std::vector::iterator R = TmpRelocs.begin(); - R != TmpRelocs.end(); ++R, ++I) { - Relocs[I] = ELFRelocationEntry(R->r_offset, R->Index, R->Type, - R->Symbol, R->r_addend, *R->Fixup); - } -} - - MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS, bool Is64Bit, uint8_t OSABI) { -- cgit v1.1 From c299ad32c8e59ceea05ede15e1c59ac787d17feb Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Fri, 17 May 2013 12:36:29 +0000 Subject: [PowerPC] Fix processing of ha16/lo16 fixups The current PowerPC MC back end distinguishes between fixup_ppc_ha16 and fixup_ppc_lo16, which are determined by the instruction the fixup applies to, and uses this distinction to decide whether a fixup ought to resolve to the high or the low part of a symbol address. This isn't quite correct, however. It is valid -if unusual- assembler to use, e.g. li 1, symbol@ha or lis 1, symbol@l Whether the high or the low part of the address is used depends solely on the @ suffix, not on the instruction. In addition, both li 1, symbol and lis 1, symbol are valid, assuming the symbol address fits into 16 bits; again, both will then refer to the actual symbol value (so li will load the value itself, while lis will load the value shifted by 16). To fix this, two places need to be adapted. If the fixup cannot be resolved at assembler time, a relocation needs to be emitted via PPCELFObjectWriter::getRelocType. This routine already looks at the VK_ type to determine the relocation. The only problem is that will reject any _LO modifier in a ha16 fixup and vice versa. This is simply incorrect; any of those modifiers ought to be accepted for either fixup type. If the fixup *can* be resolved at assembler time, adjustFixupValue currently selects the high bits of the symbol value if the fixup type is ha16. Again, this is incorrect; see the above example lis 1, symbol Now, in theory we'd have to respect a VK_ modifier here. However, in fact common code never even attempts to resolve symbol references using any nontrivial VK_ modifier at assembler time; it will always fall back to emitting a reloc and letting the linker handle it. If this ever changes, presumably there'd have to be a target callback to resolve VK_ modifiers. We'd then have to handle @ha etc. there. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182091 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp') diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index 2508cc2..5193dca 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -82,6 +82,7 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_ break; case PPC::fixup_ppc_ha16: + case PPC::fixup_ppc_lo16: switch (Modifier) { default: llvm_unreachable("Unsupported Modifier"); case MCSymbolRefExpr::VK_PPC_TPREL16_HA: @@ -106,11 +107,6 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_HA: Type = ELF::R_PPC64_GOT_TLSLD16_HA; break; - } - break; - case PPC::fixup_ppc_lo16: - switch (Modifier) { - default: llvm_unreachable("Unsupported Modifier"); case MCSymbolRefExpr::VK_PPC_TPREL16_LO: Type = ELF::R_PPC_TPREL16_LO; break; -- cgit v1.1 From e152eac63efa836cbb109d79e4307516fa16f1a6 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Fri, 17 May 2013 12:37:21 +0000 Subject: [PowerPC] Merge/rename PPC fixup types Now that fixup_ppc_ha16 and fixup_ppc_lo16 are being treated exactly the same everywhere, it no longer makes sense to have two fixup types. This patch merges them both into a single type fixup_ppc_half16, and renames fixup_ppc_lo16_ds to fixup_ppc_half16ds for consistency. (The half16 and half16ds names are taken from the description of relocation types in the PowerPC ABI.) No change in code generation expected. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182092 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp') diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index 5193dca..5c272c0 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -81,8 +81,7 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, case PPC::fixup_ppc_brcond14: Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_ break; - case PPC::fixup_ppc_ha16: - case PPC::fixup_ppc_lo16: + case PPC::fixup_ppc_half16: switch (Modifier) { default: llvm_unreachable("Unsupported Modifier"); case MCSymbolRefExpr::VK_PPC_TPREL16_HA: @@ -134,7 +133,7 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, break; } break; - case PPC::fixup_ppc_lo16_ds: + case PPC::fixup_ppc_half16ds: switch (Modifier) { default: llvm_unreachable("Unsupported Modifier"); case MCSymbolRefExpr::VK_None: -- cgit v1.1 From edaa58ee66699b99841ee5dfdd485aedbae3bf90 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 23 May 2013 22:26:41 +0000 Subject: [PowerPC] Clean up generation of ha16() / lo16() markers When targeting the Darwin assembler, we need to generate markers ha16() and lo16() to designate the high and low parts of a (symbolic) immediate. This is necessary not just for plain symbols, but also for certain symbolic expression, typically along the lines of ha16(A - B). The latter doesn't work when simply using VariantKind flags on the symbol reference. This is why the current back-end uses hacks (explicitly called out as such via multiple FIXMEs) in the symbolLo/symbolHi print methods. This patch uses target-defined MCExpr codes to represent the Darwin ha16/lo16 constructs, following along the lines of the equivalent solution used by the ARM back end to handle their :upper16: / :lower16: markers. This allows us to get rid of special handling both in the symbolLo/symbolHi print method and in the common code MCExpr::print routine. Instead, the ha16 / lo16 markers are printed simply in a custom print routine for the target MCExpr types. (As a result, the symbolLo/symbolHi print methods can now replaced by a single printS16ImmOperand routine that also handles symbolic operands.) The patch also provides a EvaluateAsRelocatableImpl routine to handle ha16/lo16 constructs. This is not actually used at the moment by any in-tree code, but is provided as it makes merging into David Fang's out-of-tree Mach-O object writer simpler. Since there is no longer any need to treat VK_PPC_GAS_HA16 and VK_PPC_DARWIN_HA16 differently, they are merged into a single VK_PPC_ADDR16_HA (and likewise for the _LO16 types). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182616 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp') diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp index 5c272c0..7188f93 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -90,8 +90,7 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_PPC_DTPREL16_HA: Type = ELF::R_PPC64_DTPREL16_HA; break; - case MCSymbolRefExpr::VK_PPC_GAS_HA16: - case MCSymbolRefExpr::VK_PPC_DARWIN_HA16: + case MCSymbolRefExpr::VK_PPC_ADDR16_HA: Type = ELF::R_PPC_ADDR16_HA; break; case MCSymbolRefExpr::VK_PPC_TOC16_HA: @@ -115,8 +114,7 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_None: Type = ELF::R_PPC_ADDR16; break; - case MCSymbolRefExpr::VK_PPC_GAS_LO16: - case MCSymbolRefExpr::VK_PPC_DARWIN_LO16: + case MCSymbolRefExpr::VK_PPC_ADDR16_LO: Type = ELF::R_PPC_ADDR16_LO; break; case MCSymbolRefExpr::VK_PPC_TOC_ENTRY: @@ -139,8 +137,7 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_None: Type = ELF::R_PPC64_ADDR16_DS; break; - case MCSymbolRefExpr::VK_PPC_GAS_LO16: - case MCSymbolRefExpr::VK_PPC_DARWIN_LO16: + case MCSymbolRefExpr::VK_PPC_ADDR16_LO: Type = ELF::R_PPC64_ADDR16_LO_DS; break; case MCSymbolRefExpr::VK_PPC_TOC_ENTRY: -- cgit v1.1