brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · b5adf69 Raw
209 lines · cpp
1//===- llvm/unittest/unittests/MC/AMDGPU/Disassembler.cpp -----------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm-c/Disassembler.h"10#include "llvm/MC/MCAsmInfo.h"11#include "llvm/MC/MCContext.h"12#include "llvm/MC/MCDisassembler/MCDisassembler.h"13#include "llvm/MC/MCDisassembler/MCSymbolizer.h"14#include "llvm/MC/MCInst.h"15#include "llvm/MC/MCInstPrinter.h"16#include "llvm/MC/MCInstrInfo.h"17#include "llvm/MC/MCRegisterInfo.h"18#include "llvm/MC/MCSubtargetInfo.h"19#include "llvm/MC/MCSymbol.h"20#include "llvm/MC/MCTargetOptions.h"21#include "llvm/MC/TargetRegistry.h"22#include "llvm/Support/TargetSelect.h"23#include "gtest/gtest.h"24 25using namespace llvm;26 27static const char *symbolLookupCallback(void *DisInfo, uint64_t ReferenceValue,28                                        uint64_t *ReferenceType,29                                        uint64_t ReferencePC,30                                        const char **ReferenceName) {31  *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;32  return nullptr;33}34 35static constexpr char TripleName[] = "amdgcn--amdpal";36static constexpr char CPUName[] = "gfx1030";37 38// Basic smoke test.39TEST(AMDGPUDisassembler, Basic) {40  LLVMInitializeAMDGPUTargetInfo();41  LLVMInitializeAMDGPUTargetMC();42  LLVMInitializeAMDGPUDisassembler();43 44  uint8_t Bytes[] = {0x04, 0x00, 0x80, 0xb0};45  uint8_t *BytesP = Bytes;46  const char OutStringSize = 100;47  char OutString[OutStringSize];48  LLVMDisasmContextRef DCR = LLVMCreateDisasmCPU(49      TripleName, CPUName, nullptr, 0, nullptr, symbolLookupCallback);50 51  // Skip test if AMDGPU not built.52  if (!DCR)53    GTEST_SKIP();54 55  size_t InstSize;56  unsigned NumBytes = sizeof(Bytes);57  unsigned PC = 0U;58 59  InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString,60                                   OutStringSize);61  EXPECT_EQ(InstSize, 4U);62  EXPECT_EQ(StringRef(OutString), "\ts_version UC_VERSION_GFX10");63 64  LLVMDisasmDispose(DCR);65}66 67// Check multiple disassemblers in same MCContext.68TEST(AMDGPUDisassembler, MultiDisassembler) {69  LLVMInitializeAMDGPUTargetInfo();70  LLVMInitializeAMDGPUTargetMC();71  LLVMInitializeAMDGPUDisassembler();72 73  std::string Error;74  Triple TT(TripleName);75  const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);76 77  // Skip test if AMDGPU not built.78  if (!TheTarget)79    GTEST_SKIP();80 81  std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));82  std::unique_ptr<MCAsmInfo> MAI(83      TheTarget->createMCAsmInfo(*MRI, TT, MCTargetOptions()));84  std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());85  std::unique_ptr<MCSubtargetInfo> STI(86      TheTarget->createMCSubtargetInfo(TT, CPUName, ""));87  auto Ctx = std::make_unique<MCContext>(TT, MAI.get(), MRI.get(), STI.get());88 89  int AsmPrinterVariant = MAI->getAssemblerDialect();90  std::unique_ptr<MCInstPrinter> IP(91      TheTarget->createMCInstPrinter(TT, AsmPrinterVariant, *MAI, *MII, *MRI));92 93  SmallVector<char, 64> InsnStr, AnnoStr;94  raw_svector_ostream OS(InsnStr);95  raw_svector_ostream Annotations(AnnoStr);96  formatted_raw_ostream FormattedOS(OS);97 98  char StrBuffer[128];99 100  uint8_t Bytes[] = {0x04, 0x00, 0x80, 0xb0};101  uint64_t InstSize = 0U;102  MCInst Inst1, Inst2;103  MCDisassembler::DecodeStatus Status;104 105  // Test disassembler works as expected.106  AnnoStr.clear();107  InsnStr.clear();108  std::unique_ptr<MCDisassembler> DisAsm1(109      TheTarget->createMCDisassembler(*STI, *Ctx));110  Status = DisAsm1->getInstruction(Inst1, InstSize, Bytes, 0, Annotations);111  ASSERT_TRUE(Status == MCDisassembler::Success);112  EXPECT_EQ(InstSize, 4U);113 114  IP->printInst(&Inst1, 0U, Annotations.str(), *STI, FormattedOS);115  ASSERT_TRUE(InsnStr.size() < (sizeof(StrBuffer) - 1));116  std::memcpy(StrBuffer, InsnStr.data(), InsnStr.size());117  StrBuffer[InsnStr.size()] = '\0';118  EXPECT_EQ(StringRef(StrBuffer), "\ts_version UC_VERSION_GFX10");119 120  // Test that second disassembler in same context works as expected.121  AnnoStr.clear();122  InsnStr.clear();123  std::unique_ptr<MCDisassembler> DisAsm2(124      TheTarget->createMCDisassembler(*STI, *Ctx));125  Status = DisAsm2->getInstruction(Inst2, InstSize, Bytes, 0, Annotations);126  ASSERT_TRUE(Status == MCDisassembler::Success);127  EXPECT_EQ(InstSize, 4U);128 129  IP->printInst(&Inst2, 0U, Annotations.str(), *STI, FormattedOS);130  ASSERT_TRUE(InsnStr.size() < (sizeof(StrBuffer) - 1));131  std::memcpy(StrBuffer, InsnStr.data(), InsnStr.size());132  StrBuffer[InsnStr.size()] = '\0';133  EXPECT_EQ(StringRef(StrBuffer), "\ts_version UC_VERSION_GFX10");134}135 136// Test UC_VERSION symbols can be overriden without crashing.137// There is no valid behaviour if symbols are redefined in this way.138TEST(AMDGPUDisassembler, UCVersionOverride) {139  LLVMInitializeAMDGPUTargetInfo();140  LLVMInitializeAMDGPUTargetMC();141  LLVMInitializeAMDGPUDisassembler();142 143  Triple TT(TripleName);144 145  std::string Error;146  const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);147 148  // Skip test if AMDGPU not built.149  if (!TheTarget)150    GTEST_SKIP();151 152  std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));153  std::unique_ptr<MCAsmInfo> MAI(154      TheTarget->createMCAsmInfo(*MRI, TT, MCTargetOptions()));155  std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());156  std::unique_ptr<MCSubtargetInfo> STI(157      TheTarget->createMCSubtargetInfo(TT, CPUName, ""));158  auto Ctx = std::make_unique<MCContext>(TT, MAI.get(), MRI.get(), STI.get());159 160  // Define custom UC_VERSION before initializing disassembler.161  const uint8_t UC_VERSION_GFX10_DEFAULT = 0x04;162  const uint8_t UC_VERSION_GFX10_NEW = 0x99;163  auto Sym = Ctx->getOrCreateSymbol("UC_VERSION_GFX10");164  Sym->setVariableValue(MCConstantExpr::create(UC_VERSION_GFX10_NEW, *Ctx));165 166  int AsmPrinterVariant = MAI->getAssemblerDialect();167  std::unique_ptr<MCInstPrinter> IP(168      TheTarget->createMCInstPrinter(TT, AsmPrinterVariant, *MAI, *MII, *MRI));169 170  testing::internal::CaptureStderr();171  std::unique_ptr<MCDisassembler> DisAsm(172      TheTarget->createMCDisassembler(*STI, *Ctx));173  std::string Output = testing::internal::GetCapturedStderr();174  EXPECT_TRUE(Output.find("<unknown>:0: warning: unsupported redefinition of "175                          "UC_VERSION_GFX10") != std::string::npos);176 177  SmallVector<char, 64> InsnStr, AnnoStr;178  raw_svector_ostream OS(InsnStr);179  raw_svector_ostream Annotations(AnnoStr);180  formatted_raw_ostream FormattedOS(OS);181 182  char StrBuffer[128];183 184  // Decode S_VERSION instruction with original or custom version.185  uint8_t Versions[] = {UC_VERSION_GFX10_DEFAULT, UC_VERSION_GFX10_NEW};186  for (uint8_t Version : Versions) {187    uint8_t Bytes[] = {Version, 0x00, 0x80, 0xb0};188    uint64_t InstSize = 0U;189    MCInst Inst;190 191    AnnoStr.clear();192    InsnStr.clear();193    MCDisassembler::DecodeStatus Status =194        DisAsm->getInstruction(Inst, InstSize, Bytes, 0, Annotations);195    ASSERT_TRUE(Status == MCDisassembler::Success);196    EXPECT_EQ(InstSize, 4U);197 198    IP->printInst(&Inst, 0, Annotations.str(), *STI, FormattedOS);199    ASSERT_TRUE(InsnStr.size() < (sizeof(StrBuffer) - 1));200    std::memcpy(StrBuffer, InsnStr.data(), InsnStr.size());201    StrBuffer[InsnStr.size()] = '\0';202 203    if (Version == UC_VERSION_GFX10_DEFAULT)204      EXPECT_EQ(StringRef(StrBuffer), "\ts_version UC_VERSION_GFX10");205    else206      EXPECT_EQ(StringRef(StrBuffer), "\ts_version 153");207  }208}209