Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / unittests / MC / X86 / X86MCDisassemblerTest.cpp
blob5ae10bb7ace7ab2045fe2d17699b877d3081de55
1 //===- X86MCDisassemblerTest.cpp - Tests for X86 MCDisassembler -----------===//
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/MC/MCAsmInfo.h"
10 #include "llvm/MC/MCContext.h"
11 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
12 #include "llvm/MC/MCDisassembler/MCSymbolizer.h"
13 #include "llvm/MC/MCInst.h"
14 #include "llvm/MC/MCRegisterInfo.h"
15 #include "llvm/MC/MCSubtargetInfo.h"
16 #include "llvm/MC/MCTargetOptions.h"
17 #include "llvm/MC/TargetRegistry.h"
18 #include "llvm/Support/TargetSelect.h"
19 #include "gtest/gtest.h"
21 using namespace llvm;
23 namespace {
25 struct Context {
26 const char *TripleName = "x86_64-unknown-elf";
27 std::unique_ptr<MCRegisterInfo> MRI;
28 std::unique_ptr<MCAsmInfo> MAI;
29 std::unique_ptr<MCContext> Ctx;
30 std::unique_ptr<MCSubtargetInfo> STI;
31 std::unique_ptr<MCDisassembler> DisAsm;
33 Context() {
34 LLVMInitializeX86TargetInfo();
35 LLVMInitializeX86TargetMC();
36 LLVMInitializeX86Disassembler();
38 // If we didn't build x86, do not run the test.
39 std::string Error;
40 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
41 if (!TheTarget)
42 return;
44 MRI.reset(TheTarget->createMCRegInfo(TripleName));
45 MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCTargetOptions()));
46 STI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
47 Ctx = std::make_unique<MCContext>(Triple(TripleName), MAI.get(), MRI.get(),
48 STI.get());
50 DisAsm.reset(TheTarget->createMCDisassembler(*STI, *Ctx));
53 operator MCContext &() { return *Ctx; };
56 Context &getContext() {
57 static Context Ctxt;
58 return Ctxt;
61 class X86MCSymbolizerTest : public MCSymbolizer {
62 public:
63 X86MCSymbolizerTest(MCContext &MC) : MCSymbolizer(MC, nullptr) {}
64 ~X86MCSymbolizerTest() {}
66 struct OpInfo {
67 int64_t Value = 0;
68 uint64_t Offset = 0;
69 uint64_t Size;
71 std::vector<OpInfo> Operands;
72 uint64_t InstructionSize = 0;
74 void reset() {
75 Operands.clear();
76 InstructionSize = 0;
79 bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &CStream,
80 int64_t Value, uint64_t Address, bool IsBranch,
81 uint64_t Offset, uint64_t OpSize,
82 uint64_t InstSize) override {
83 Operands.push_back({Value, Offset, OpSize});
84 InstructionSize = InstSize;
85 return false;
88 void tryAddingPcLoadReferenceComment(raw_ostream &cStream, int64_t Value,
89 uint64_t Address) override {}
92 } // namespace
94 TEST(X86Disassembler, X86MCSymbolizerTest) {
95 X86MCSymbolizerTest *TestSymbolizer = new X86MCSymbolizerTest(getContext());
96 getContext().DisAsm->setSymbolizer(
97 std::unique_ptr<MCSymbolizer>(TestSymbolizer));
99 MCDisassembler::DecodeStatus Status;
100 MCInst Inst;
101 uint64_t InstSize;
103 auto checkBytes = [&](ArrayRef<uint8_t> Bytes) {
104 TestSymbolizer->reset();
105 Status =
106 getContext().DisAsm->getInstruction(Inst, InstSize, Bytes, 0, nulls());
107 ASSERT_TRUE(Status == MCDisassembler::Success);
108 EXPECT_EQ(TestSymbolizer->InstructionSize, InstSize);
111 auto checkOperand = [&](size_t OpNo, int64_t Value, uint64_t Offset,
112 uint64_t Size) {
113 ASSERT_TRUE(TestSymbolizer->Operands.size() > OpNo);
114 EXPECT_EQ(TestSymbolizer->Operands[OpNo].Value, Value);
115 EXPECT_EQ(TestSymbolizer->Operands[OpNo].Offset, Offset);
116 EXPECT_EQ(TestSymbolizer->Operands[OpNo].Size, Size);
119 // movq $0x80000, 0x80000
120 checkBytes(
121 {0x48, 0xc7, 0x04, 0x25, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00});
122 checkOperand(0, 0x80000, 4, 4);
123 checkOperand(1, 0x80000, 8, 4);
125 // movq $0x2a, 0x123(%rax,%r14,8)
126 checkBytes(
127 {0x4a, 0xc7, 0x84, 0xf0, 0x23, 0x01, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00});
128 checkOperand(0, 291, 4, 4);
129 checkOperand(1, 42, 8, 4);
131 // movq $0xffffffffffffefe8, -0x1(%rip)
132 // Test that the value of the rip-relative operand is set correctly.
133 // The instruction address is 0 and the size is 12 bytes.
134 checkBytes(
135 {0x48, 0xc7, 0x05, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xef, 0xff, 0xff});
136 checkOperand(0, /*next instr address*/ 11 - /*disp*/ 1, 3, 4);
137 checkOperand(1, 0xffffffffffffefe8, 7, 4);
139 // movq $0xfffffffffffffef5, (%r12)
140 // Test that the displacement operand has a size of 0, since it is not
141 // explicitly specified in the instruction.
142 checkBytes({0x49, 0xc7, 0x04, 0x24, 0xf5, 0xfe, 0xff, 0xff});
143 checkOperand(0, 0, 4, 0);
144 checkOperand(1, 0xfffffffffffffef5, 4, 4);
146 // mov %ax, 0x1568179(%rbx)
147 // Test that the displacement operand size is not affected by the operand
148 // size override prefix.
149 checkBytes({0x66, 0x89, 0x83, 0x79, 0x81, 0x56, 0x01});
150 checkOperand(0, 0x1568179, 3, 4);