1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // x86_64 machine IR insns debugging.
18 
19 #include "berberis/backend/x86_64/code_debug.h"
20 
21 #include <cinttypes>
22 #include <string>
23 
24 #include "berberis/base/logging.h"
25 #include "berberis/base/stringprintf.h"
26 
27 // TODO(b/179708579): share this code with 32-bit backend.
28 
29 using std::string;
30 
31 namespace berberis {
32 
GetMachineHardRegDebugName(MachineReg r)33 const char* GetMachineHardRegDebugName(MachineReg r) {
34   static const char* kHardRegs[] = {
35       "?",    "r8",     "r9",   "r10",   "r11",   "rsi",   "rdi",   "rax",   "rbx",
36       "rcx",  "rdx",    "rbp",  "rsp",   "r12",   "r13",   "r14",   "r15",   "?",
37       "?",    "eflags", "xmm0", "xmm1",  "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",
38       "xmm7", "xmm8",   "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
39   };
40   CHECK_LT(static_cast<unsigned>(r.reg()), std::size(kHardRegs));
41   return kHardRegs[r.reg()];
42 }
43 
44 namespace x86_64 {
45 
46 namespace {
47 
ScaleToInt(MachineMemOperandScale scale)48 int ScaleToInt(MachineMemOperandScale scale) {
49   switch (scale) {
50     case MachineMemOperandScale::kOne:
51       return 1;
52     case MachineMemOperandScale::kTwo:
53       return 2;
54     case MachineMemOperandScale::kFour:
55       return 4;
56     case MachineMemOperandScale::kEight:
57       return 8;
58   }
59 }
60 
61 }  // namespace
62 
GetImplicitRegOperandDebugString(const MachineInsnX86_64 * insn,int i)63 string GetImplicitRegOperandDebugString(const MachineInsnX86_64* insn, int i) {
64   return StringPrintf("(%s)", GetRegOperandDebugString(insn, i).c_str());
65 }
66 
GetAbsoluteMemOperandDebugString(const MachineInsnX86_64 * insn)67 string GetAbsoluteMemOperandDebugString(const MachineInsnX86_64* insn) {
68   return StringPrintf("[0x%x]", insn->disp());
69 }
70 
GetBaseDispMemOperandDebugString(const MachineInsnX86_64 * insn,int i)71 string GetBaseDispMemOperandDebugString(const MachineInsnX86_64* insn, int i) {
72   return StringPrintf("[%s + 0x%x]", GetRegOperandDebugString(insn, i).c_str(), insn->disp());
73 }
74 
GetIndexDispMemOperandDebugString(const MachineInsnX86_64 * insn,int i)75 string GetIndexDispMemOperandDebugString(const MachineInsnX86_64* insn, int i) {
76   return StringPrintf("[%s * %d + 0x%x]",
77                       GetRegOperandDebugString(insn, i).c_str(),
78                       ScaleToInt(insn->scale()),
79                       insn->disp());
80 }
81 
GetBaseIndexDispMemOperandDebugString(const MachineInsnX86_64 * insn,int i)82 string GetBaseIndexDispMemOperandDebugString(const MachineInsnX86_64* insn, int i) {
83   return StringPrintf("[%s + %s * %d + 0x%x]",
84                       GetRegOperandDebugString(insn, i).c_str(),
85                       GetRegOperandDebugString(insn, i + 1).c_str(),
86                       ScaleToInt(insn->scale()),
87                       insn->disp());
88 }
89 
GetImmOperandDebugString(const MachineInsnX86_64 * insn)90 string GetImmOperandDebugString(const MachineInsnX86_64* insn) {
91   return StringPrintf("0x%" PRIx64, insn->imm());
92 }
93 
GetCondOperandDebugString(const MachineInsnX86_64 * insn)94 string GetCondOperandDebugString(const MachineInsnX86_64* insn) {
95   return GetCondName(insn->cond());
96 }
97 
GetLabelOperandDebugString(const MachineInsnX86_64 * insn)98 string GetLabelOperandDebugString(const MachineInsnX86_64* insn) {
99   return GetImmOperandDebugString(insn);
100 }
101 
GetDebugString() const102 string CallImm::GetDebugString() const {
103   string out(StringPrintf("CALL 0x%" PRIx64, imm()));
104   for (int i = 0; i < NumRegOperands(); ++i) {
105     out += ", ";
106     out += GetRegOperandDebugString(this, i);
107   }
108   return out;
109 }
110 
GetDebugString() const111 string CallImmArg::GetDebugString() const {
112   return "CALL_ARG " + GetRegOperandDebugString(this, 0);
113 }
114 
115 }  // namespace x86_64
116 
117 }  // namespace berberis
118