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 defined, then it's a label. We need to add label's offset from + // its containting csect to get the correct virtual address for it. + return SectionMap[ContainingCsect]->Address + + (Sym->isDefined() ? Layout.getSymbolOffset(*Sym) : 0); + }; + + const MCSymbol *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 *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.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/PowerPC/aix-xcoff-reloc-symb.ll @@ -0,0 +1,344 @@ +; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc-ibm-aix-xcoff -mattr=-altivec -filetype=obj -o %t.o < %s +; RUN: llvm-readobj --relocs --expand-relocs %t.o | FileCheck --check-prefix=RELOC %s +; RUN: llvm-readobj -t %t.o | FileCheck --check-prefix=SYM %s +; RUN: llvm-objdump -D %t.o | FileCheck --check-prefix=DIS %s + +; RUN: not --crash llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc64-ibm-aix-xcoff -mattr=-altivec -filetype=obj < %s 2>&1 | \ +; RUN: FileCheck --check-prefix=XCOFF64 %s +; XCOFF64: LLVM ERROR: 64-bit XCOFF object files are not supported yet. + +; // The IR below is generated by "clang -cc1 -triple powerpc-aix-xcoff -emit-llvm" +; // with the following source. +; int foo(int rc) { +; int a = 0; +; switch(rc) { +; case 0: +; return 1; +; case 1: +; return 1; +; case 2: +; a = 1; +; case 3: +; a = 2; +; default: +; a = 3; +; break; +; } +; return a; +; } + +define i32 @foo(i32 %rc) #0 { +entry: + %retval = alloca i32, align 4 + %rc.addr = alloca i32, align 4 + %a = alloca i32, align 4 + store i32 %rc, i32* %rc.addr, align 4 + store i32 0, i32* %a, align 4 + %0 = load i32, i32* %rc.addr, align 4 + switch i32 %0, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + ] + +sw.bb: ; preds = %entry + store i32 1, i32* %retval, align 4 + br label %return + +sw.bb1: ; preds = %entry + store i32 1, i32* %retval, align 4 + br label %return + +sw.bb2: ; preds = %entry + store i32 1, i32* %a, align 4 + br label %sw.bb3 + +sw.bb3: ; preds = %entry, %sw.bb2 + store i32 2, i32* %a, align 4 + br label %sw.default + +sw.default: ; preds = %entry, %sw.bb3 + store i32 3, i32* %a, align 4 + br label %sw.epilog + +sw.epilog: ; preds = %sw.default + %1 = load i32, i32* %a, align 4 + store i32 %1, i32* %retval, align 4 + br label %return + +return: ; preds = %sw.epilog, %sw.bb1, %sw.bb + %2 = load i32, i32* %retval, align 4 + ret i32 %2 +} + + +; RELOC: Relocations [ +; RELOC-NEXT: Section (index: 1) .text { +; RELOC-NEXT: Relocation { +; RELOC-NEXT: Virtual Address: 0x16 +; RELOC-NEXT: Symbol: .LJTI0_0 (10) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 16 +; RELOC-NEXT: Type: R_TOC (0x3) +; RELOC-NEXT: } +; RELOC-NEXT: Relocation { +; RELOC-NEXT: Virtual Address: 0x58 +; RELOC-NEXT: Symbol: .text (0) +; 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: 0x58 +; RELOC-NEXT: Symbol: .rodata (4) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 32 +; RELOC-NEXT: Type: R_NEG (0x1) +; RELOC-NEXT: } +; RELOC-NEXT: Relocation { +; RELOC-NEXT: Virtual Address: 0x5C +; RELOC-NEXT: Symbol: .text (0) +; 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: 0x5C +; RELOC-NEXT: Symbol: .rodata (4) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 32 +; RELOC-NEXT: Type: R_NEG (0x1) +; RELOC-NEXT: } +; RELOC-NEXT: Relocation { +; RELOC-NEXT: Virtual Address: 0x60 +; RELOC-NEXT: Symbol: .text (0) +; 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: 0x60 +; RELOC-NEXT: Symbol: .rodata (4) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 32 +; RELOC-NEXT: Type: R_NEG (0x1) +; RELOC-NEXT: } +; RELOC-NEXT: Relocation { +; RELOC-NEXT: Virtual Address: 0x64 +; RELOC-NEXT: Symbol: .text (0) +; 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: 0x64 +; RELOC-NEXT: Symbol: .rodata (4) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 32 +; RELOC-NEXT: Type: R_NEG (0x1) +; RELOC-NEXT: } +; RELOC-NEXT: } +; RELOC-NEXT: Section (index: 2) .data { +; RELOC-NEXT: Relocation { +; RELOC-NEXT: Virtual Address: 0x68 +; RELOC-NEXT: Symbol: .foo (2) +; 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: 0x6C +; RELOC-NEXT: Symbol: TOC (8) +; 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: 0x74 +; RELOC-NEXT: Symbol: .rodata (4) +; RELOC-NEXT: IsSigned: No +; RELOC-NEXT: FixupBitValue: 0 +; RELOC-NEXT: Length: 32 +; RELOC-NEXT: Type: R_POS (0x0) +; RELOC-NEXT: } +; RELOC-NEXT: } +; RELOC-NEXT: ] + + +; SYM: Symbols [ +; SYM-NEXT: Symbol { +; SYM-NEXT: Index: 0 +; SYM-NEXT: 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: 88 +; 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-NEXT: Symbol { +; SYM-NEXT: Index: 2 +; SYM-NEXT: Name: .foo +; SYM-NEXT: Value (RelocatableAddress): 0x0 +; SYM-NEXT: Section: .text +; SYM-NEXT: Type: 0x0 +; SYM-NEXT: StorageClass: C_EXT (0x2) +; SYM-NEXT: NumberOfAuxEntries: 1 +; SYM-NEXT: CSECT Auxiliary Entry { +; SYM-NEXT: Index: 3 +; SYM-NEXT: ContainingCsectSymbolIndex: 0 +; SYM-NEXT: ParameterHashIndex: 0x0 +; SYM-NEXT: TypeChkSectNum: 0x0 +; SYM-NEXT: SymbolAlignmentLog2: 0 +; SYM-NEXT: SymbolType: XTY_LD (0x2) +; SYM-NEXT: StorageMappingClass: XMC_PR (0x0) +; SYM-NEXT: StabInfoIndex: 0x0 +; SYM-NEXT: StabSectNum: 0x0 +; SYM-NEXT: } +; SYM-NEXT: } +; SYM-NEXT: Symbol { +; SYM-NEXT: Index: 4 +; SYM-NEXT: Name: .rodata +; SYM-NEXT: Value (RelocatableAddress): 0x58 +; 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: 16 +; 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: } +; SYM-NEXT: Symbol { +; SYM-NEXT: Index: 6 +; SYM-NEXT: Name: foo +; SYM-NEXT: Value (RelocatableAddress): 0x68 +; SYM-NEXT: Section: .data +; SYM-NEXT: Type: 0x0 +; SYM-NEXT: StorageClass: C_EXT (0x2) +; SYM-NEXT: NumberOfAuxEntries: 1 +; SYM-NEXT: CSECT Auxiliary Entry { +; SYM-NEXT: Index: 7 +; SYM-NEXT: SectionLen: 12 +; SYM-NEXT: ParameterHashIndex: 0x0 +; SYM-NEXT: TypeChkSectNum: 0x0 +; SYM-NEXT: SymbolAlignmentLog2: 2 +; SYM-NEXT: SymbolType: XTY_SD (0x1) +; SYM-NEXT: StorageMappingClass: XMC_DS (0xA) +; SYM-NEXT: StabInfoIndex: 0x0 +; SYM-NEXT: StabSectNum: 0x0 +; SYM-NEXT: } +; SYM-NEXT: } +; SYM-NEXT: Symbol { +; SYM-NEXT: Index: 8 +; SYM-NEXT: Name: TOC +; SYM-NEXT: Value (RelocatableAddress): 0x74 +; SYM-NEXT: Section: .data +; SYM-NEXT: Type: 0x0 +; SYM-NEXT: StorageClass: C_HIDEXT (0x6B) +; SYM-NEXT: NumberOfAuxEntries: 1 +; SYM-NEXT: CSECT Auxiliary Entry { +; SYM-NEXT: Index: 9 +; SYM-NEXT: SectionLen: 0 +; SYM-NEXT: ParameterHashIndex: 0x0 +; SYM-NEXT: TypeChkSectNum: 0x0 +; SYM-NEXT: SymbolAlignmentLog2: 2 +; SYM-NEXT: SymbolType: XTY_SD (0x1) +; SYM-NEXT: StorageMappingClass: XMC_TC0 (0xF) +; SYM-NEXT: StabInfoIndex: 0x0 +; SYM-NEXT: StabSectNum: 0x0 +; SYM-NEXT: } +; SYM-NEXT: } +; SYM-NEXT: Symbol { +; SYM-NEXT: Index: 10 +; SYM-NEXT: Name: .LJTI0_0 +; SYM-NEXT: Value (RelocatableAddress): 0x74 +; SYM-NEXT: Section: .data +; SYM-NEXT: Type: 0x0 +; SYM-NEXT: StorageClass: C_HIDEXT (0x6B) +; SYM-NEXT: NumberOfAuxEntries: 1 +; SYM-NEXT: CSECT Auxiliary Entry { +; SYM-NEXT: Index: 11 +; 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_TC (0x3) +; SYM-NEXT: StabInfoIndex: 0x0 +; SYM-NEXT: StabSectNum: 0x0 +; SYM-NEXT: } +; SYM-NEXT: } +; SYM-NEXT: ] + +; DIS: Disassembly of section .text: +; DIS-EMPTY: +; DIS-NEXT: 00000000 <.text>: +; DIS-NEXT: 0: 38 80 00 00 li 4, 0 +; DIS-NEXT: 4: 28 03 00 03 cmplwi 3, 3 +; DIS-NEXT: 8: 90 61 ff f8 stw 3, -8(1) +; DIS-NEXT: c: 90 81 ff f4 stw 4, -12(1) +; DIS-NEXT: 10: 41 81 00 34 bt 1, .+52 +; DIS-NEXT: 14: 80 82 00 00 lwz 4, 0(2) +; DIS-NEXT: 18: 54 63 10 3a slwi 3, 3, 2 +; DIS-NEXT: 1c: 7c 63 20 2e lwzx 3, 3, 4 +; DIS-NEXT: 20: 7c 63 22 14 add 3, 3, 4 +; DIS-NEXT: 24: 7c 69 03 a6 mtctr 3 +; DIS-NEXT: 28: 4e 80 04 20 bctr +; DIS-NEXT: 2c: 38 60 00 01 li 3, 1 +; DIS-NEXT: 30: 48 00 00 1c b .+28 +; DIS-NEXT: 34: 38 60 00 01 li 3, 1 +; DIS-NEXT: 38: 90 61 ff f4 stw 3, -12(1) +; DIS-NEXT: 3c: 38 60 00 02 li 3, 2 +; DIS-NEXT: 40: 90 61 ff f4 stw 3, -12(1) +; DIS-NEXT: 44: 38 60 00 03 li 3, 3 +; DIS-NEXT: 48: 90 61 ff f4 stw 3, -12(1) +; DIS-NEXT: 4c: 90 61 ff fc stw 3, -4(1) +; DIS-NEXT: 50: 80 61 ff fc lwz 3, -4(1) +; DIS-NEXT: 54: 4e 80 00 20 blr +; DIS-EMPTY: +; DIS-NEXT: 00000058 <.rodata>: +; DIS-NEXT: 58: ff ff ff d4 +; DIS-NEXT: 5c: ff ff ff d4 +; DIS-NEXT: 60: ff ff ff dc +; DIS-NEXT: 64: ff ff ff e4 +; DIS-EMPTY: +; DIS-NEXT: Disassembly of section .data: +; DIS-EMPTY: +; DIS-NEXT: 00000068 : +; DIS-NEXT: 68: 00 00 00 00 +; DIS-NEXT: 6c: 00 00 00 74 +; DIS-NEXT: 70: 00 00 00 00 +; DIS-EMPTY: +; DIS-NEXT: 00000074 : +; DIS-NEXT: 74: 00 00 00 58 +