CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
189 lines
7.3 KiB
C++
189 lines
7.3 KiB
C++
//===-- TestRiscvInstEmulation.cpp ----------------------------------------===//
|
|
//
|
|
// 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 "gtest/gtest.h"
|
|
|
|
#include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h"
|
|
|
|
#include "lldb/Core/AddressRange.h"
|
|
#include "lldb/Symbol/UnwindPlan.h"
|
|
#include "lldb/Utility/ArchSpec.h"
|
|
|
|
#include "Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h"
|
|
#include "Plugins/Instruction/RISCV/EmulateInstructionRISCV.h"
|
|
#include "Plugins/Process/Utility/lldb-riscv-register-enums.h"
|
|
#include "llvm/Support/TargetSelect.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
class TestRiscvInstEmulation : public testing::Test {
|
|
public:
|
|
static void SetUpTestCase();
|
|
static void TearDownTestCase();
|
|
|
|
protected:
|
|
};
|
|
|
|
void TestRiscvInstEmulation::SetUpTestCase() {
|
|
llvm::InitializeAllTargets();
|
|
llvm::InitializeAllAsmPrinters();
|
|
llvm::InitializeAllTargetMCs();
|
|
llvm::InitializeAllDisassemblers();
|
|
DisassemblerLLVMC::Initialize();
|
|
EmulateInstructionRISCV::Initialize();
|
|
}
|
|
|
|
void TestRiscvInstEmulation::TearDownTestCase() {
|
|
DisassemblerLLVMC::Terminate();
|
|
EmulateInstructionRISCV::Terminate();
|
|
}
|
|
|
|
TEST_F(TestRiscvInstEmulation, TestSimpleRiscvFunction) {
|
|
ArchSpec arch("riscv64-unknown-linux-gnu");
|
|
// Enable compressed instruction support (RVC extension).
|
|
arch.SetFlags(ArchSpec::eRISCV_rvc);
|
|
std::unique_ptr<UnwindAssemblyInstEmulation> engine(
|
|
static_cast<UnwindAssemblyInstEmulation *>(
|
|
UnwindAssemblyInstEmulation::CreateInstance(arch)));
|
|
ASSERT_NE(nullptr, engine);
|
|
|
|
// RISC-V function with compressed and uncompressed instructions
|
|
// 0x0000: 1141 addi sp, sp, -0x10
|
|
// 0x0002: e406 sd ra, 0x8(sp)
|
|
// 0x0004: e022 sd s0, 0x0(sp)
|
|
// 0x0006: 0800 addi s0, sp, 0x10
|
|
// 0x0008: 00000537 lui a0, 0x0
|
|
// 0x000C: 00050513 mv a0, a0
|
|
// 0x0010: 00000097 auipc ra, 0x0
|
|
// 0x0014: 000080e7 jalr ra <main+0x10>
|
|
// 0x0018: 4501 li a0, 0x0
|
|
// 0x001A: ff040113 addi sp, s0, -0x10
|
|
// 0x001E: 60a2 ld ra, 0x8(sp)
|
|
// 0x0020: 6402 ld s0, 0x0(sp)
|
|
// 0x0022: 0141 addi sp, sp, 0x10
|
|
// 0x0024: 8082 ret
|
|
uint8_t data[] = {// 0x0000: 1141 addi sp, sp, -0x10
|
|
0x41, 0x11,
|
|
// 0x0002: e406 sd ra, 0x8(sp)
|
|
0x06, 0xE4,
|
|
// 0x0004: e022 sd s0, 0x0(sp)
|
|
0x22, 0xE0,
|
|
// 0x0006: 0800 addi s0, sp, 0x10
|
|
0x00, 0x08,
|
|
// 0x0008: 00000537 lui a0, 0x0
|
|
0x37, 0x05, 0x00, 0x00,
|
|
// 0x000C: 00050513 mv a0, a0
|
|
0x13, 0x05, 0x05, 0x00,
|
|
// 0x0010: 00000097 auipc ra, 0x0
|
|
0x97, 0x00, 0x00, 0x00,
|
|
// 0x0014: 000080e7 jalr ra <main+0x10>
|
|
0xE7, 0x80, 0x00, 0x00,
|
|
// 0x0018: 4501 li a0, 0x0
|
|
0x01, 0x45,
|
|
// 0x001A: ff040113 addi sp, s0, -0x10
|
|
0x13, 0x01, 0x04, 0xFF,
|
|
// 0x001E: 60a2 ld ra, 0x8(sp)
|
|
0xA2, 0x60,
|
|
// 0x0020: 6402 ld s0, 0x0(sp)
|
|
0x02, 0x64,
|
|
// 0x0022: 0141 addi sp, sp, 0x10
|
|
0x41, 0x01,
|
|
// 0x0024: 8082 ret
|
|
0x82, 0x80};
|
|
|
|
// Expected UnwindPlan (prologue only - emulation stops after frame setup):
|
|
// row[0]: 0: CFA=sp+0 => fp= <same> ra= <same>
|
|
// row[1]: 2: CFA=sp+16 => fp= <same> ra= <same> (after stack
|
|
// allocation) row[2]: 4: CFA=sp+16 => fp= <same> ra=[CFA-8]
|
|
// (after saving ra) row[3]: 6: CFA=sp+16 => fp=[CFA-16] ra=[CFA-8]
|
|
// (after saving s0/fp) row[4]: 8: CFA=s0+0 => fp=[CFA-16] ra=[CFA-8]
|
|
// (after setting frame pointer: s0=sp+16)
|
|
|
|
const UnwindPlan::Row *row;
|
|
AddressRange sample_range;
|
|
UnwindPlan unwind_plan(eRegisterKindLLDB);
|
|
UnwindPlan::Row::AbstractRegisterLocation regloc;
|
|
sample_range = AddressRange(0x1000, sizeof(data));
|
|
|
|
EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
|
|
sample_range, data, sizeof(data), unwind_plan));
|
|
|
|
// CFA=sp+0 => fp=<same> ra=<same>.
|
|
row = unwind_plan.GetRowForFunctionOffset(0);
|
|
EXPECT_EQ(0, row->GetOffset());
|
|
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_riscv);
|
|
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
|
|
EXPECT_EQ(0, row->GetCFAValue().GetOffset());
|
|
|
|
EXPECT_TRUE(row->GetRegisterInfo(gpr_fp_riscv, regloc));
|
|
EXPECT_TRUE(regloc.IsSame());
|
|
|
|
EXPECT_TRUE(row->GetRegisterInfo(gpr_ra_riscv, regloc));
|
|
EXPECT_TRUE(regloc.IsSame());
|
|
|
|
// CFA=sp+16 => fp=<same> ra=<same>.
|
|
row = unwind_plan.GetRowForFunctionOffset(2);
|
|
EXPECT_EQ(2, row->GetOffset());
|
|
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_riscv);
|
|
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
|
|
EXPECT_EQ(16, row->GetCFAValue().GetOffset());
|
|
|
|
EXPECT_TRUE(row->GetRegisterInfo(gpr_fp_riscv, regloc));
|
|
EXPECT_TRUE(regloc.IsSame());
|
|
|
|
EXPECT_TRUE(row->GetRegisterInfo(gpr_ra_riscv, regloc));
|
|
EXPECT_TRUE(regloc.IsSame());
|
|
|
|
// CFA=sp+16 => fp=<same> ra=[CFA-8].
|
|
row = unwind_plan.GetRowForFunctionOffset(4);
|
|
EXPECT_EQ(4, row->GetOffset());
|
|
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_riscv);
|
|
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
|
|
EXPECT_EQ(16, row->GetCFAValue().GetOffset());
|
|
|
|
EXPECT_TRUE(row->GetRegisterInfo(gpr_fp_riscv, regloc));
|
|
EXPECT_TRUE(regloc.IsSame());
|
|
|
|
EXPECT_TRUE(row->GetRegisterInfo(gpr_ra_riscv, regloc));
|
|
EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
|
|
EXPECT_EQ(-8, regloc.GetOffset());
|
|
|
|
// CFA=sp+16 => fp=[CFA-16] ra=[CFA-8]
|
|
row = unwind_plan.GetRowForFunctionOffset(6);
|
|
EXPECT_EQ(6, row->GetOffset());
|
|
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_riscv);
|
|
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
|
|
EXPECT_EQ(16, row->GetCFAValue().GetOffset());
|
|
|
|
EXPECT_TRUE(row->GetRegisterInfo(gpr_fp_riscv, regloc));
|
|
EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
|
|
EXPECT_EQ(-16, regloc.GetOffset());
|
|
|
|
EXPECT_TRUE(row->GetRegisterInfo(gpr_ra_riscv, regloc));
|
|
EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
|
|
EXPECT_EQ(-8, regloc.GetOffset());
|
|
|
|
// CFA=s0+0 => fp=[CFA-16] ra=[CFA-8]
|
|
// s0 = sp + 16, so switching CFA to s0 does not change the effective
|
|
// locations.
|
|
row = unwind_plan.GetRowForFunctionOffset(8);
|
|
EXPECT_EQ(8, row->GetOffset());
|
|
EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_fp_riscv);
|
|
EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);
|
|
EXPECT_EQ(0, row->GetCFAValue().GetOffset());
|
|
|
|
EXPECT_TRUE(row->GetRegisterInfo(gpr_fp_riscv, regloc));
|
|
EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
|
|
EXPECT_EQ(-16, regloc.GetOffset());
|
|
|
|
EXPECT_TRUE(row->GetRegisterInfo(gpr_ra_riscv, regloc));
|
|
EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
|
|
EXPECT_EQ(-8, regloc.GetOffset());
|
|
}
|