[llvm] e83e53b - [AMDGPU][MC] Allow UC_VERSION_* constant reuse (#96461)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Jul 7 01:39:07 PDT 2024
Author: Carl Ritson
Date: 2024-07-07T17:39:03+09:00
New Revision: e83e53b7027149a61a6d4d27ddf66614d8d24129
URL: https://github.com/llvm/llvm-project/commit/e83e53b7027149a61a6d4d27ddf66614d8d24129
DIFF: https://github.com/llvm/llvm-project/commit/e83e53b7027149a61a6d4d27ddf66614d8d24129.diff
LOG: [AMDGPU][MC] Allow UC_VERSION_* constant reuse (#96461)
If more than one disassembler is created for a context then allow reuse
of existing constants.
Warn if constants values do not match.
Added:
llvm/unittests/MC/AMDGPU/Disassembler.cpp
Modified:
llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
llvm/unittests/MC/AMDGPU/CMakeLists.txt
Removed:
################################################################################
diff --git a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
index 0c0e9163fc6ef..695b2f246a778 100644
--- a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
+++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
@@ -2366,8 +2366,16 @@ const MCExpr *AMDGPUDisassembler::createConstantSymbolExpr(StringRef Id,
int64_t Val) {
MCContext &Ctx = getContext();
MCSymbol *Sym = Ctx.getOrCreateSymbol(Id);
- assert(!Sym->isVariable());
- Sym->setVariableValue(MCConstantExpr::create(Val, Ctx));
+ // Note: only set value to Val on a new symbol in case an dissassembler
+ // has already been initialized in this context.
+ if (!Sym->isVariable()) {
+ Sym->setVariableValue(MCConstantExpr::create(Val, Ctx));
+ } else {
+ int64_t Res = ~Val;
+ bool Valid = Sym->getVariableValue()->evaluateAsAbsolute(Res);
+ if (!Valid || Res != Val)
+ Ctx.reportWarning(SMLoc(), "unsupported redefinition of " + Id);
+ }
return MCSymbolRefExpr::create(Sym, Ctx);
}
diff --git a/llvm/unittests/MC/AMDGPU/CMakeLists.txt b/llvm/unittests/MC/AMDGPU/CMakeLists.txt
index 0a399772e019e..029f814a7d510 100644
--- a/llvm/unittests/MC/AMDGPU/CMakeLists.txt
+++ b/llvm/unittests/MC/AMDGPU/CMakeLists.txt
@@ -6,12 +6,15 @@ include_directories(
set(LLVM_LINK_COMPONENTS
AMDGPUCodeGen
AMDGPUDesc
+ AMDGPUDisassembler
AMDGPUInfo
MC
+ MCDisassembler
Support
TargetParser
)
add_llvm_unittest(AMDGPUMCTests
+ Disassembler.cpp
DwarfRegMappings.cpp
)
diff --git a/llvm/unittests/MC/AMDGPU/Disassembler.cpp b/llvm/unittests/MC/AMDGPU/Disassembler.cpp
new file mode 100644
index 0000000000000..3f841f87c4ea0
--- /dev/null
+++ b/llvm/unittests/MC/AMDGPU/Disassembler.cpp
@@ -0,0 +1,207 @@
+//===- llvm/unittest/unittests/MC/AMDGPU/Disassembler.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 "llvm-c/Disassembler.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDisassembler/MCDisassembler.h"
+#include "llvm/MC/MCDisassembler/MCSymbolizer.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+static const char *symbolLookupCallback(void *DisInfo, uint64_t ReferenceValue,
+ uint64_t *ReferenceType,
+ uint64_t ReferencePC,
+ const char **ReferenceName) {
+ *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
+ return nullptr;
+}
+
+static const char *TripleName = "amdgcn--amdpal";
+static const char *CPUName = "gfx1030";
+
+// Basic smoke test.
+TEST(AMDGPUDisassembler, Basic) {
+ LLVMInitializeAMDGPUTargetInfo();
+ LLVMInitializeAMDGPUTargetMC();
+ LLVMInitializeAMDGPUDisassembler();
+
+ uint8_t Bytes[] = {0x04, 0x00, 0x80, 0xb0};
+ uint8_t *BytesP = Bytes;
+ const char OutStringSize = 100;
+ char OutString[OutStringSize];
+ LLVMDisasmContextRef DCR = LLVMCreateDisasmCPU(
+ TripleName, CPUName, nullptr, 0, nullptr, symbolLookupCallback);
+
+ // Skip test if AMDGPU not built.
+ if (!DCR)
+ GTEST_SKIP();
+
+ size_t InstSize;
+ unsigned NumBytes = sizeof(Bytes);
+ unsigned PC = 0U;
+
+ InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString,
+ OutStringSize);
+ EXPECT_EQ(InstSize, 4U);
+ EXPECT_EQ(StringRef(OutString), "\ts_version UC_VERSION_GFX10");
+
+ LLVMDisasmDispose(DCR);
+}
+
+// Check multiple disassemblers in same MCContext.
+TEST(AMDGPUDisassembler, MultiDisassembler) {
+ LLVMInitializeAMDGPUTargetInfo();
+ LLVMInitializeAMDGPUTargetMC();
+ LLVMInitializeAMDGPUDisassembler();
+
+ std::string Error;
+ const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
+
+ // Skip test if AMDGPU not built.
+ if (!TheTarget)
+ GTEST_SKIP();
+
+ std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
+ std::unique_ptr<MCAsmInfo> MAI(
+ TheTarget->createMCAsmInfo(*MRI, TripleName, MCTargetOptions()));
+ std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
+ std::unique_ptr<MCSubtargetInfo> STI(
+ TheTarget->createMCSubtargetInfo(TripleName, CPUName, ""));
+ auto Ctx = std::make_unique<MCContext>(Triple(TripleName), MAI.get(),
+ MRI.get(), STI.get());
+
+ int AsmPrinterVariant = MAI->getAssemblerDialect();
+ std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
+ Triple(TripleName), AsmPrinterVariant, *MAI, *MII, *MRI));
+
+ SmallVector<char, 64> InsnStr, AnnoStr;
+ raw_svector_ostream OS(InsnStr);
+ raw_svector_ostream Annotations(AnnoStr);
+ formatted_raw_ostream FormattedOS(OS);
+
+ char StrBuffer[128];
+
+ uint8_t Bytes[] = {0x04, 0x00, 0x80, 0xb0};
+ size_t InstSize = 0U;
+ MCInst Inst1, Inst2;
+ MCDisassembler::DecodeStatus Status;
+
+ // Test disassembler works as expected.
+ AnnoStr.clear();
+ InsnStr.clear();
+ std::unique_ptr<MCDisassembler> DisAsm1(
+ TheTarget->createMCDisassembler(*STI, *Ctx));
+ Status = DisAsm1->getInstruction(Inst1, InstSize, Bytes, 0, Annotations);
+ ASSERT_TRUE(Status == MCDisassembler::Success);
+ EXPECT_EQ(InstSize, 4U);
+
+ IP->printInst(&Inst1, 0U, Annotations.str(), *STI, FormattedOS);
+ ASSERT_TRUE(InsnStr.size() < (sizeof(StrBuffer) - 1));
+ std::memcpy(StrBuffer, InsnStr.data(), InsnStr.size());
+ StrBuffer[InsnStr.size()] = '\0';
+ EXPECT_EQ(StringRef(StrBuffer), "\ts_version UC_VERSION_GFX10");
+
+ // Test that second disassembler in same context works as expected.
+ AnnoStr.clear();
+ InsnStr.clear();
+ std::unique_ptr<MCDisassembler> DisAsm2(
+ TheTarget->createMCDisassembler(*STI, *Ctx));
+ Status = DisAsm2->getInstruction(Inst2, InstSize, Bytes, 0, Annotations);
+ ASSERT_TRUE(Status == MCDisassembler::Success);
+ EXPECT_EQ(InstSize, 4U);
+
+ IP->printInst(&Inst2, 0U, Annotations.str(), *STI, FormattedOS);
+ ASSERT_TRUE(InsnStr.size() < (sizeof(StrBuffer) - 1));
+ std::memcpy(StrBuffer, InsnStr.data(), InsnStr.size());
+ StrBuffer[InsnStr.size()] = '\0';
+ EXPECT_EQ(StringRef(StrBuffer), "\ts_version UC_VERSION_GFX10");
+}
+
+// Test UC_VERSION symbols can be overriden without crashing.
+// There is no valid behaviour if symbols are redefined in this way.
+TEST(AMDGPUDisassembler, UCVersionOverride) {
+ LLVMInitializeAMDGPUTargetInfo();
+ LLVMInitializeAMDGPUTargetMC();
+ LLVMInitializeAMDGPUDisassembler();
+
+ std::string Error;
+ const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
+
+ // Skip test if AMDGPU not built.
+ if (!TheTarget)
+ GTEST_SKIP();
+
+ std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
+ std::unique_ptr<MCAsmInfo> MAI(
+ TheTarget->createMCAsmInfo(*MRI, TripleName, MCTargetOptions()));
+ std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
+ std::unique_ptr<MCSubtargetInfo> STI(
+ TheTarget->createMCSubtargetInfo(TripleName, CPUName, ""));
+ auto Ctx = std::make_unique<MCContext>(Triple(TripleName), MAI.get(),
+ MRI.get(), STI.get());
+
+ // Define custom UC_VERSION before initializing disassembler.
+ const uint8_t UC_VERSION_GFX10_DEFAULT = 0x04;
+ const uint8_t UC_VERSION_GFX10_NEW = 0x99;
+ auto Sym = Ctx->getOrCreateSymbol("UC_VERSION_GFX10");
+ Sym->setVariableValue(MCConstantExpr::create(UC_VERSION_GFX10_NEW, *Ctx));
+
+ int AsmPrinterVariant = MAI->getAssemblerDialect();
+ std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
+ Triple(TripleName), AsmPrinterVariant, *MAI, *MII, *MRI));
+
+ testing::internal::CaptureStderr();
+ std::unique_ptr<MCDisassembler> DisAsm(
+ TheTarget->createMCDisassembler(*STI, *Ctx));
+ std::string Output = testing::internal::GetCapturedStderr();
+ EXPECT_TRUE(Output.find("<unknown>:0: warning: unsupported redefinition of "
+ "UC_VERSION_GFX10") != std::string::npos);
+
+ SmallVector<char, 64> InsnStr, AnnoStr;
+ raw_svector_ostream OS(InsnStr);
+ raw_svector_ostream Annotations(AnnoStr);
+ formatted_raw_ostream FormattedOS(OS);
+
+ char StrBuffer[128];
+
+ // Decode S_VERSION instruction with original or custom version.
+ uint8_t Versions[] = {UC_VERSION_GFX10_DEFAULT, UC_VERSION_GFX10_NEW};
+ for (uint8_t Version : Versions) {
+ uint8_t Bytes[] = {Version, 0x00, 0x80, 0xb0};
+ size_t InstSize = 0U;
+ MCInst Inst;
+
+ AnnoStr.clear();
+ InsnStr.clear();
+ MCDisassembler::DecodeStatus Status =
+ DisAsm->getInstruction(Inst, InstSize, Bytes, 0, Annotations);
+ ASSERT_TRUE(Status == MCDisassembler::Success);
+ EXPECT_EQ(InstSize, 4U);
+
+ IP->printInst(&Inst, 0, Annotations.str(), *STI, FormattedOS);
+ ASSERT_TRUE(InsnStr.size() < (sizeof(StrBuffer) - 1));
+ std::memcpy(StrBuffer, InsnStr.data(), InsnStr.size());
+ StrBuffer[InsnStr.size()] = '\0';
+
+ if (Version == UC_VERSION_GFX10_DEFAULT)
+ EXPECT_EQ(StringRef(StrBuffer), "\ts_version UC_VERSION_GFX10");
+ else
+ EXPECT_EQ(StringRef(StrBuffer), "\ts_version 153");
+ }
+}
More information about the llvm-commits
mailing list