Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / unittests / MC / AMDGPU / Disassembler.cpp
blob23413030136ab5c668a2f19dc5880e98188ae985
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-exception
6 //
7 //===----------------------------------------------------------------------===//
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"
25 using namespace llvm;
27 static 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;
35 static const char *TripleName = "amdgcn--amdpal";
36 static const char *CPUName = "gfx1030";
38 // Basic smoke test.
39 TEST(AMDGPUDisassembler, Basic) {
40 LLVMInitializeAMDGPUTargetInfo();
41 LLVMInitializeAMDGPUTargetMC();
42 LLVMInitializeAMDGPUDisassembler();
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);
51 // Skip test if AMDGPU not built.
52 if (!DCR)
53 GTEST_SKIP();
55 size_t InstSize;
56 unsigned NumBytes = sizeof(Bytes);
57 unsigned PC = 0U;
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");
64 LLVMDisasmDispose(DCR);
67 // Check multiple disassemblers in same MCContext.
68 TEST(AMDGPUDisassembler, MultiDisassembler) {
69 LLVMInitializeAMDGPUTargetInfo();
70 LLVMInitializeAMDGPUTargetMC();
71 LLVMInitializeAMDGPUDisassembler();
73 std::string Error;
74 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
76 // Skip test if AMDGPU not built.
77 if (!TheTarget)
78 GTEST_SKIP();
80 std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
81 std::unique_ptr<MCAsmInfo> MAI(
82 TheTarget->createMCAsmInfo(*MRI, TripleName, MCTargetOptions()));
83 std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
84 std::unique_ptr<MCSubtargetInfo> STI(
85 TheTarget->createMCSubtargetInfo(TripleName, CPUName, ""));
86 auto Ctx = std::make_unique<MCContext>(Triple(TripleName), MAI.get(),
87 MRI.get(), STI.get());
89 int AsmPrinterVariant = MAI->getAssemblerDialect();
90 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
91 Triple(TripleName), AsmPrinterVariant, *MAI, *MII, *MRI));
93 SmallVector<char, 64> InsnStr, AnnoStr;
94 raw_svector_ostream OS(InsnStr);
95 raw_svector_ostream Annotations(AnnoStr);
96 formatted_raw_ostream FormattedOS(OS);
98 char StrBuffer[128];
100 uint8_t Bytes[] = {0x04, 0x00, 0x80, 0xb0};
101 uint64_t InstSize = 0U;
102 MCInst Inst1, Inst2;
103 MCDisassembler::DecodeStatus Status;
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);
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");
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);
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");
136 // Test UC_VERSION symbols can be overriden without crashing.
137 // There is no valid behaviour if symbols are redefined in this way.
138 TEST(AMDGPUDisassembler, UCVersionOverride) {
139 LLVMInitializeAMDGPUTargetInfo();
140 LLVMInitializeAMDGPUTargetMC();
141 LLVMInitializeAMDGPUDisassembler();
143 std::string Error;
144 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
146 // Skip test if AMDGPU not built.
147 if (!TheTarget)
148 GTEST_SKIP();
150 std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
151 std::unique_ptr<MCAsmInfo> MAI(
152 TheTarget->createMCAsmInfo(*MRI, TripleName, MCTargetOptions()));
153 std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
154 std::unique_ptr<MCSubtargetInfo> STI(
155 TheTarget->createMCSubtargetInfo(TripleName, CPUName, ""));
156 auto Ctx = std::make_unique<MCContext>(Triple(TripleName), MAI.get(),
157 MRI.get(), STI.get());
159 // Define custom UC_VERSION before initializing disassembler.
160 const uint8_t UC_VERSION_GFX10_DEFAULT = 0x04;
161 const uint8_t UC_VERSION_GFX10_NEW = 0x99;
162 auto Sym = Ctx->getOrCreateSymbol("UC_VERSION_GFX10");
163 Sym->setVariableValue(MCConstantExpr::create(UC_VERSION_GFX10_NEW, *Ctx));
165 int AsmPrinterVariant = MAI->getAssemblerDialect();
166 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
167 Triple(TripleName), AsmPrinterVariant, *MAI, *MII, *MRI));
169 testing::internal::CaptureStderr();
170 std::unique_ptr<MCDisassembler> DisAsm(
171 TheTarget->createMCDisassembler(*STI, *Ctx));
172 std::string Output = testing::internal::GetCapturedStderr();
173 EXPECT_TRUE(Output.find("<unknown>:0: warning: unsupported redefinition of "
174 "UC_VERSION_GFX10") != std::string::npos);
176 SmallVector<char, 64> InsnStr, AnnoStr;
177 raw_svector_ostream OS(InsnStr);
178 raw_svector_ostream Annotations(AnnoStr);
179 formatted_raw_ostream FormattedOS(OS);
181 char StrBuffer[128];
183 // Decode S_VERSION instruction with original or custom version.
184 uint8_t Versions[] = {UC_VERSION_GFX10_DEFAULT, UC_VERSION_GFX10_NEW};
185 for (uint8_t Version : Versions) {
186 uint8_t Bytes[] = {Version, 0x00, 0x80, 0xb0};
187 uint64_t InstSize = 0U;
188 MCInst Inst;
190 AnnoStr.clear();
191 InsnStr.clear();
192 MCDisassembler::DecodeStatus Status =
193 DisAsm->getInstruction(Inst, InstSize, Bytes, 0, Annotations);
194 ASSERT_TRUE(Status == MCDisassembler::Success);
195 EXPECT_EQ(InstSize, 4U);
197 IP->printInst(&Inst, 0, Annotations.str(), *STI, FormattedOS);
198 ASSERT_TRUE(InsnStr.size() < (sizeof(StrBuffer) - 1));
199 std::memcpy(StrBuffer, InsnStr.data(), InsnStr.size());
200 StrBuffer[InsnStr.size()] = '\0';
202 if (Version == UC_VERSION_GFX10_DEFAULT)
203 EXPECT_EQ(StringRef(StrBuffer), "\ts_version UC_VERSION_GFX10");
204 else
205 EXPECT_EQ(StringRef(StrBuffer), "\ts_version 153");