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

Djordje Todorovic via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 24 06:20:29 PDT 2025


================
@@ -0,0 +1,139 @@
+//===- RISCVMCInstAnalysis.cpp - Unit tests for RISCV MCInstrAnalysis ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCSubTargetInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInstrAnalysis.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/MathExtras.h"
+#include "gtest/gtest.h"
+#include <cstdint>
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+struct TestContext {
+  const char *TripleName = "riscv32-unknown-elf";
+  std::unique_ptr<MCRegisterInfo> MRI;
+  std::unique_ptr<MCAsmInfo> MAI;
+  std::unique_ptr<MCInstrInfo> MII;
+  std::unique_ptr<MCInstrAnalysis> MIA;
+  std::unique_ptr<MCContext> Ctx;
+  std::unique_ptr<const MCSubtargetInfo> STI;
+
+  TestContext(const char *TripleName) {
+    llvm::InitializeAllTargetInfos();
+    llvm::InitializeAllTargetMCs();
+    llvm::InitializeAllDisassemblers();
+
+    std::string Error;
+    const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
+    if (!TheTarget)
+      return;
+
+    MRI.reset(TheTarget->createMCRegInfo(TripleName));
+    MII.reset(TheTarget->createMCInstrInfo());
+    MIA.reset(TheTarget->createMCInstrAnalysis(MII.get()));
+    MCTargetOptions MCOptions;
+    MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
+    Ctx = std::make_unique<MCContext>(Triple(TripleName), MAI.get(), MRI.get(), /*MSTI=*/nullptr);
+    const char *MCPU = "generic";
+    std::string Features = ""; // No extensions, just RV32I
+    STI.reset(TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features));
+  }
+
+  operator bool() { return Ctx.get() && MIA.get(); }
+  operator MCContext &() { return *Ctx; }
+  MCInstrAnalysis &getInstrAnalysis() { return *MIA; }
+};
+
+TestContext &getTestContext() {
+  static TestContext Ctx;
+  return Ctx;
+}
+
+} // end anonymous namespace
+
+// Helper to create an MCInst with register and immediate operands
+static MCInst makeInst(unsigned Opcode, std::initializer_list<MCOperand> Ops) {
+  MCInst Inst;
+  Inst.setOpcode(Opcode);
+  for (const auto &Op : Ops)
+    Inst.addOperand(Op);
+  return Inst;
+}
+
+TEST(RISCVMCInstrAnalysis, FindTargetAddressWithRegisterState) {
+  if (!getTestContext())
+    GTEST_SKIP();
+  auto &MIA = getTestContext().getInstrAnalysis();
+
+  // Set up variables.
+  uint64_t Addr = 0x2, Target;
+  uint32_t mask = ~(0); // All bits set to 1.
+  uint64_t lowerImm = 0xfff; // Lower 12 bits set to 1.
+  bool found;
+
+  // ------------ Test 1 --------------
+  // Verifies accuracy of the result when ADDI (and related instructions, see
+  // switch case in RISCVTargetDesc.cpp) is involved in an instruction sequence.
+  // ADDI only retains the bottom XLEN bits, making it dependent on the target.
+  // This masking is especially apparent in 32-bit targets as overflow must
+  // correctly be discarded
+  uint64_t upperImm1 = 0 | mask;
+  upperImm1 >>= 12; // Bottom 20 bits set to 1.
+
+  // 1. AUIPC x5, 0xFFFFF.
+  MCInst auipc = makeInst(/*AUIPC=*/23, {MCOperand::createReg(5), MCOperand::createImm(upperImm1)});
+  // 2. ADDI x5, x5, 0xFFF.
+  MCInst addi = makeInst(/*ADDI=*/13, {MCOperand::createReg(5), MCOperand::createReg(5), MCOperand::createImm(lowerImm)});
+
+  MIA.updateState(auipc, Addr);
+  found = MIA.findTargetAddress(addi, Addr, 4, Target, nullptr);
+  EXPECT_TRUE(found);
+
+  uint64_t expected1 = ((upperImm1 << 12) + lowerImm + Addr) & maskTrailingOnes<uint64_t>(32);
+  EXPECT_EQ(Target, expected1);
+  MIA.resetState();
+
+  // ------------------- Test 2 -----------------
+  // Verifies the correctness when ADDIW is involved in a sequence. ADDIW
+  // performs a sign extension up to 64 bits based on the 32nd bit after the
+  // result has been computed.
+  mask >>= 1; // Bottom 31 bits set to 1.
+
+  uint64_t upper_bits2 = 0 | mask;
+  upper_bits2 >>= 12; // Bottom 19 bits set to 1.
+
+  // 1. AUIPC x6, 0x7FFFF.
+  MCInst auipc2 = makeInst(/*AUIPC=*/23, {MCOperand::createReg(6), MCOperand::createImm(upper_bits2)});
+  // 2. ADDIW x6, x6, 0xFFF.
+  MCInst addiw = makeInst(/*ADDIW=*/15, {MCOperand::createReg(6), MCOperand::createReg(6), MCOperand::createImm(lowerImm)});
----------------
djtodoro wrote:

Please format whole file.

https://github.com/llvm/llvm-project/pull/144620


More information about the llvm-commits mailing list