diff --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp --- a/llvm/lib/MC/XCOFFObjectWriter.cpp +++ b/llvm/lib/MC/XCOFFObjectWriter.cpp @@ -384,11 +384,26 @@ const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) { - - if (Target.getSymB()) - report_fatal_error("Handling Target.SymB for relocation is unimplemented."); - - const MCSymbol &SymA = Target.getSymA()->getSymbol(); + auto getIndex = [this](const MCSymbol *Sym, + const MCSectionXCOFF *ContainingCsect) { + // If we could not find the symbol directly in SymbolIndexMap, this symbol + // could either be a temporary symbol or an undefined symbol. In this case, + // we would need to have the relocation reference its csect instead. + return SymbolIndexMap.find(Sym) != SymbolIndexMap.end() + ? SymbolIndexMap[Sym] + : SymbolIndexMap[ContainingCsect->getQualNameSymbol()]; + }; + + auto getVirtualAddress = [this, + &Layout](const MCSymbol *Sym, + const MCSectionXCOFF *ContainingCsect) { + // If Sym is a csect, return csect's address. + // If Sym is a label, return csect's address + label's offset from the csect. + return SectionMap[ContainingCsect]->Address + + (Sym->isDefined() ? Layout.getSymbolOffset(*Sym) : 0); + }; + + const MCSymbol *const SymA = &Target.getSymA()->getSymbol(); MCAsmBackend &Backend = Asm.getBackend(); bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags & @@ -399,26 +414,15 @@ std::tie(Type, SignAndSize) = TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel); - const MCSectionXCOFF *SymASec = - getContainingCsect(cast(&SymA)); + const MCSectionXCOFF *SymASec = getContainingCsect(cast(SymA)); assert(SectionMap.find(SymASec) != SectionMap.end() && "Expected containing csect to exist in map."); - // If we could not find SymA directly in SymbolIndexMap, this symbol could - // either be a temporary symbol or an undefined symbol. In this case, we - // would need to have the relocation reference its csect instead. - uint32_t Index = SymbolIndexMap.find(&SymA) != SymbolIndexMap.end() - ? SymbolIndexMap[&SymA] - : SymbolIndexMap[SymASec->getQualNameSymbol()]; - + const uint32_t Index = getIndex(SymA, SymASec); if (Type == XCOFF::RelocationType::R_POS) // The FixedValue should be symbol's virtual address in this object file // plus any constant value that we might get. - // Notice that SymA.isDefined() could return false, but SymASec could still - // be a defined csect. One of the example is the TOC-base symbol. - FixedValue = SectionMap[SymASec]->Address + - (SymA.isDefined() ? Layout.getSymbolOffset(SymA) : 0) + - Target.getConstant(); + FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant(); else if (Type == XCOFF::RelocationType::R_TOC) // The FixedValue should be the TC entry offset from TOC-base. FixedValue = SectionMap[SymASec]->Address - TOCCsects.front().Address; @@ -435,6 +439,33 @@ assert(SectionMap.find(RelocationSec) != SectionMap.end() && "Expected containing csect to exist in map."); SectionMap[RelocationSec]->Relocations.push_back(Reloc); + + if (!Target.getSymB()) + return; + + const MCSymbol *const SymB = &Target.getSymB()->getSymbol(); + if (SymA == SymB) + report_fatal_error("relocation for opposite term is not yet supported"); + + const MCSectionXCOFF *SymBSec = getContainingCsect(cast(SymB)); + assert(SectionMap.find(SymBSec) != SectionMap.end() && + "Expected containing csect to exist in map."); + if (SymASec == SymBSec) + report_fatal_error( + "relocation for paired relocatable term is not yet supported"); + + assert(Type == XCOFF::RelocationType::R_POS && + "SymA must be R_POS here if it's not opposite term or paired " + "relocatable term."); + const uint32_t IndexB = getIndex(SymB, SymBSec); + // SymB must be R_NEG here, given the general form of Target(MCValue) is + // "SymbolA - SymbolB + imm64". + const uint8_t TypeB = XCOFF::RelocationType::R_NEG; + XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB}; + SectionMap[RelocationSec]->Relocations.push_back(RelocB); + // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA, + // now we just need to fold "- SymbolB" here. + FixedValue -= getVirtualAddress(SymB, SymBSec); } void XCOFFObjectWriter::writeSections(const MCAssembler &Asm, diff --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-reloc-symb.mir b/llvm/test/CodeGen/PowerPC/aix-xcoff-reloc-symb.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-reloc-symb.mir @@ -0,0 +1,83 @@ +# RUN: llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc-ibm-aix-xcoff -x mir -verify-machineinstrs -start-after=lazy-machine-block-freq -filetype=obj -o %t.o < %s +# RUN: llvm-readobj --relocs --expand-relocs -t %t.o | FileCheck --check-prefixes=RELOC,SYM %s +# RUN: llvm-objdump -D %t.o | FileCheck --check-prefix=DIS %s + +--- +name: foo +alignment: 16 +tracksRegLiveness: true +jumpTable: + kind: label-difference32 + entries: + - id: 0 + blocks: [ '%bb.0' ] +body: | + bb.0: + successors: %bb.0(0x20000000) + liveins: $r2 + renamable $r3 = LWZtoc %jump-table.0, $r2 :: (load 4 from got) + BLR implicit $lr, implicit $rm, implicit killed $r3 +... + +# RELOC: Relocation {{[{][[:space:]] *}}Virtual Address: 0x8 +# RELOC-NEXT: Symbol: .text ([[#TXT_INDX:]]) +# RELOC-NEXT: IsSigned: No +# RELOC-NEXT: FixupBitValue: 0 +# RELOC-NEXT: Length: 32 +# RELOC-NEXT: Type: R_POS (0x0) +# RELOC-NEXT: } +# RELOC-NEXT: Relocation { +# RELOC-NEXT: Virtual Address: 0x8 +# RELOC-NEXT: Symbol: .rodata ([[#RO_INDX:]]) +# RELOC-NEXT: IsSigned: No +# RELOC-NEXT: FixupBitValue: 0 +# RELOC-NEXT: Length: 32 +# RELOC-NEXT: Type: R_NEG (0x1) +# RELOC-NEXT: } + +# SYM: Symbol {{[{][[:space:]] *}}Index: [[#TXT_INDX]]{{[[:space:]] *}}Name: .text +# SYM-NEXT: Value (RelocatableAddress): 0x0 +# SYM-NEXT: Section: .text +# SYM-NEXT: Type: 0x0 +# SYM-NEXT: StorageClass: C_HIDEXT (0x6B) +# SYM-NEXT: NumberOfAuxEntries: 1 +# SYM-NEXT: CSECT Auxiliary Entry { +# SYM-NEXT: Index: [[#TXT_INDX+1]] +# SYM-NEXT: SectionLen: 8 +# SYM-NEXT: ParameterHashIndex: 0x0 +# SYM-NEXT: TypeChkSectNum: 0x0 +# SYM-NEXT: SymbolAlignmentLog2: 4 +# SYM-NEXT: SymbolType: XTY_SD (0x1) +# SYM-NEXT: StorageMappingClass: XMC_PR (0x0) +# SYM-NEXT: StabInfoIndex: 0x0 +# SYM-NEXT: StabSectNum: 0x0 +# SYM-NEXT: } +# SYM-NEXT: } +# SYM: Symbol {{[{][[:space:]] *}}Index: [[#RO_INDX]]{{[[:space:]] *}}Name: .rodata +# SYM-NEXT: Value (RelocatableAddress): 0x8 +# SYM-NEXT: Section: .text +# SYM-NEXT: Type: 0x0 +# SYM-NEXT: StorageClass: C_HIDEXT (0x6B) +# SYM-NEXT: NumberOfAuxEntries: 1 +# SYM-NEXT: CSECT Auxiliary Entry { +# SYM-NEXT: Index: [[#RO_INDX+1]] +# SYM-NEXT: SectionLen: 4 +# SYM-NEXT: ParameterHashIndex: 0x0 +# SYM-NEXT: TypeChkSectNum: 0x0 +# SYM-NEXT: SymbolAlignmentLog2: 2 +# SYM-NEXT: SymbolType: XTY_SD (0x1) +# SYM-NEXT: StorageMappingClass: XMC_RO (0x1) +# SYM-NEXT: StabInfoIndex: 0x0 +# SYM-NEXT: StabSectNum: 0x0 +# SYM-NEXT: } +# SYM-NEXT: } + +# DIS: Disassembly of section .text: +# DIS-EMPTY: +# DIS-NEXT: 00000000 <.text>: +# DIS-NEXT: 0: 80 62 00 00 lwz 3, 0(2) +# DIS-NEXT: 4: 4e 80 00 20 blr +# DIS-EMPTY: +# DIS-NEXT: 00000008 <.rodata>: +# DIS-NEXT: 8: ff ff ff f8 fmsub 31, 31, 31, 31 +# DIS-EMPTY: