diff --git a/lld/test/ELF/ppc64-toc-call-to-pcrel.s b/lld/test/ELF/ppc64-toc-call-to-pcrel.s --- a/lld/test/ELF/ppc64-toc-call-to-pcrel.s +++ b/lld/test/ELF/ppc64-toc-call-to-pcrel.s @@ -29,23 +29,22 @@ # SYMBOL: 10020020 0 NOTYPE LOCAL DEFAULT [] 2 caller_14 # SYMBOL: 10020040 8 FUNC LOCAL DEFAULT 2 __toc_save_callee -# CHECK-LABEL: callee -# CHECK: blr +# CHECK: +# CHECK: blr -# CHECK-LABEL: caller -# CHECK: bl 0x10020040 -# CHECK-NEXT: ld 2, 24(1) -# CHECK-NEXT: blr +# CHECK: +# CHECK: bl 0x10020040 +# CHECK-NEXT: ld 2, 24(1) +# CHECK-NEXT: blr -# CHECK-LABEL: caller_14 -# CHECK: bfl 0, 0x10020040 -# CHECK-NEXT: ld 2, 24(1) -# CHECK-NEXT: blr - -# CHECK-LABEL: __toc_save_callee -# CHECK-NEXT: std 2, 24(1) -# CHECK-NEXT: b 0x10010000 +# CHECK: +# CHECK: bfl 0, 0x10020040 <__toc_save_callee> +# CHECK-NEXT: ld 2, 24(1) +# CHECK-NEXT: blr +# CHECK: <__toc_save_callee> +# CHECK-NEXT: std 2, 24(1) +# CHECK-NEXT: b 0x10010000 .section .text_callee, "ax", %progbits callee: diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -28,6 +28,7 @@ #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCRegisterInfo.h" @@ -368,6 +369,42 @@ return new PPCInstPrinter(MAI, MII, MRI, T); } +namespace { + +class PPCMCInstrAnalysis : public MCInstrAnalysis { +public: + explicit PPCMCInstrAnalysis(const MCInstrInfo *Info) + : MCInstrAnalysis(Info) {} + + bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + uint64_t &Target) const override { + int64_t Imm; + const MCInstrDesc &Desc = Info->get(Inst.getOpcode()); + if (isUnconditionalBranch(Inst) && Desc.getNumOperands() == 1 && + Inst.getOperand(0).isImm()) { + Imm = Inst.getOperand(0).getImm(); + } else if (isConditionalBranch(Inst)) { + if (Desc.getNumOperands() == 2 && Inst.getOperand(1).isImm()) + Imm = Inst.getOperand(1).getImm(); + else if (Desc.getNumOperands() == 3 && Inst.getOperand(2).isImm()) + Imm = Inst.getOperand(2).getImm(); + else + return false; + } else { + return false; + } + + Target = Addr + Imm * Size; + return true; + } +}; + +} // end anonymous namespace + +static MCInstrAnalysis *createPPCMCInstrAnalysis(const MCInstrInfo *Info) { + return new PPCMCInstrAnalysis(Info); +} + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetMC() { for (Target *T : {&getThePPC32Target(), &getThePPC32LETarget(), &getThePPC64Target(), &getThePPC64LETarget()}) { @@ -383,6 +420,9 @@ // Register the MC subtarget info. TargetRegistry::RegisterMCSubtargetInfo(*T, createPPCMCSubtargetInfo); + // Register the MC instruction analyzer. + TargetRegistry::RegisterMCInstrAnalysis(*T, createPPCMCInstrAnalysis); + // Register the MC Code Emitter TargetRegistry::RegisterMCCodeEmitter(*T, createPPCMCCodeEmitter); diff --git a/llvm/test/tools/llvm-objdump/ELF/PowerPC/elf-disassemble-symbolize-operands.yaml b/llvm/test/tools/llvm-objdump/ELF/PowerPC/elf-disassemble-symbolize-operands.yaml --- a/llvm/test/tools/llvm-objdump/ELF/PowerPC/elf-disassemble-symbolize-operands.yaml +++ b/llvm/test/tools/llvm-objdump/ELF/PowerPC/elf-disassemble-symbolize-operands.yaml @@ -0,0 +1,95 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-objdump %t -d --symbolize-operands --no-show-raw-insn --no-leading-addr | \ +# RUN: FileCheck %s + +## Expect to find the branch labels. +# CHECK: andi. 4, 4, 1 +# CHECK: li 4, 1 +# CHECK: b 0x28 +# CHECK: : +# CHECK: addi 4, 4, 1 +# CHECK: : +# CHECK: bclr 4, 1 +# CHECK: : +# CHECK: cmplw 1, 3, 4 +# CHECK: bf 4, 0x20 +# CHECK: dcbf 0, 3 +# CHECK: b 0x20 + +## This yaml was created from the following LLVM IR by: +## $ llc -mtriple=powerpc64le-unknown-linux-gnu 1.ll -filetype=obj -o a.elf +## $ obj2yaml a.elf +## ``` +## define void @break_cond_is_arg(i32 %arg, i1 %breakcond) { +## entry: +## br label %loop +## loop: +## %tmp23phi = phi i32 [ %tmp23, %endif ], [ 0, %entry ] +## %tmp23 = add nuw i32 %tmp23phi, 1 +## %tmp27 = icmp ult i32 %arg, %tmp23 +## br i1 %tmp27, label %then, label %endif +## then: ; preds = %bb +## tail call void @llvm.ppc.dcbf(i8* undef) +## br label %endif +## endif: ; preds = %bb28, %bb +## br i1 %breakcond, label %loop, label %loopexit +## loopexit: +## ret void +## } +## +## declare void @llvm.ppc.dcbf(i8*) +## ``` + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_PPC64 + Flags: [ ] + SectionHeaderStringTable: .strtab +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x20 + Content: 0100847001008038200000480000006000000060000000600000006000000060010084382000814C4020837CF4FF8440AC18007CECFFFF4B000000000000000000000000 + - Name: .note.GNU-stack + Type: SHT_PROGBITS + AddressAlign: 0x1 + - Name: .eh_frame + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + AddressAlign: 0x8 + Content: 1000000000000000017A5200047841011B0C01001000000018000000000000004400000000000000 + - Name: .rela.eh_frame + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .eh_frame + Relocations: + - Offset: 0x1C + Symbol: .text + Type: R_PPC64_REL32 + - Type: SectionHeaderTable + Sections: + - Name: .strtab + - Name: .text + - Name: .note.GNU-stack + - Name: .eh_frame + - Name: .rela.eh_frame + - Name: .symtab +Symbols: + - Name: 1.ll + Type: STT_FILE + Index: SHN_ABS + - Name: .text + Type: STT_SECTION + Section: .text + - Name: break_cond_is_arg + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Size: 0x44 +... diff --git a/llvm/test/tools/llvm-objdump/XCOFF/disassemble-symbolize-operands.yaml b/llvm/test/tools/llvm-objdump/XCOFF/disassemble-symbolize-operands.yaml --- a/llvm/test/tools/llvm-objdump/XCOFF/disassemble-symbolize-operands.yaml +++ b/llvm/test/tools/llvm-objdump/XCOFF/disassemble-symbolize-operands.yaml @@ -0,0 +1,110 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-objdump %t -d --symbolize-operands --no-show-raw-insn --no-leading-addr | \ +# RUN: FileCheck %s + +## Expect to find the branch labels. +# CHECK: b 0x14 +# CHECK: : +# CHECK: addi 4, 4, 1 +# CHECK: : +# CHECK: bclr 4, 1 +# CHECK: : +# CHECK: cmplw 1, 3, 4 +# CHECK: bf 4, 0xc +# CHECK: dcbf 0, 3 +# CHECK: b 0xc + +## This yaml was created from the following LLVM IR by: +## $ llc -mtriple=powerpc-ibm-aix-xcoff 1.ll -filetype=obj -o a.xcoff +## $ obj2yaml a.xcoff +## ``` +## define void @break_cond_is_arg(i32 %arg, i1 %breakcond) { +## entry: +## br label %loop +## loop: +## %tmp23phi = phi i32 [ %tmp23, %endif ], [ 0, %entry ] +## %tmp23 = add nuw i32 %tmp23phi, 1 +## %tmp27 = icmp ult i32 %arg, %tmp23 +## br i1 %tmp27, label %then, label %endif +## then: ; preds = %bb +## tail call void @llvm.ppc.dcbf(i8* undef) +## br label %endif +## endif: ; preds = %bb28, %bb +## br i1 %breakcond, label %loop, label %loopexit +## loopexit: +## ret void +## } +## +## declare void @llvm.ppc.dcbf(i8*) +## ``` + +--- !XCOFF +FileHeader: + MagicNumber: 0x1DF + NumberOfSections: 2 + CreationTime: 0 + OffsetToSymbolTable: 0xD0 + EntriesInSymbolTable: 9 + AuxiliaryHeaderSize: 0 + Flags: 0x0 +Sections: + - Name: .text + Address: 0x0 + Size: 0x4C + FileOffsetToData: 0x64 + FileOffsetToRelocations: 0x0 + FileOffsetToLineNumbers: 0x0 + NumberOfRelocations: 0x0 + NumberOfLineNumbers: 0x0 + Flags: [ STYP_TEXT ] + SectionData: 70840001388000014800000C388400014C8100207C8320404084FFF47C0018AC4BFFFFEC00000000000920408000020100000000000000240011627265616B5F636F6E645F69735F61726700 + - Name: .data + Address: 0x4C + Size: 0xC + FileOffsetToData: 0xB0 + FileOffsetToRelocations: 0xBC + FileOffsetToLineNumbers: 0x0 + NumberOfRelocations: 0x2 + NumberOfLineNumbers: 0x0 + Flags: [ STYP_DATA ] + SectionData: '000000000000005800000000' + Relocations: + - Address: 0x4C + Symbol: 0x3 + Info: 0x1F + Type: 0x0 + - Address: 0x50 + Symbol: 0x7 + Info: 0x1F + Type: 0x0 +Symbols: + - Name: .file + Value: 0x0 + Section: N_DEBUG + Type: 0x0 + StorageClass: C_FILE + NumberOfAuxEntries: 0 + - Name: .text + Value: 0x0 + Section: .text + Type: 0x0 + StorageClass: C_HIDEXT + NumberOfAuxEntries: 1 + - Name: .break_cond_is_arg + Value: 0x0 + Section: .text + Type: 0x0 + StorageClass: C_EXT + NumberOfAuxEntries: 1 + - Name: break_cond_is_arg + Value: 0x4C + Section: .data + Type: 0x0 + StorageClass: C_EXT + NumberOfAuxEntries: 1 + - Name: TOC + Value: 0x58 + Section: .data + Type: 0x0 + StorageClass: C_HIDEXT + NumberOfAuxEntries: 1 diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -978,8 +978,8 @@ const MCSubtargetInfo *STI, uint64_t SectionAddr, uint64_t Start, uint64_t End, std::unordered_map &Labels) { - // So far only supports X86. - if (!STI->getTargetTriple().isX86()) + // So far only supports X86 and PowerPC. + if (!STI->getTargetTriple().isX86() && !STI->getTargetTriple().isPPC()) return; Labels.clear();