[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