Index: llvm/lib/MC/XCOFFObjectWriter.cpp =================================================================== --- llvm/lib/MC/XCOFFObjectWriter.cpp +++ 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, Index: llvm/test/CodeGen/PowerPC/aix-xcoff-reloc-symb.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/PowerPC/aix-xcoff-reloc-symb.mir @@ -0,0 +1,92 @@ +# 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.4' ] +body: | + bb.1: + successors: %bb.4(0x20000000) + liveins: $r2, $r3 + renamable $r4 = LWZtoc %jump-table.0, $r2 :: (load 4 from got) + renamable $r3 = LWZX killed renamable $r3, renamable $r4 :: (load 4 from jump-table) + MTCTR killed renamable $r3, implicit-def $ctr + BCTR implicit $ctr + bb.4: + renamable $r3 = LI 2 + STW killed renamable $r3, -12, $r1 +... + +# RELOC: Relocation {{[{][[:space:]] *}}Virtual Address: 0x18 +# 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: 0x18 +# 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: 1 +# SYM-NEXT: SectionLen: 24 +# 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): 0x18 +# 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: 5 +# 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 82 00 00 lwz 4, 0(2) +# DIS-NEXT: 4: 7c 63 20 2e lwzx 3, 3, 4 +# DIS-NEXT: 8: 7c 69 03 a6 mtctr 3 +# DIS-NEXT: c: 4e 80 04 20 bctr +# DIS-NEXT: 10: 38 60 00 02 li 3, 2 +# DIS-NEXT: 14: 90 61 ff f4 stw 3, -12(1) +# DIS-EMPTY: +# DIS-NEXT: 00000018 <.rodata>: +# DIS-NEXT: 18: ff ff ff f8 fmsub 31, 31, 31, 31 +# DIS-EMPTY: