• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "berberis/backend/common/machine_ir.h"
18 
19 #include <string>
20 
21 #include "berberis/base/stringprintf.h"
22 
23 namespace berberis {
24 
25 namespace {
26 
GetInsnListDebugString(const char * indent,const MachineInsnList & insn_list)27 std::string GetInsnListDebugString(const char* indent, const MachineInsnList& insn_list) {
28   std::string out;
29   for (const auto* insn : insn_list) {
30     out += indent;
31     out += insn->GetDebugString();
32     out += "\n";
33   }
34   return out;
35 }
36 
37 }  // namespace
38 
GetMachineRegDebugString(MachineReg r)39 std::string GetMachineRegDebugString(MachineReg r) {
40   if (r.IsHardReg()) {
41     return GetMachineHardRegDebugName(r);
42   }
43   if (r.IsVReg()) {
44     return StringPrintf("v%d", r.GetVRegIndex());
45   }
46   if (r.IsSpilledReg()) {
47     return StringPrintf("s%d", r.GetSpilledRegIndex());
48   }
49   return "?";
50 }
51 
GetRegOperandDebugString(const MachineInsn * insn,int i)52 std::string GetRegOperandDebugString(const MachineInsn* insn, int i) {
53   MachineReg r = insn->RegAt(i);
54   std::string out;
55   if (r.IsVReg()) {
56     out += insn->RegKindAt(i).RegClass()->GetDebugName();
57     out += " ";
58   }
59   out += GetMachineRegDebugString(r);
60   return out;
61 }
62 
GetDebugString() const63 std::string MachineBasicBlock::GetDebugString() const {
64   std::string out(StringPrintf("%2d MachineBasicBlock live_in=[", id()));
65 
66   for (size_t i = 0; i < live_in().size(); ++i) {
67     if (i > 0) {
68       out += ", ";
69     }
70     out += GetMachineRegDebugString(live_in()[i]);
71   }
72   out += "] live_out=[";
73 
74   for (size_t i = 0; i < live_out().size(); ++i) {
75     if (i > 0) {
76       out += ", ";
77     }
78     out += GetMachineRegDebugString(live_out()[i]);
79   }
80   out += "]\n";
81 
82   for (const auto* edge : in_edges()) {
83     out += StringPrintf("    MachineEdge %d -> %d [\n", edge->src()->id(), edge->dst()->id());
84     out += GetInsnListDebugString("      ", edge->insn_list());
85     out += "    ]\n";
86   }
87 
88   out += GetInsnListDebugString("    ", insn_list());
89 
90   return out;
91 }
92 
GetDebugString() const93 std::string MachineIR::GetDebugString() const {
94   std::string out;
95   for (const auto* bb : bb_list()) {
96     out += bb->GetDebugString();
97   }
98   return out;
99 }
100 
GetDebugStringForDot() const101 std::string MachineIR::GetDebugStringForDot() const {
102   std::string str;
103   str += "digraph MachineIR {\n";
104 
105   for (const auto* bb : bb_list()) {
106     for (auto* in_edge : bb->in_edges()) {
107       auto* pred_bb = in_edge->src();
108 
109       // Print edge.
110       str += StringPrintf("BB%d->BB%d", pred_bb->id(), bb->id());
111       str += ";\n";
112     }
113 
114     // Print instructions with "\l" new-lines for left-justification.
115     str += StringPrintf("BB%d [shape=box,label=\"BB%d\\l", bb->id(), bb->id());
116     for (const auto* insn : bb->insn_list()) {
117       str += insn->GetDebugString();
118       str += "\\l";
119     }
120     str += "\"];\n";
121   }
122 
123   str += "}\n";
124   return str;
125 }
126 
GetDebugString() const127 std::string PseudoBranch::GetDebugString() const {
128   return StringPrintf("PSEUDO_BRANCH %d", then_bb()->id());
129 }
130 
GetDebugString() const131 std::string PseudoCondBranch::GetDebugString() const {
132   std::string out("PSEUDO_COND_BRANCH ");
133   out += GetCondName(cond());
134   out += ", ";
135   out += StringPrintf("%d, ", then_bb()->id());
136   out += StringPrintf("%d, ", else_bb()->id());
137   out += StringPrintf("(%s)", GetRegOperandDebugString(this, 0).c_str());
138   return out;
139 }
140 
GetDebugString() const141 std::string PseudoJump::GetDebugString() const {
142   const char* suffix;
143   switch (kind_) {
144     case Kind::kJumpWithPendingSignalsCheck:
145       suffix = "_SIG_CHECK";
146       break;
147     case Kind::kJumpWithoutPendingSignalsCheck:
148       suffix = "";
149       break;
150     case Kind::kSyscall:
151       suffix = "_TO_SYSCALL";
152       break;
153     case Kind::kExitGeneratedCode:
154       suffix = "_EXIT_GEN_CODE";
155       break;
156   }
157   return StringPrintf("PSEUDO_JUMP%s 0x%" PRIxPTR, suffix, target_);
158 }
159 
GetDebugString() const160 std::string PseudoIndirectJump::GetDebugString() const {
161   std::string out("PSEUDO_INDIRECT_JUMP ");
162   out += GetMachineRegDebugString(src_);
163   return out;
164 }
165 
GetDebugString() const166 std::string PseudoCopy::GetDebugString() const {
167   std::string out("PSEUDO_COPY ");
168   out += GetRegOperandDebugString(this, 0);
169   out += ", ";
170   out += GetRegOperandDebugString(this, 1);
171   return out;
172 }
173 
GetDebugString() const174 std::string PseudoDefXReg::GetDebugString() const {
175   return std::string("PSEUDO_DEF ") + GetRegOperandDebugString(this, 0);
176 }
177 
GetDebugString() const178 std::string PseudoDefReg::GetDebugString() const {
179   return std::string("PSEUDO_DEF ") + GetRegOperandDebugString(this, 0);
180 }
181 
GetDebugString() const182 std::string PseudoReadFlags::GetDebugString() const {
183   std::string out("PSEUDO_READ_FLAGS ");
184   out += with_overflow() ? "" : "(skip overflow) ";
185   out += GetRegOperandDebugString(this, 0);
186   out += ", ";
187   out += GetRegOperandDebugString(this, 1);
188   return out;
189 }
190 
GetDebugString() const191 std::string PseudoWriteFlags::GetDebugString() const {
192   std::string out("PSEUDO_WRITE_FLAGS ");
193   out += GetRegOperandDebugString(this, 0);
194   out += ", ";
195   out += GetRegOperandDebugString(this, 1);
196   return out;
197 }
198 
199 }  // namespace berberis
200