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 @@ -664,10 +664,10 @@ // address, fragment offset and Fixup offset. uint64_t BRInstrAddress = SectionMap[ParentSec]->Address + FixupOffsetInCsect; - // The FixedValue should be the difference between SymA csect address and BR - // instr address plus any constant value. - FixedValue = - SectionMap[SymASec]->Address - BRInstrAddress + Target.getConstant(); + // The FixedValue should be the difference between symbol's virtual address + // and BR instr address plus any constant value. + FixedValue = getVirtualAddress(SymA, SymASec) - BRInstrAddress + + Target.getConstant(); } else if (Type == XCOFF::RelocationType::R_REF) { // The FixedValue and FixupOffsetInCsect should always be 0 since it // specifies a nonrelocating reference. diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -19,6 +19,7 @@ #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/MCSymbolXCOFF.h" #include "llvm/MC/MCValue.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" @@ -178,7 +179,10 @@ unsigned Other = S->getOther() << 2; if ((Other & ELF::STO_PPC64_LOCAL_MASK) != 0) return true; - } + } else if (const auto *S = dyn_cast(&A->getSymbol())) { + return !Target.isAbsolute() && S->isExternal() && + S->getStorageClass() == XCOFF::C_WEAKEXT; + } } return false; } diff --git a/llvm/test/CodeGen/PowerPC/aix-weak-reloc.ll b/llvm/test/CodeGen/PowerPC/aix-weak-reloc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-weak-reloc.ll @@ -0,0 +1,46 @@ +; RUN: llc -mtriple powerpc-ibm-aix-xcoff -filetype=obj -o %t.o < %s +; RUN: llvm-objdump -dr %t.o | FileCheck --check-prefix=OBJ32 %s + +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -filetype=obj -o %t.o < %s +; RUN: llvm-objdump -dr %t.o | FileCheck --check-prefix=OBJ64 %s + +; Function Attrs: noinline nounwind optnone +define i32 @main() { +entry: + %retval = alloca i32, align 4 + store i32 0, ptr %retval, align 4 + %call = call i32 @foo() + ret i32 %call +} + +; Function Attrs: noinline nounwind optnone +define weak i32 @foo() { +entry: + ret i32 3 +} + +; OBJ32: 00000000 <.main>: +; OBJ32-NEXT: 0: 7c 08 02 a6 mflr 0 +; OBJ32-NEXT: 4: 94 21 ff c0 stwu 1, -64(1) +; OBJ32-NEXT: 8: 38 60 00 00 li 3, 0 +; OBJ32-NEXT: c: 90 01 00 48 stw 0, 72(1) +; OBJ32-NEXT: 10: 90 61 00 3c stw 3, 60(1) +; OBJ32-NEXT: 14: 48 00 00 31 bl 0x44 <.foo> +; OBJ32-NEXT: 00000014: R_RBR .foo +; OBJ32-NEXT: 18: 60 00 00 00 nop +; OBJ32: 00000044 <.foo>: +; OBJ32-NEXT: 44: 38 60 00 03 li 3, 3 +; OBJ32-NEXT: 48: 4e 80 00 20 blr + +; OBJ64: 0000000000000000 <.main>: +; OBJ64-NEXT: 0: 7c 08 02 a6 mflr 0 +; OBJ64-NEXT: 4: f8 21 ff 81 stdu 1, -128(1) +; OBJ64-NEXT: 8: 38 60 00 00 li 3, 0 +; OBJ64-NEXT: c: f8 01 00 90 std 0, 144(1) +; OBJ64-NEXT: 10: 90 61 00 7c stw 3, 124(1) +; OBJ64-NEXT: 14: 48 00 00 31 bl 0x44 <.foo> +; OBJ64-NEXT: 0000000000000014: R_RBR .foo +; OBJ64-NEXT: 18: 60 00 00 00 nop +; OBJ64: 0000000000000044 <.foo>: +; OBJ64-NEXT: 44: 38 60 00 03 li 3, 3 +; OBJ64-NEXT: 48: 4e 80 00 20 blr