Skip to content

[feature][riscv] handle target address calculation in llvm-objdump disassembly for riscv #144620

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cross-project-tests/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell)

# suffixes: A list of file extensions to treat as test files.
config.suffixes = [".c", ".cl", ".cpp", ".m"]
config.suffixes = [".c", ".cl", ".cpp", ".m", ".s"]

# excludes: A list of directories to exclude from the testsuite. The 'Inputs'
# subdirectories contain auxiliary inputs for various tests in their parent
Expand Down
13 changes: 10 additions & 3 deletions llvm/include/llvm/MC/MCInstrAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/Compiler.h"
#include <cstdint>
#include <vector>
Expand Down Expand Up @@ -178,9 +179,15 @@ class LLVM_ABI MCInstrAnalysis {

/// Given a branch instruction try to get the address the branch
/// targets. Return true on success, and the address in Target.
virtual bool
evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const;
virtual bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target,
const MCSubtargetInfo *STI = nullptr) const;

/// Given an instruction that accesses a memory address, try to compute
/// the target address. Return true on success, and the address in \p Target.
virtual bool evaluateInstruction(const MCInst &Inst, uint64_t Addr,
uint64_t Size, uint64_t &Target,
const MCSubtargetInfo &STI) const;

/// Given an instruction tries to get the address of a memory operand. Returns
/// the address on success.
Expand Down
12 changes: 9 additions & 3 deletions llvm/lib/MC/MCInstrAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,15 @@ bool MCInstrAnalysis::clearsSuperRegisters(const MCRegisterInfo &MRI,
return false;
}

bool MCInstrAnalysis::evaluateBranch(const MCInst & /*Inst*/, uint64_t /*Addr*/,
uint64_t /*Size*/,
uint64_t & /*Target*/) const {
bool MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr,
uint64_t Size, uint64_t &Target,
const MCSubtargetInfo *STI) const {
return false;
}

bool MCInstrAnalysis::evaluateInstruction(const MCInst &Inst, uint64_t Addr,
uint64_t Size, uint64_t &Target,
const MCSubtargetInfo &STI) const {
return false;
}

Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,8 @@ class AArch64MCInstrAnalysis : public MCInstrAnalysis {
AArch64MCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}

bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
uint64_t &Target,
const MCSubtargetInfo *STI) const override {
// Search for a PC-relative argument.
// This will handle instructions like bcc (where the first argument is the
// condition code) and cbz (where it is a register).
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ class AMDGPUMCInstrAnalysis : public MCInstrAnalysis {
: MCInstrAnalysis(Info) {}

bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
uint64_t &Target,
const MCSubtargetInfo *STI) const override {
if (Inst.getNumOperands() == 0 || !Inst.getOperand(0).isImm() ||
Info->get(Inst.getOpcode()).operands()[0].OperandType !=
MCOI::OPERAND_PCREL)
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,8 @@ class ARMMCInstrAnalysis : public MCInstrAnalysis {
}

bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
uint64_t &Target,
const MCSubtargetInfo *STI) const override {
const MCInstrDesc &Desc = Info->get(Inst.getOpcode());

// Find the PC-relative immediate operand in the instruction.
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ class BPFMCInstrAnalysis : public MCInstrAnalysis {
: MCInstrAnalysis(Info) {}

bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
uint64_t &Target,
const MCSubtargetInfo *STI) const override {
// The target is the 3rd operand of cond inst and the 1st of uncond inst.
int32_t Imm;
if (isConditionalBranch(Inst)) {
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ class CSKYMCInstrAnalysis : public MCInstrAnalysis {
: MCInstrAnalysis(Info) {}

bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
uint64_t &Target,
const MCSubtargetInfo *STI) const override {
if (isConditionalBranch(Inst) || isUnconditionalBranch(Inst)) {
int64_t Imm;
Imm = Inst.getOperand(Inst.getNumOperands() - 1).getImm();
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,8 +716,9 @@ class HexagonMCInstrAnalysis : public MCInstrAnalysis {
return MCInstrAnalysis::isConditionalBranch(Inst);
}

bool evaluateBranch(MCInst const &Inst, uint64_t Addr,
uint64_t Size, uint64_t &Target) const override {
bool evaluateBranch(MCInst const &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target,
const MCSubtargetInfo *STI) const override {
if (!(isCall(Inst) || isUnconditionalBranch(Inst) ||
isConditionalBranch(Inst)))
return false;
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/Lanai/MCTargetDesc/LanaiMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ class LanaiMCInstrAnalysis : public MCInstrAnalysis {
: MCInstrAnalysis(Info) {}

bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
uint64_t &Target,
const MCSubtargetInfo *STI) const override {
if (Inst.getNumOperands() == 0)
return false;
if (!isConditionalBranch(Inst) && !isUnconditionalBranch(Inst) &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ class LoongArchMCInstrAnalysis : public MCInstrAnalysis {
: MCInstrAnalysis(Info) {}

bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
uint64_t &Target,
const MCSubtargetInfo *STI) const override {
unsigned NumOps = Inst.getNumOperands();
if ((isBranch(Inst) && !isIndirectBranch(Inst)) ||
Inst.getOpcode() == LoongArch::BL) {
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ class MipsMCInstrAnalysis : public MCInstrAnalysis {
MipsMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}

bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
uint64_t &Target,
const MCSubtargetInfo *STI) const override {
unsigned NumOps = Inst.getNumOperands();
if (NumOps == 0)
return false;
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,8 @@ class PPCMCInstrAnalysis : public MCInstrAnalysis {
: MCInstrAnalysis(Info) {}

bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
uint64_t &Target,
const MCSubtargetInfo *STI) const override {
unsigned NumOps = Inst.getNumOperands();
if (NumOps == 0 ||
Info->get(Inst.getOpcode()).operands()[NumOps - 1].OperandType !=
Expand Down
104 changes: 96 additions & 8 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <bitset>
#include <cstdint>

#define GET_INSTRINFO_MC_DESC
#define ENABLE_INSTR_PREDICATE_VERIFIER
Expand Down Expand Up @@ -182,6 +184,17 @@ class RISCVMCInstrAnalysis : public MCInstrAnalysis {
}

switch (Inst.getOpcode()) {
case RISCV::C_LUI:
case RISCV::LUI: {
setGPRState(Inst.getOperand(0).getReg(),
SignExtend64<32>(Inst.getOperand(1).getImm() << 12));
break;
}
case RISCV::AUIPC: {
setGPRState(Inst.getOperand(0).getReg(),
Addr + SignExtend64<32>(Inst.getOperand(1).getImm() << 12));
break;
}
default: {
// Clear the state of all defined registers for instructions that we don't
// explicitly support.
Expand All @@ -193,15 +206,12 @@ class RISCVMCInstrAnalysis : public MCInstrAnalysis {
}
break;
}
case RISCV::AUIPC:
setGPRState(Inst.getOperand(0).getReg(),
Addr + SignExtend64<32>(Inst.getOperand(1).getImm() << 12));
break;
}
}

bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override {
uint64_t &Target,
const MCSubtargetInfo *STI) const override {
if (isConditionalBranch(Inst)) {
int64_t Imm;
if (Size == 2)
Expand All @@ -213,6 +223,8 @@ class RISCVMCInstrAnalysis : public MCInstrAnalysis {
}

switch (Inst.getOpcode()) {
default:
return false;
case RISCV::C_J:
case RISCV::C_JAL:
case RISCV::QC_E_J:
Expand All @@ -229,8 +241,85 @@ class RISCVMCInstrAnalysis : public MCInstrAnalysis {
}
return false;
}
case RISCV::C_ADDI:
case RISCV::ADDI: {
if (!STI)
return false;
unsigned int ArchRegWidth =
STI->getTargetTriple().getArchPointerBitWidth();
MCRegister Reg = Inst.getOperand(1).getReg();
auto TargetRegState = getGPRState(Reg);
if (TargetRegState && Reg != RISCV::X0) {
Target = *TargetRegState + Inst.getOperand(2).getImm();
Target &= maskTrailingOnes<uint64_t>(ArchRegWidth);
return true;
}
break;
}
case RISCV::C_ADDIW:
case RISCV::ADDIW: {
MCRegister Reg = Inst.getOperand(1).getReg();
auto TargetRegState = getGPRState(Reg);
if (TargetRegState && Reg != RISCV::X0) {
Target = *TargetRegState + Inst.getOperand(2).getImm();
Target = SignExtend64<32>(Target);
return true;
}
break;
}
case RISCV::LB:
case RISCV::LH:
case RISCV::LD:
case RISCV::LW:
case RISCV::LBU:
case RISCV::LHU:
case RISCV::LWU:
case RISCV::SB:
case RISCV::SH:
case RISCV::SW:
case RISCV::SD:
case RISCV::FLH:
case RISCV::FLW:
case RISCV::FLD:
case RISCV::FSH:
case RISCV::FSW:
case RISCV::FSD:
case RISCV::C_LD:
case RISCV::C_SD:
case RISCV::C_FLD:
case RISCV::C_FSD:
case RISCV::C_SW:
case RISCV::C_LW:
case RISCV::C_FSW:
case RISCV::C_FLW:
case RISCV::C_LBU:
case RISCV::C_LH:
case RISCV::C_LHU:
case RISCV::C_SB:
case RISCV::C_SH:
case RISCV::C_LWSP:
case RISCV::C_SWSP:
case RISCV::C_LDSP:
case RISCV::C_SDSP:
case RISCV::C_FLWSP:
case RISCV::C_FSWSP:
case RISCV::C_FLDSP:
case RISCV::C_FSDSP:
case RISCV::C_LD_RV32:
case RISCV::C_SD_RV32:
case RISCV::C_SDSP_RV32:
case RISCV::LD_RV32:
case RISCV::C_LDSP_RV32:
case RISCV::SD_RV32: {
MCRegister Reg = Inst.getOperand(1).getReg();
auto TargetRegState = getGPRState(Reg);
if (TargetRegState) {
Target = *TargetRegState + Inst.getOperand(2).getImm();
return true;
}
break;
}
}

return false;
}

Expand Down Expand Up @@ -344,12 +433,11 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMC() {
TargetRegistry::RegisterELFStreamer(*T, createRISCVELFStreamer);
TargetRegistry::RegisterObjectTargetStreamer(
*T, createRISCVObjectTargetStreamer);
TargetRegistry::RegisterMCInstrAnalysis(*T, createRISCVInstrAnalysis);

// Register the asm target streamer.
TargetRegistry::RegisterAsmTargetStreamer(*T, createRISCVAsmTargetStreamer);
// Register the null target streamer.
TargetRegistry::RegisterNullTargetStreamer(*T,
createRISCVNullTargetStreamer);
TargetRegistry::RegisterMCInstrAnalysis(*T, createRISCVInstrAnalysis);
}
}
8 changes: 5 additions & 3 deletions llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,8 @@ class X86MCInstrAnalysis : public MCInstrAnalysis {
const MCSubtargetInfo &STI) const override;

bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
uint64_t &Target) const override;
uint64_t &Target,
const MCSubtargetInfo *STI) const override;
std::optional<uint64_t>
evaluateMemoryOperandAddress(const MCInst &Inst, const MCSubtargetInfo *STI,
uint64_t Addr, uint64_t Size) const override;
Expand Down Expand Up @@ -640,8 +641,9 @@ X86MCInstrAnalysis::findPltEntries(uint64_t PltSectionVA,
}
}

bool X86MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr,
uint64_t Size, uint64_t &Target) const {
bool X86MCInstrAnalysis::evaluateBranch(
const MCInst &Inst, uint64_t Addr, uint64_t Size, uint64_t &Target,
const MCSubtargetInfo *STI = nullptr) const {
if (Inst.getNumOperands() == 0 ||
Info->get(Inst.getOpcode()).operands()[0].OperandType !=
MCOI::OPERAND_PCREL)
Expand Down
2 changes: 2 additions & 0 deletions llvm/test/tools/llvm-objdump/RISCV/lit.local.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
if "RISCV" not in config.targets_to_build:
config.unsupported = True
32 changes: 32 additions & 0 deletions llvm/test/tools/llvm-objdump/RISCV/riscv32-ar-coverage.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# RUN: llvm-mc -riscv-add-build-attributes -triple=riscv32 -filetype=obj -mattr=+zclsd,+zilsd %s -o %t
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does "ar-coverage" mean in these test file names?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Explanation for ar: short for address resolution
  • Explanation for coverage: mostly pulls from code coverage. Many of the instructions do the same thing during address resolution. So instead of redundantly testing each and every one of them, I picked a few of them from different extensions and those the behaved differently under different circumstances (rv32 vs 64) to make sure that the various extensions are supported properly and address resolution works under different circumstances like long jumps of the target address and unrelated instructions in between pairs of instructions.

# RUN: llvm-objdump -d %t | FileCheck %s

# CHECK: 00000000 <_start>:
# CHECK-NEXT 0: 00000517 auipc a0, 0x0
# CHECK-NEXT 4: 0559 addi a0, a0, 0x16 <target>
# CHECK-NEXT 6: 00000517 auipc a0, 0x0
# CHECK-NEXT a: 6910 ld a2, 0x10(a0) <target>
# CHECK-NEXT c: 00000517 auipc a0, 0x0
# CHECK-NEXT 10: 00c53523 sd a2, 0xa(a0) <target>
# CHECK-NEXT 14: 0000 unimp

## The structure of this test file is similar to that of riscv64-ar-coverage
## with the major difference being that these tests are focused on instructions
## for 32 bit architecture.

.global _start
.text
_start:
auipc a0, 0x0
addi a0, a0, 0x16 ## addi -- behavior changes with different architectures.

## Test Zclsd and Zilsd instructions respectively
auipc a0, 0x0
c.ld a2, 0x10(a0)

auipc a0, 0x0
sd a2, 0xa(a0)

.skip 0x2
target:
ret:
Loading