• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <iomanip>
17 #include <iostream>
18 #include <sstream>
19 #include <string>
20 #include "basicblock.h"
21 #include "compiler_options.h"
22 #include "inst.h"
23 #include "graph.h"
24 #include "dump.h"
25 #include "optimizer/analysis/linear_order.h"
26 #include "optimizer/analysis/rpo.h"
27 #include "optimizer/analysis/loop_analyzer.h"
28 #include "optimizer/code_generator/target_info.h"
29 
30 namespace ark::compiler {
31 
32 // indent constants for dump instructions
33 static const int INDENT_ID = 6;
34 static const int INDENT_TYPE = 5;
35 static const int INDENT_OPCODE = 27;
36 static const int HEX_PTR_SIZE = sizeof(void *);
37 
38 template <class T>
ToArenaString(T value,ArenaAllocator * allocator)39 std::enable_if_t<std::is_integral_v<T>, ArenaString> ToArenaString(T value, ArenaAllocator *allocator)
40 {
41     ArenaString res(std::to_string(value), allocator->Adapter());
42     return res;
43 }
44 
GetId(uint32_t id,ArenaAllocator * allocator)45 ArenaString GetId(uint32_t id, ArenaAllocator *allocator)
46 {
47     return (id == INVALID_ID ? ArenaString("XX", allocator->Adapter()) : ToArenaString(id, allocator));
48 }
49 
IdToString(uint32_t id,ArenaAllocator * allocator,bool vReg,bool isPhi)50 ArenaString IdToString(uint32_t id, ArenaAllocator *allocator, bool vReg, bool isPhi)
51 {
52     ArenaString reg(vReg ? "v" : "", allocator->Adapter());
53     ArenaString phi(isPhi ? "p" : "", allocator->Adapter());
54     return reg + GetId(id, allocator) + phi;
55 }
56 
57 // If print without brackets, then we print with space.
PrintIfValidLocation(Location location,Arch arch,std::ostream * out,bool withBrackets=false)58 void PrintIfValidLocation(Location location, Arch arch, std::ostream *out, bool withBrackets = false)
59 {
60     if (!location.IsInvalid() && !location.IsUnallocatedRegister()) {
61         auto string = location.ToString(arch);
62         if (withBrackets) {
63             (*out) << "(" << string << ")";
64         } else {
65             (*out) << string << " ";
66         }
67     }
68 }
69 
InstId(const Inst * inst,ArenaAllocator * allocator)70 ArenaString InstId(const Inst *inst, ArenaAllocator *allocator)
71 {
72     if (inst != nullptr) {
73         if (inst->IsSaveState() && g_options.IsCompilerDumpCompact()) {
74             return ArenaString("ss", allocator->Adapter()) +
75                    ArenaString(std::to_string(inst->GetId()), allocator->Adapter());
76         }
77         return IdToString(static_cast<uint32_t>(inst->GetId()), allocator, true, inst->IsPhi());
78     }
79     ArenaString null("null", allocator->Adapter());
80     return null;
81 }
82 
BBId(const BasicBlock * block,ArenaAllocator * allocator)83 ArenaString BBId(const BasicBlock *block, ArenaAllocator *allocator)
84 {
85     if (block != nullptr) {
86         return IdToString(static_cast<uint32_t>(block->GetId()), allocator);
87     }
88     ArenaString null("null", allocator->Adapter());
89     return null;
90 }
91 
DumpUsers(const Inst * inst,std::ostream * out)92 void DumpUsers(const Inst *inst, std::ostream *out)
93 {
94     auto allocator = inst->GetBasicBlock()->GetGraph()->GetLocalAllocator();
95     auto arch = inst->GetBasicBlock()->GetGraph()->GetArch();
96     for (size_t i = 0; i < inst->GetDstCount(); ++i) {
97         PrintIfValidLocation(inst->GetDstLocation(i), arch, out);
98     }
99     bool flFirst = true;
100     for (auto &nodeInst : inst->GetUsers()) {
101         auto user = nodeInst.GetInst();
102         (*out) << (flFirst ? "(" : ", ") << InstId(user, allocator);
103         if (flFirst) {
104             flFirst = false;
105         }
106     }
107     if (!flFirst) {
108         (*out) << ')';
109     }
110 }
111 
GetCondCodeToString(ConditionCode cc,ArenaAllocator * allocator)112 ArenaString GetCondCodeToString(ConditionCode cc, ArenaAllocator *allocator)
113 {
114     switch (cc) {
115         case ConditionCode::CC_EQ:
116             return ArenaString("EQ", allocator->Adapter());
117         case ConditionCode::CC_NE:
118             return ArenaString("NE", allocator->Adapter());
119 
120         case ConditionCode::CC_LT:
121             return ArenaString("LT", allocator->Adapter());
122         case ConditionCode::CC_LE:
123             return ArenaString("LE", allocator->Adapter());
124         case ConditionCode::CC_GT:
125             return ArenaString("GT", allocator->Adapter());
126         case ConditionCode::CC_GE:
127             return ArenaString("GE", allocator->Adapter());
128 
129         case ConditionCode::CC_B:
130             return ArenaString("B", allocator->Adapter());
131         case ConditionCode::CC_BE:
132             return ArenaString("BE", allocator->Adapter());
133         case ConditionCode::CC_A:
134             return ArenaString("A", allocator->Adapter());
135         case ConditionCode::CC_AE:
136             return ArenaString("AE", allocator->Adapter());
137 
138         case ConditionCode::CC_TST_EQ:
139             return ArenaString("TST_EQ", allocator->Adapter());
140         case ConditionCode::CC_TST_NE:
141             return ArenaString("TST_NE", allocator->Adapter());
142         default:
143             UNREACHABLE();
144     }
145 }
146 
PcToString(uint32_t pc,ArenaAllocator * allocator)147 ArenaString PcToString(uint32_t pc, ArenaAllocator *allocator)
148 {
149     std::ostringstream outString;
150     outString << "bc: 0x" << std::setfill('0') << std::setw(HEX_PTR_SIZE) << std::hex << pc;
151     return ArenaString(outString.str(), allocator->Adapter());
152 }
153 
154 template <typename T>
BBDependence(const char * type,const T & bbVector,std::ostream * out,ArenaAllocator * allocator)155 void BBDependence(const char *type, const T &bbVector, std::ostream *out, ArenaAllocator *allocator)
156 {
157     bool flFirst = true;
158     (*out) << type << ": [";
159     for (auto blockIt : bbVector) {
160         (*out) << (flFirst ? "" : ", ") << "bb " << BBId(blockIt, allocator);
161         if (flFirst) {
162             flFirst = false;
163         }
164     }
165     (*out) << ']';
166 }
167 
FieldToString(RuntimeInterface * runtime,ObjectType type,RuntimeInterface::FieldPtr field,ArenaAllocator * allocator)168 ArenaString FieldToString(RuntimeInterface *runtime, ObjectType type, RuntimeInterface::FieldPtr field,
169                           ArenaAllocator *allocator)
170 {
171     const auto &adapter = allocator->Adapter();
172     if (type != ObjectType::MEM_STATIC && type != ObjectType::MEM_OBJECT) {
173         return ArenaString(ObjectTypeToString(type), adapter);
174     }
175 
176     if (!runtime->HasFieldMetadata(field)) {
177         auto offset = runtime->GetFieldOffset(field);
178         return ArenaString("Unknown.Unknown", adapter) + ArenaString(std::to_string(offset), adapter);
179     }
180 
181     ArenaString dot(".", adapter);
182     ArenaString clsName(runtime->GetClassName(runtime->GetClassForField(field)), adapter);
183     ArenaString fieldName(runtime->GetFieldName(field), adapter);
184     return clsName + dot + fieldName;
185 }
186 
DumpTypedFieldOpcode(std::ostream * out,Opcode opcode,uint32_t typeId,const ArenaString & fieldName,ArenaAllocator * allocator)187 void DumpTypedFieldOpcode(std::ostream *out, Opcode opcode, uint32_t typeId, const ArenaString &fieldName,
188                           ArenaAllocator *allocator)
189 {
190     const auto &adapter = allocator->Adapter();
191     ArenaString space(" ", adapter);
192     ArenaString opc(GetOpcodeString(opcode), adapter);
193     ArenaString id(IdToString(typeId, allocator), adapter);
194     (*out) << std::setw(INDENT_OPCODE) << opc + space + id + space + fieldName + space;
195 }
196 
DumpTypedOpcode(std::ostream * out,Opcode opcode,uint32_t typeId,ArenaAllocator * allocator)197 void DumpTypedOpcode(std::ostream *out, Opcode opcode, uint32_t typeId, ArenaAllocator *allocator)
198 {
199     ArenaString space(" ", allocator->Adapter());
200     ArenaString opc(GetOpcodeString(opcode), allocator->Adapter());
201     ArenaString id(IdToString(typeId, allocator), allocator->Adapter());
202     (*out) << std::setw(INDENT_OPCODE) << opc + space + id + space;
203 }
204 
DumpTypedOpcode(std::ostream * out,Opcode opcode,uint32_t typeId,const ArenaString & flags,ArenaAllocator * allocator)205 void DumpTypedOpcode(std::ostream *out, Opcode opcode, uint32_t typeId, const ArenaString &flags,
206                      ArenaAllocator *allocator)
207 {
208     ArenaString space(" ", allocator->Adapter());
209     ArenaString opc(GetOpcodeString(opcode), allocator->Adapter());
210     ArenaString id(IdToString(typeId, allocator), allocator->Adapter());
211     (*out) << std::setw(INDENT_OPCODE) << opc + flags + space + id + space;
212 }
213 
DumpInputs(std::ostream * out) const214 bool Inst::DumpInputs(std::ostream *out) const
215 {
216     const auto &allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
217     auto arch = GetBasicBlock()->GetGraph()->GetArch();
218     bool flFirst = true;
219     unsigned i = 0;
220     for (auto nodeInst : GetInputs()) {
221         Inst *input = nodeInst.GetInst();
222         (*out) << (flFirst ? "" : ", ") << InstId(input, allocator);
223         PrintIfValidLocation(GetLocation(i), arch, out, true);
224         i++;
225         flFirst = false;
226     }
227 
228     if (!GetTmpLocation().IsInvalid()) {
229         (*out) << (flFirst ? "" : ", ") << "Tmp(" << GetTmpLocation().ToString(arch) << ")";
230     }
231 
232     return !flFirst;
233 }
234 
DumpInputs(std::ostream * out) const235 bool SaveStateInst::DumpInputs(std::ostream *out) const
236 {
237     const auto &allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
238     const char *sep = "";
239     for (size_t i = 0; i < GetInputsCount(); i++) {
240         (*out) << sep << std::dec << InstId(GetInput(i).GetInst(), allocator);
241         if (GetVirtualRegister(i).IsSpecialReg()) {
242             (*out) << "(" << VRegInfo::VRegTypeToString(GetVirtualRegister(i).GetVRegType()) << ")";
243         } else if (GetVirtualRegister(i).IsBridge()) {
244             (*out) << "(bridge)";
245         } else {
246             (*out) << "(vr" << GetVirtualRegister(i).Value() << ")";
247         }
248         sep = ", ";
249     }
250     if (GetImmediatesCount() > 0) {
251         for (auto imm : *GetImmediates()) {
252             (*out) << sep << std::hex << "0x" << imm.value;
253             if (imm.vregType == VRegType::VREG) {
254                 (*out) << std::dec << "(vr" << imm.vreg << ")";
255             } else {
256                 (*out) << "(" << VRegInfo::VRegTypeToString(imm.vregType) << ")";
257             }
258             sep = ", ";
259         }
260     }
261     if (GetCallerInst() != nullptr) {
262         (*out) << sep << "caller=" << GetCallerInst()->GetId();
263     }
264     (*out) << sep << "inlining_depth=" << GetInliningDepth();
265     return true;
266 }
267 
DumpInputs(std::ostream * out) const268 bool BinaryImmOperation::DumpInputs(std::ostream *out) const
269 {
270     Inst::DumpInputs(out);
271     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
272     return true;
273 }
274 
DumpInputs(std::ostream * out) const275 bool BinaryShiftedRegisterOperation::DumpInputs(std::ostream *out) const
276 {
277     Inst::DumpInputs(out);
278     (*out) << ", " << GetShiftTypeStr(GetShiftType()) << " 0x" << std::hex << GetImm() << std::dec;
279     return true;
280 }
281 
DumpInputs(std::ostream * out) const282 bool UnaryShiftedRegisterOperation::DumpInputs(std::ostream *out) const
283 {
284     Inst::DumpInputs(out);
285     (*out) << ", " << GetShiftTypeStr(GetShiftType()) << " 0x" << std::hex << GetImm() << std::dec;
286     return true;
287 }
288 
DumpInputs(std::ostream * out) const289 bool SelectImmInst::DumpInputs(std::ostream *out) const
290 {
291     Inst::DumpInputs(out);
292     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
293     return true;
294 }
295 
DumpInputs(std::ostream * out) const296 bool IfImmInst::DumpInputs(std::ostream *out) const
297 {
298     Inst::DumpInputs(out);
299     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
300     return true;
301 }
302 
DumpInputs(std::ostream * out) const303 bool PhiInst::DumpInputs(std::ostream *out) const
304 {
305     const auto &allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
306     bool flFirst = true;
307     for (size_t idx = 0; idx < GetInputsCount(); ++idx) {
308         Inst *input = GetInput(idx).GetInst();
309         auto block = GetPhiInputBb(idx);
310         (*out) << (flFirst ? "" : ", ") << InstId(input, allocator) << "(bb" << BBId(block, allocator) << ")";
311         if (flFirst) {
312             flFirst = false;
313         }
314     }
315     return !flFirst;
316 }
317 
DumpInputs(std::ostream * out) const318 bool ConstantInst::DumpInputs(std::ostream *out) const
319 {
320     switch (GetType()) {
321         case DataType::Type::REFERENCE:
322         case DataType::Type::BOOL:
323         case DataType::Type::UINT8:
324         case DataType::Type::INT8:
325         case DataType::Type::UINT16:
326         case DataType::Type::INT16:
327         case DataType::Type::UINT32:
328         case DataType::Type::INT32:
329         case DataType::Type::UINT64:
330         case DataType::Type::INT64:
331             (*out) << "0x" << std::hex << GetIntValue() << std::dec;
332             break;
333         case DataType::Type::FLOAT32:
334             (*out) << GetFloatValue();
335             break;
336         case DataType::Type::FLOAT64:
337             (*out) << GetDoubleValue();
338             break;
339         case DataType::Type::ANY:
340             (*out) << "0x" << std::hex << GetRawValue() << std::dec;
341             break;
342         default:
343             UNREACHABLE();
344     }
345     return true;
346 }
347 
DumpInputs(std::ostream * out) const348 bool SpillFillInst::DumpInputs(std::ostream *out) const
349 {
350     bool first = true;
351     for (auto spillFill : GetSpillFills()) {
352         if (!first) {
353             (*out) << ", ";
354         }
355         first = false;
356         (*out) << sf_data::ToString(spillFill, GetBasicBlock()->GetGraph()->GetArch());
357     }
358     return true;
359 }
360 
DumpInputs(std::ostream * out) const361 bool ParameterInst::DumpInputs(std::ostream *out) const
362 {
363     auto argNum = GetArgNumber();
364     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
365     ArenaString nums("nums", allocator->Adapter());
366     (*out) << "arg " << ((argNum == ParameterInst::DYNAMIC_NUM_ARGS) ? nums : IdToString(argNum, allocator));
367     return true;
368 }
369 
DumpOpcode(std::ostream * out) const370 void CompareInst::DumpOpcode(std::ostream *out) const
371 {
372     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
373     const auto &adapter = allocator->Adapter();
374     ArenaString space(" ", adapter);
375     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
376     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
377     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
378     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
379 }
380 
DumpOpcodeAnyTypeMixin(std::ostream & out,const Inst * inst)381 static void DumpOpcodeAnyTypeMixin(std::ostream &out, const Inst *inst)
382 {
383     const auto *mixinInst = static_cast<const AnyTypeMixin<FixedInputsInst1> *>(inst);
384     ASSERT(mixinInst != nullptr);
385     auto allocator = mixinInst->GetBasicBlock()->GetGraph()->GetLocalAllocator();
386     const auto &adapter = allocator->Adapter();
387     ArenaString space(" ", adapter);
388     ArenaString opcode(GetOpcodeString(mixinInst->GetOpcode()), adapter);
389     ArenaString anyBaseType(AnyTypeTypeToString(mixinInst->GetAnyType()), adapter);
390     out << std::setw(INDENT_OPCODE)
391         << opcode + space + anyBaseType + (mixinInst->IsIntegerWasSeen() ? " i" : "") +
392                (mixinInst->IsSpecialWasSeen() ? " s" : "") + (mixinInst->IsTypeWasProfiled() ? " p" : "") + space;
393 }
394 
DumpOpcode(std::ostream * out) const395 void PhiInst::DumpOpcode(std::ostream *out) const
396 {
397     if (GetBasicBlock()->GetGraph()->IsDynamicMethod()) {
398         DumpOpcodeAnyTypeMixin(*out, this);
399     } else {
400         Inst::DumpOpcode(out);
401     }
402 }
403 
DumpOpcode(std::ostream * out) const404 void CompareAnyTypeInst::DumpOpcode(std::ostream *out) const
405 {
406     DumpOpcodeAnyTypeMixin(*out, this);
407 }
408 
DumpOpcode(std::ostream * out) const409 void GetAnyTypeNameInst::DumpOpcode(std::ostream *out) const
410 {
411     DumpOpcodeAnyTypeMixin(*out, this);
412 }
413 
DumpOpcode(std::ostream * out) const414 void CastAnyTypeValueInst::DumpOpcode(std::ostream *out) const
415 {
416     DumpOpcodeAnyTypeMixin(*out, this);
417 }
418 
DumpOpcode(std::ostream * out) const419 void CastValueToAnyTypeInst::DumpOpcode(std::ostream *out) const
420 {
421     DumpOpcodeAnyTypeMixin(*out, this);
422 }
423 
DumpOpcode(std::ostream * out) const424 void AnyTypeCheckInst::DumpOpcode(std::ostream *out) const
425 {
426     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
427     const auto &adapter = allocator->Adapter();
428     ArenaString space(" ", adapter);
429     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
430     ArenaString anyBaseType(AnyTypeTypeToString(GetAnyType()), adapter);
431     (*out) << std::setw(INDENT_OPCODE)
432            << (opcode + space + anyBaseType + (IsIntegerWasSeen() ? " i" : "") + (IsSpecialWasSeen() ? " s" : "") +
433                (IsTypeWasProfiled() ? " p" : "") + space);
434 }
435 
DumpOpcode(std::ostream * out) const436 void HclassCheckInst::DumpOpcode(std::ostream *out) const
437 {
438     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
439     const auto &adapter = allocator->Adapter();
440     ArenaString space(" ", adapter);
441     ArenaString open("[", adapter);
442     ArenaString close("]", adapter);
443     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
444     bool isFirst = true;
445     ArenaString summary = opcode + space + open;
446     if (GetCheckIsFunction()) {
447         summary += ArenaString("IsFunc", adapter);
448         isFirst = false;
449     }
450     if (GetCheckFunctionIsNotClassConstructor()) {
451         if (!isFirst) {
452             summary += ArenaString(", ", adapter);
453         }
454         summary += ArenaString("IsNotClassConstr", adapter);
455     }
456     summary += close + space;
457     (*out) << std::setw(INDENT_OPCODE) << summary;
458 }
459 
DumpOpcode(std::ostream * out) const460 void LoadImmediateInst::DumpOpcode(std::ostream *out) const
461 {
462     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
463     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
464     ArenaString open("(", adapter);
465     ArenaString close(") ", adapter);
466     if (IsClass()) {
467         ArenaString type("class: ", adapter);
468         ArenaString className(GetBasicBlock()->GetGraph()->GetRuntime()->GetClassName(GetObject()), adapter);
469         (*out) << std::setw(INDENT_OPCODE) << opcode + open + type + className + close;
470     } else if (IsMethod()) {
471         ArenaString type("method: ", adapter);
472         ArenaString methodName(GetBasicBlock()->GetGraph()->GetRuntime()->GetMethodName(GetObject()), adapter);
473         (*out) << std::setw(INDENT_OPCODE) << opcode + open + type + methodName + close;
474     } else if (IsString()) {
475         ArenaString type("string: 0x", adapter);
476         (*out) << std::setw(INDENT_OPCODE) << opcode + open + type << std::hex << GetString() << close;
477     } else if (IsPandaFileOffset()) {
478         ArenaString type("PandaFileOffset: ", adapter);
479         (*out) << std::setw(INDENT_OPCODE) << opcode + open + type << std::hex << GetPandaFileOffset() << close;
480     } else if (IsConstantPool()) {
481         ArenaString type("constpool: 0x", adapter);
482         (*out) << std::setw(INDENT_OPCODE) << opcode + open + type << std::hex << GetConstantPool() << close;
483     } else if (IsObject()) {
484         ArenaString type("object: 0x", adapter);
485         (*out) << std::setw(INDENT_OPCODE) << opcode + open + type << std::hex << GetObject() << close;
486     } else if (IsTlsOffset()) {
487         ArenaString type("TlsOffset: 0x", adapter);
488         (*out) << std::setw(INDENT_OPCODE) << opcode + open + type << std::hex << GetTlsOffset() << close;
489     } else {
490         UNREACHABLE();
491     }
492 }
493 
DumpOpcode(std::ostream * out) const494 void FunctionImmediateInst::DumpOpcode(std::ostream *out) const
495 {
496     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
497     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
498     ArenaString prefix(" 0x", adapter);
499     (*out) << std::setw(INDENT_OPCODE) << opcode << prefix << std::hex << GetFunctionPtr() << " ";
500 }
501 
DumpOpcode(std::ostream * out) const502 void LoadObjFromConstInst::DumpOpcode(std::ostream *out) const
503 {
504     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
505     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
506     ArenaString prefix(" 0x", adapter);
507     (*out) << std::setw(INDENT_OPCODE) << opcode << prefix << std::hex << GetObjPtr() << " ";
508 }
509 
DumpOpcode(std::ostream * out) const510 void SelectInst::DumpOpcode(std::ostream *out) const
511 {
512     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
513     const auto &adapter = allocator->Adapter();
514     ArenaString space(" ", adapter);
515     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
516     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
517     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
518     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
519 }
520 
DumpOpcode(std::ostream * out) const521 void SelectImmInst::DumpOpcode(std::ostream *out) const
522 {
523     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
524     const auto &adapter = allocator->Adapter();
525     ArenaString space(" ", adapter);
526     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
527     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
528     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
529     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
530 }
531 
DumpOpcode(std::ostream * out) const532 void IfInst::DumpOpcode(std::ostream *out) const
533 {
534     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
535     const auto &adapter = allocator->Adapter();
536     ArenaString space(" ", adapter);
537     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
538     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
539     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
540     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
541 }
542 
DumpOpcode(std::ostream * out) const543 void IfImmInst::DumpOpcode(std::ostream *out) const
544 {
545     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
546     const auto &adapter = allocator->Adapter();
547     ArenaString space(" ", adapter);
548     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
549     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
550     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
551     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
552 }
553 
DumpOpcode(std::ostream * out) const554 void MonitorInst::DumpOpcode(std::ostream *out) const
555 {
556     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
557     ArenaString suffix(IsExit() ? ".Exit" : ".Entry", adapter);
558     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
559     (*out) << std::setw(INDENT_OPCODE) << opcode + suffix;
560 }
561 
DumpOpcode(std::ostream * out) const562 void CmpInst::DumpOpcode(std::ostream *out) const
563 {
564     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
565     auto type = GetOperandsType();
566     ArenaString suffix = ArenaString(" ", adapter) + ArenaString(DataType::ToString(type), adapter);
567     if (IsFloatType(type)) {
568         (*out) << std::setw(INDENT_OPCODE) << ArenaString(IsFcmpg() ? "Fcmpg" : "Fcmpl", adapter) + suffix;
569     } else if (IsTypeSigned(type)) {
570         (*out) << std::setw(INDENT_OPCODE) << ArenaString("Cmp", adapter) + ArenaString(" ", adapter) + suffix;
571     } else {
572         (*out) << std::setw(INDENT_OPCODE) << ArenaString("Ucmp", adapter) + suffix;
573     }
574 }
575 
DumpOpcode(std::ostream * out) const576 void CastInst::DumpOpcode(std::ostream *out) const
577 {
578     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
579     ArenaString space(" ", adapter);
580     (*out) << std::setw(INDENT_OPCODE)
581            << (ArenaString(GetOpcodeString(GetOpcode()), adapter) + space +
582                ArenaString(DataType::ToString(GetOperandsType()), adapter));
583 }
584 
DumpOpcode(std::ostream * out) const585 void NewObjectInst::DumpOpcode(std::ostream *out) const
586 {
587     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
588 }
589 
DumpOpcode(std::ostream * out) const590 void NewArrayInst::DumpOpcode(std::ostream *out) const
591 {
592     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
593     auto adapter = allocator->Adapter();
594     ArenaString space(" ", adapter);
595     ArenaString opc(GetOpcodeString(GetOpcode()), adapter);
596     ArenaString id(IdToString(GetTypeId(), allocator), adapter);
597     ArenaString size("", adapter);
598     ASSERT(GetInputsCount() > 1);
599     auto sizeInst = GetDataFlowInput(1);
600     if (sizeInst->IsConst()) {
601         auto sizeValue = sizeInst->CastToConstant()->GetIntValue();
602         size = ArenaString("(size=", adapter) + ToArenaString(sizeValue, allocator) + ")";
603     }
604     (*out) << std::setw(INDENT_OPCODE) << opc + space + size + space + id + space;
605 }
606 
DumpOpcode(std::ostream * out) const607 void LoadConstArrayInst::DumpOpcode(std::ostream *out) const
608 {
609     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
610 }
611 
DumpOpcode(std::ostream * out) const612 void FillConstArrayInst::DumpOpcode(std::ostream *out) const
613 {
614     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
615 }
616 
DumpOpcode(std::ostream * out) const617 void LoadObjectInst::DumpOpcode(std::ostream *out) const
618 {
619     auto graph = GetBasicBlock()->GetGraph();
620     auto fieldName = FieldToString(graph->GetRuntime(), GetObjectType(), GetObjField(), graph->GetLocalAllocator());
621     DumpTypedFieldOpcode(out, GetOpcode(), GetTypeId(), fieldName, graph->GetLocalAllocator());
622 }
623 
624 class ObjectPairParams {
625 public:
626     const Graph *graph;
627     Opcode opc;
628     RuntimeInterface::FieldPtr field0;
629     RuntimeInterface::FieldPtr field1;
630     uint32_t typeId0;
631     uint32_t typeId1;
632 };
633 
DumpObjectPairOpcode(std::ostream * out,ObjectPairParams & params)634 void DumpObjectPairOpcode(std::ostream *out, ObjectPairParams &params)
635 {
636     auto graph = params.graph;
637     auto runtime = graph->GetRuntime();
638     auto *allocator = graph->GetLocalAllocator();
639     const auto &adapter = allocator->Adapter();
640 
641     auto field0 = params.field0;
642     auto field1 = params.field1;
643 
644     ArenaString space(" ", adapter);
645     ArenaString dot(".", adapter);
646 
647     ArenaString clsName("", adapter);
648     ArenaString fieldName0("", adapter);
649     ArenaString fieldName1("", adapter);
650 
651     ArenaString id0(IdToString(params.typeId0, allocator), adapter);
652     auto offset0 = space + ArenaString(std::to_string(runtime->GetFieldOffset(field0)), adapter);
653     ArenaString id1(IdToString(params.typeId1, allocator), adapter);
654     auto offset1 = space + ArenaString(std::to_string(runtime->GetFieldOffset(field1)), adapter);
655     if (!runtime->HasFieldMetadata(field0)) {
656         clsName = ArenaString("Unknown ", adapter);
657         fieldName0 = id0 + space + dot + ArenaString(".Unknown", adapter) + offset0;
658         fieldName1 = id1 + space + dot + ArenaString(".Unknown", adapter) + offset1;
659     } else {
660         clsName = ArenaString(runtime->GetClassName(runtime->GetClassForField(field0)), adapter) + space;
661         fieldName0 = id0 + space + dot + ArenaString(runtime->GetFieldName(field0), adapter) + offset0;
662         fieldName1 = id1 + space + dot + ArenaString(runtime->GetFieldName(field1), adapter) + offset1;
663     }
664     ArenaString opc(GetOpcodeString(params.opc), adapter);
665     (*out) << std::setw(INDENT_OPCODE) << opc + space + clsName + space + fieldName0 + space + fieldName1 + space;
666 }
667 
DumpOpcode(std::ostream * out) const668 void LoadObjectPairInst::DumpOpcode(std::ostream *out) const
669 {
670     ObjectPairParams params {
671         GetBasicBlock()->GetGraph(), GetOpcode(), GetObjField0(), GetObjField1(), GetTypeId0(), GetTypeId1()};
672     DumpObjectPairOpcode(out, params);
673 }
674 
DumpOpcode(std::ostream * out) const675 void StoreObjectPairInst::DumpOpcode(std::ostream *out) const
676 {
677     ObjectPairParams params {
678         GetBasicBlock()->GetGraph(), GetOpcode(), GetObjField0(), GetObjField1(), GetTypeId0(), GetTypeId1()};
679     DumpObjectPairOpcode(out, params);
680 }
681 
DumpOpcode(std::ostream * out) const682 void LoadMemInst::DumpOpcode(std::ostream *out) const
683 {
684     DumpTypedOpcode(out, GetOpcode(), GetType(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
685 }
686 
DumpOpcode(std::ostream * out) const687 void ResolveObjectFieldInst::DumpOpcode(std::ostream *out) const
688 {
689     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
690 }
691 
DumpOpcode(std::ostream * out) const692 void LoadResolvedObjectFieldInst::DumpOpcode(std::ostream *out) const
693 {
694     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
695 }
696 
DumpOpcode(std::ostream * out) const697 void StoreObjectInst::DumpOpcode(std::ostream *out) const
698 {
699     auto graph = GetBasicBlock()->GetGraph();
700     auto fieldName = FieldToString(graph->GetRuntime(), GetObjectType(), GetObjField(), graph->GetLocalAllocator());
701     DumpTypedFieldOpcode(out, GetOpcode(), GetTypeId(), fieldName, graph->GetLocalAllocator());
702 }
703 
DumpOpcode(std::ostream * out) const704 void StoreResolvedObjectFieldInst::DumpOpcode(std::ostream *out) const
705 {
706     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
707 }
708 
DumpOpcode(std::ostream * out) const709 void StoreMemInst::DumpOpcode(std::ostream *out) const
710 {
711     DumpTypedOpcode(out, GetOpcode(), GetType(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
712 }
713 
DumpOpcode(std::ostream * out) const714 void LoadStaticInst::DumpOpcode(std::ostream *out) const
715 {
716     auto graph = GetBasicBlock()->GetGraph();
717     auto fieldName =
718         FieldToString(graph->GetRuntime(), ObjectType::MEM_STATIC, GetObjField(), graph->GetLocalAllocator());
719     DumpTypedFieldOpcode(out, GetOpcode(), GetTypeId(), fieldName, graph->GetLocalAllocator());
720 }
721 
DumpOpcode(std::ostream * out) const722 void ResolveObjectFieldStaticInst::DumpOpcode(std::ostream *out) const
723 {
724     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
725 }
726 
DumpOpcode(std::ostream * out) const727 void LoadResolvedObjectFieldStaticInst::DumpOpcode(std::ostream *out) const
728 {
729     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
730 }
731 
DumpOpcode(std::ostream * out) const732 void StoreStaticInst::DumpOpcode(std::ostream *out) const
733 {
734     auto graph = GetBasicBlock()->GetGraph();
735     auto fieldName =
736         FieldToString(graph->GetRuntime(), ObjectType::MEM_STATIC, GetObjField(), graph->GetLocalAllocator());
737     DumpTypedFieldOpcode(out, GetOpcode(), GetTypeId(), fieldName, graph->GetLocalAllocator());
738 }
739 
DumpOpcode(std::ostream * out) const740 void UnresolvedStoreStaticInst::DumpOpcode(std::ostream *out) const
741 {
742     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
743 }
744 
DumpOpcode(std::ostream * out) const745 void StoreResolvedObjectFieldStaticInst::DumpOpcode(std::ostream *out) const
746 {
747     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
748 }
749 
DumpOpcode(std::ostream * out) const750 void LoadFromPool::DumpOpcode(std::ostream *out) const
751 {
752     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
753 }
754 
DumpOpcode(std::ostream * out) const755 void LoadFromPoolDynamic::DumpOpcode(std::ostream *out) const
756 {
757     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
758 }
759 
DumpOpcode(std::ostream * out) const760 void ClassInst::DumpOpcode(std::ostream *out) const
761 {
762     auto graph = GetBasicBlock()->GetGraph();
763     auto allocator = graph->GetLocalAllocator();
764     const auto &adapter = allocator->Adapter();
765 
766     ArenaString space(" ", adapter);
767     ArenaString qt("'", adapter);
768     ArenaString opc(GetOpcodeString(GetOpcode()), adapter);
769     ArenaString className(GetClass() == nullptr ? ArenaString("", adapter)
770                                                 : ArenaString(graph->GetRuntime()->GetClassName(GetClass()), adapter));
771     (*out) << std::setw(INDENT_OPCODE) << opc + space + qt + className + qt << " ";
772 }
773 
DumpOpcode(std::ostream * out) const774 void RuntimeClassInst::DumpOpcode(std::ostream *out) const
775 {
776     auto graph = GetBasicBlock()->GetGraph();
777     auto allocator = graph->GetLocalAllocator();
778     const auto &adapter = allocator->Adapter();
779 
780     ArenaString space(" ", adapter);
781     ArenaString qt("'", adapter);
782     ArenaString opc(GetOpcodeString(GetOpcode()), adapter);
783     ArenaString className(GetClass() == nullptr ? ArenaString("", adapter)
784                                                 : ArenaString(graph->GetRuntime()->GetClassName(GetClass()), adapter));
785     (*out) << std::setw(INDENT_OPCODE) << opc + space + qt + className + qt << " ";
786 }
787 
DumpOpcode(std::ostream * out) const788 void GlobalVarInst::DumpOpcode(std::ostream *out) const
789 {
790     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
791 }
792 
DumpOpcode(std::ostream * out) const793 void CheckCastInst::DumpOpcode(std::ostream *out) const
794 {
795     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
796     const auto &adapter = allocator->Adapter();
797     ArenaString flags("", adapter);
798     if (CanDeoptimize()) {
799         flags = " D";
800     }
801     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), flags, allocator);
802 }
803 
DumpOpcode(std::ostream * out) const804 void IsInstanceInst::DumpOpcode(std::ostream *out) const
805 {
806     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
807 }
808 
DumpOpcode(std::ostream * out) const809 void IntrinsicInst::DumpOpcode(std::ostream *out) const
810 {
811     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
812     ArenaString intrinsic(IsBuiltin() ? ArenaString("BuiltinIntrinsic.", adapter) : ArenaString("Intrinsic.", adapter));
813     ArenaString opcode(GetIntrinsicName(intrinsicId_), adapter);
814     (*out) << std::setw(INDENT_OPCODE) << intrinsic + opcode << " ";
815 }
816 
DumpOpcode(std::ostream * out) const817 void Inst::DumpOpcode(std::ostream *out) const
818 {
819     auto graph = GetBasicBlock()->GetGraph();
820     auto allocator = graph->GetLocalAllocator();
821     const auto &adapter = allocator->Adapter();
822     ArenaString space(" ", adapter);
823     ArenaString flags("", adapter);
824     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
825     if (CanDeoptimize()) {
826         flags += "D";
827     }
828     if (GetFlag(inst_flags::MEM_BARRIER)) {
829         static constexpr auto FENCE = "F";
830         flags += FENCE;
831     }
832     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
833     (*out) << std::setw(INDENT_OPCODE) << opcode + space + flags;
834 }
835 
DumpOpcode(std::ostream * out) const836 void ResolveStaticInst::DumpOpcode(std::ostream *out) const
837 {
838     auto graph = GetBasicBlock()->GetGraph();
839     auto allocator = graph->GetLocalAllocator();
840     const auto &adapter = allocator->Adapter();
841     ArenaString space(" ", adapter);
842     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
843     ArenaString methodId(ToArenaString(GetCallMethodId(), allocator));
844     if (GetCallMethod() != nullptr) {
845         ArenaString method(graph->GetRuntime()->GetMethodFullName(GetCallMethod()), adapter);
846         (*out) << std::setw(INDENT_OPCODE) << opcode + ' ' + methodId + ' ' + method << ' ';
847     } else {
848         (*out) << std::setw(INDENT_OPCODE) << opcode + ' ' + methodId << ' ';
849     }
850 }
851 
DumpOpcode(std::ostream * out) const852 void ResolveVirtualInst::DumpOpcode(std::ostream *out) const
853 {
854     auto graph = GetBasicBlock()->GetGraph();
855     auto allocator = graph->GetLocalAllocator();
856     const auto &adapter = allocator->Adapter();
857     ArenaString space(" ", adapter);
858     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
859     ArenaString methodId(ToArenaString(GetCallMethodId(), allocator));
860     if (GetCallMethod() != nullptr) {
861         ArenaString method(graph->GetRuntime()->GetMethodFullName(GetCallMethod()), adapter);
862         (*out) << std::setw(INDENT_OPCODE) << opcode + ' ' + methodId + ' ' + method << ' ';
863     } else {
864         (*out) << std::setw(INDENT_OPCODE) << opcode + ' ' + methodId << ' ';
865     }
866 }
867 
DumpOpcode(std::ostream * out) const868 void InitStringInst::DumpOpcode(std::ostream *out) const
869 {
870     auto graph = GetBasicBlock()->GetGraph();
871     auto allocator = graph->GetLocalAllocator();
872     const auto &adapter = allocator->Adapter();
873     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
874     if (IsFromString()) {
875         ArenaString mode(" FromString", adapter);
876         (*out) << std::setw(INDENT_OPCODE) << opcode + mode << ' ';
877     } else {
878         ASSERT(IsFromCharArray());
879         ArenaString mode(" FromCharArray", adapter);
880         (*out) << std::setw(INDENT_OPCODE) << opcode + mode << ' ';
881     }
882 }
883 
DumpOpcode(std::ostream * out) const884 void CallInst::DumpOpcode(std::ostream *out) const
885 {
886     auto graph = GetBasicBlock()->GetGraph();
887     auto allocator = graph->GetLocalAllocator();
888     const auto &adapter = allocator->Adapter();
889     ArenaString space(" ", adapter);
890     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
891     ArenaString inlined(IsInlined() ? ".Inlined " : " ", adapter);
892     ArenaString methodId(ToArenaString(GetCallMethodId(), allocator));
893     if (!IsUnresolved() && GetCallMethod() != nullptr) {
894         ArenaString method(graph->GetRuntime()->GetMethodFullName(GetCallMethod()), adapter);
895         (*out) << std::setw(INDENT_OPCODE) << opcode + inlined + methodId + ' ' + method << ' ';
896     } else {
897         (*out) << std::setw(INDENT_OPCODE) << opcode + inlined + methodId << ' ';
898     }
899 }
900 
DumpOpcode(std::ostream * out) const901 void DeoptimizeInst::DumpOpcode(std::ostream *out) const
902 {
903     auto graph = GetBasicBlock()->GetGraph();
904     auto allocator = graph->GetLocalAllocator();
905     const auto &adapter = allocator->Adapter();
906     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
907     ArenaString type(DeoptimizeTypeToString(GetDeoptimizeType()), adapter);
908     (*out) << std::setw(INDENT_OPCODE) << opcode + ArenaString(" ", adapter) + type << ' ';
909 }
910 
DumpOpcode(std::ostream * out) const911 void DeoptimizeIfInst::DumpOpcode(std::ostream *out) const
912 {
913     auto graph = GetBasicBlock()->GetGraph();
914     auto allocator = graph->GetLocalAllocator();
915     const auto &adapter = allocator->Adapter();
916     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
917     ArenaString type(DeoptimizeTypeToString(GetDeoptimizeType()), adapter);
918     (*out) << std::setw(INDENT_OPCODE) << opcode + ArenaString(" ", adapter) + type << ' ';
919 }
920 
DumpOpcode(std::ostream * out) const921 void DeoptimizeCompareInst::DumpOpcode(std::ostream *out) const
922 {
923     auto graph = GetBasicBlock()->GetGraph();
924     auto allocator = graph->GetLocalAllocator();
925     const auto &adapter = allocator->Adapter();
926     ArenaString opcode(ArenaString(GetOpcodeString(GetOpcode()), adapter).append(" "));
927     ArenaString cc(ArenaString(GetCondCodeToString(GetCc(), allocator), adapter).append(" "));
928     ArenaString type(ArenaString(DeoptimizeTypeToString(GetDeoptimizeType()), adapter).append(" "));
929     ArenaString cmpType(ArenaString(DataType::ToString(GetOperandsType()), adapter).append(" "));
930     (*out) << std::setw(INDENT_OPCODE) << opcode.append(cc).append(cmpType).append(type);
931 }
932 
DumpOpcode(std::ostream * out) const933 void DeoptimizeCompareImmInst::DumpOpcode(std::ostream *out) const
934 {
935     auto graph = GetBasicBlock()->GetGraph();
936     auto allocator = graph->GetLocalAllocator();
937     const auto &adapter = allocator->Adapter();
938     ArenaString opcode(ArenaString(GetOpcodeString(GetOpcode()), adapter).append(" "));
939     ArenaString cc(ArenaString(GetCondCodeToString(GetCc(), allocator), adapter).append(" "));
940     ArenaString type(ArenaString(DeoptimizeTypeToString(GetDeoptimizeType()), adapter).append(" "));
941     ArenaString cmpType(ArenaString(DataType::ToString(GetOperandsType()), adapter).append(" "));
942     (*out) << std::setw(INDENT_OPCODE) << opcode.append(cc).append(cmpType).append(type);
943 }
944 
DumpInputs(std::ostream * out) const945 bool DeoptimizeCompareImmInst::DumpInputs(std::ostream *out) const
946 {
947     Inst::DumpInputs(out);
948     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
949     return true;
950 }
951 
DumpInputs(std::ostream * out) const952 bool BoundsCheckInstI::DumpInputs(std::ostream *out) const
953 {
954     Inst *lenInput = GetInput(0).GetInst();
955     Inst *ssInput = GetInput(1).GetInst();
956     auto graph = GetBasicBlock()->GetGraph();
957     auto allocator = graph->GetLocalAllocator();
958 
959     (*out) << InstId(lenInput, allocator);
960     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
961     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
962     (*out) << ", " << InstId(ssInput, allocator);
963     return true;
964 }
965 
DumpInputs(std::ostream * out) const966 bool StoreInstI::DumpInputs(std::ostream *out) const
967 {
968     Inst *arrInput = GetInput(0).GetInst();
969     Inst *ssInput = GetInput(1).GetInst();
970     auto graph = GetBasicBlock()->GetGraph();
971     auto arch = graph->GetArch();
972     const auto &allocator = graph->GetLocalAllocator();
973 
974     (*out) << InstId(arrInput, allocator);
975     PrintIfValidLocation(GetLocation(0), arch, out, true);
976     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
977     (*out) << ", " << InstId(ssInput, allocator);
978     PrintIfValidLocation(GetLocation(1), arch, out, true);
979     return true;
980 }
981 
DumpInputs(std::ostream * out) const982 bool StoreMemInstI::DumpInputs(std::ostream *out) const
983 {
984     Inst *arrInput = GetInput(0).GetInst();
985     Inst *ssInput = GetInput(1).GetInst();
986     auto graph = GetBasicBlock()->GetGraph();
987     const auto &allocator = graph->GetLocalAllocator();
988 
989     (*out) << InstId(arrInput, allocator);
990     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
991     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
992     (*out) << ", " << InstId(ssInput, allocator);
993     return true;
994 }
995 
DumpInputs(std::ostream * out) const996 bool LoadInstI::DumpInputs(std::ostream *out) const
997 {
998     Inst::DumpInputs(out);
999     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
1000     return true;
1001 }
1002 
DumpInputs(std::ostream * out) const1003 bool LoadMemInstI::DumpInputs(std::ostream *out) const
1004 {
1005     Inst::DumpInputs(out);
1006     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
1007     return true;
1008 }
1009 
DumpInputs(std::ostream * out) const1010 bool LoadMemInst::DumpInputs(std::ostream *out) const
1011 {
1012     Inst::DumpInputs(out);
1013     if (GetScale() != 0) {
1014         (*out) << " Scale " << GetScale();
1015     }
1016     return true;
1017 }
1018 
DumpInputs(std::ostream * out) const1019 bool StoreMemInst::DumpInputs(std::ostream *out) const
1020 {
1021     Inst::DumpInputs(out);
1022     if (GetScale() != 0) {
1023         (*out) << " Scale " << GetScale();
1024     }
1025     return true;
1026 }
1027 
DumpInputs(std::ostream * out) const1028 bool LoadPairPartInst::DumpInputs(std::ostream *out) const
1029 {
1030     Inst *arrInput = GetInput(0).GetInst();
1031     auto graph = GetBasicBlock()->GetGraph();
1032     const auto &allocator = graph->GetLocalAllocator();
1033 
1034     (*out) << InstId(arrInput, allocator);
1035     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
1036     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
1037     return true;
1038 }
1039 
DumpInputs(std::ostream * out) const1040 bool LoadArrayPairInst::DumpInputs(std::ostream *out) const
1041 {
1042     Inst::DumpInputs(out);
1043     if (GetImm() > 0) {
1044         (*out) << ", 0x" << std::hex << GetImm() << std::dec;
1045     }
1046     return true;
1047 }
1048 
DumpInputs(std::ostream * out) const1049 bool LoadArrayPairInstI::DumpInputs(std::ostream *out) const
1050 {
1051     Inst *arrInput = GetInput(0).GetInst();
1052     auto graph = GetBasicBlock()->GetGraph();
1053     const auto &allocator = graph->GetLocalAllocator();
1054     (*out) << InstId(arrInput, allocator);
1055     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
1056     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
1057     return true;
1058 }
1059 
DumpInputs(std::ostream * out) const1060 bool StoreArrayPairInst::DumpInputs(std::ostream *out) const
1061 {
1062     Inst::DumpInputs(out);
1063     if (GetImm() > 0) {
1064         (*out) << ", 0x" << std::hex << GetImm() << std::dec;
1065     }
1066     return true;
1067 }
1068 
DumpInputs(std::ostream * out) const1069 bool StoreArrayPairInstI::DumpInputs(std::ostream *out) const
1070 {
1071     Inst *arrInput = GetInput(0).GetInst();
1072     Inst *fssInput = GetInput(1).GetInst();
1073     constexpr auto IMM_2 = 2;
1074     Inst *sssInput = GetInput(IMM_2).GetInst();
1075     auto graph = GetBasicBlock()->GetGraph();
1076     auto allocator = graph->GetLocalAllocator();
1077 
1078     (*out) << InstId(arrInput, allocator);
1079     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
1080     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
1081     (*out) << ", " << InstId(fssInput, allocator);
1082     (*out) << ", " << InstId(sssInput, allocator);
1083     return true;
1084 }
1085 
DumpInputs(std::ostream * out) const1086 bool ReturnInstI::DumpInputs(std::ostream *out) const
1087 {
1088     (*out) << "0x" << std::hex << GetImm() << std::dec;
1089     return true;
1090 }
1091 
DumpImms(std::ostream * out) const1092 void IntrinsicInst::DumpImms(std::ostream *out) const
1093 {
1094     if (!HasImms()) {
1095         return;
1096     }
1097 
1098     const auto &imms = GetImms();
1099     ASSERT(!imms.empty());
1100     (*out) << "0x" << std::hex << imms[0U];
1101     for (size_t i = 1U; i < imms.size(); ++i) {
1102         (*out) << ", 0x" << imms[i];
1103     }
1104     (*out) << ' ' << std::dec;
1105 }
1106 
DumpInputs(std::ostream * out) const1107 bool IntrinsicInst::DumpInputs(std::ostream *out) const
1108 {
1109     DumpImms(out);
1110     return Inst::DumpInputs(out);
1111 }
1112 
DumpBytecode(std::ostream * out) const1113 void Inst::DumpBytecode(std::ostream *out) const
1114 {
1115     if (pc_ != INVALID_PC) {
1116         auto graph = GetBasicBlock()->GetGraph();
1117         auto byteCode = graph->GetRuntime()->GetBytecodeString(graph->GetMethod(), pc_);
1118         if (!byteCode.empty()) {
1119             (*out) << byteCode << '\n';
1120         }
1121     }
1122 }
1123 
1124 #ifdef PANDA_COMPILER_DEBUG_INFO
DumpSourceLine(std::ostream * out) const1125 void Inst::DumpSourceLine(std::ostream *out) const
1126 {
1127     auto currentMethod = GetCurrentMethod();
1128     auto pc = GetPc();
1129     if (currentMethod != nullptr && pc != INVALID_PC) {
1130         auto line = GetBasicBlock()->GetGraph()->GetRuntime()->GetLineNumberAndSourceFile(currentMethod, pc);
1131         (*out) << " (" << line << " )";
1132     }
1133 }
1134 #endif  // PANDA_COMPILER_DEBUG_INFO
1135 
Dump(std::ostream * out,bool newLine) const1136 void Inst::Dump(std::ostream *out, bool newLine) const
1137 {
1138     if (g_options.IsCompilerDumpCompact() && IsSaveState()) {
1139         return;
1140     }
1141     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
1142     // Id
1143     (*out) << std::setw(INDENT_ID) << std::setfill(' ') << std::right
1144            << IdToString(id_, allocator, false, IsPhi()) + '.';
1145     // Type
1146     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
1147     (*out) << std::setw(INDENT_TYPE) << std::left << DataType::ToString(GetType());
1148     // opcode
1149     DumpOpcode(out);
1150     auto operandsPos = out->tellp();
1151     // inputs
1152     bool hasInput = DumpInputs(out);
1153     // users
1154     if (hasInput && !GetUsers().Empty()) {
1155         (*out) << " -> ";
1156     }
1157     DumpUsers(this, out);
1158     // Align rest of the instruction info
1159     static constexpr auto ALIGN_BUF_SIZE = 64;
1160     if (auto posDiff = out->tellp() - operandsPos; posDiff < ALIGN_BUF_SIZE) {
1161         posDiff = ALIGN_BUF_SIZE - posDiff;
1162         static std::array<char, ALIGN_BUF_SIZE + 1> spaceBuf;
1163         if (spaceBuf[0] != ' ') {
1164             std::fill(spaceBuf.begin(), spaceBuf.end(), ' ');
1165         }
1166         spaceBuf[posDiff] = 0;
1167         (*out) << spaceBuf.data();
1168         spaceBuf[posDiff] = ' ';
1169     }
1170     // bytecode pointer
1171     if (pc_ != INVALID_PC && !g_options.IsCompilerDumpCompact()) {
1172         (*out) << ' ' << PcToString(pc_, allocator);
1173     }
1174 #ifdef PANDA_COMPILER_DEBUG_INFO
1175     if (g_options.IsCompilerDumpSourceLine()) {
1176         DumpSourceLine(out);
1177     }
1178 #endif
1179     if (newLine) {
1180         (*out) << '\n';
1181     }
1182     if (g_options.IsCompilerDumpBytecode()) {
1183         DumpBytecode(out);
1184     }
1185     if (GetOpcode() == Opcode::Parameter) {
1186         auto spillFill = static_cast<const ParameterInst *>(this)->GetLocationData();
1187         if (spillFill.DstValue() != INVALID_REG) {
1188             (*out) << sf_data::ToString(spillFill, GetBasicBlock()->GetGraph()->GetArch());
1189             if (newLine) {
1190                 *out << std::endl;
1191             }
1192         }
1193     }
1194 }
1195 
CheckPrintPropsFlag(std::ostream * out,bool * printPropsFlag)1196 void CheckPrintPropsFlag(std::ostream *out, bool *printPropsFlag)
1197 {
1198     if (!(*printPropsFlag)) {
1199         (*out) << "prop: ";
1200         (*printPropsFlag) = true;
1201     } else {
1202         (*out) << ", ";
1203     }
1204 }
1205 
PrintLoopInfo(std::ostream * out,Loop * loop)1206 void PrintLoopInfo(std::ostream *out, Loop *loop)
1207 {
1208     (*out) << "loop" << (loop->IsIrreducible() ? " (irreducible) " : " ") << loop->GetId();
1209     if (loop->GetDepth() > 0) {
1210         (*out) << ", depth " << loop->GetDepth();
1211     }
1212 }
1213 
CheckStartEnd(const BasicBlock * block,std::ostream * out,bool * printPropsFlag)1214 static void CheckStartEnd(const BasicBlock *block, std::ostream *out, bool *printPropsFlag)
1215 {
1216     if (block->IsStartBlock()) {
1217         CheckPrintPropsFlag(out, printPropsFlag);
1218         (*out) << "start";
1219     }
1220     if (block->IsEndBlock()) {
1221         CheckPrintPropsFlag(out, printPropsFlag);
1222         (*out) << "end";
1223     }
1224 }
1225 
CheckLoop(const BasicBlock * block,std::ostream * out,bool * printPropsFlag)1226 static void CheckLoop(const BasicBlock *block, std::ostream *out, bool *printPropsFlag)
1227 {
1228     if (block->IsLoopPreHeader()) {
1229         CheckPrintPropsFlag(out, printPropsFlag);
1230         (*out) << "prehead";
1231     }
1232     if (block->IsLoopValid() && !block->GetLoop()->IsRoot()) {
1233         if (block->IsLoopHeader()) {
1234             CheckPrintPropsFlag(out, printPropsFlag);
1235             (*out) << "head";
1236         }
1237         CheckPrintPropsFlag(out, printPropsFlag);
1238         PrintLoopInfo(out, block->GetLoop());
1239     }
1240 }
1241 
CheckTryCatch(const BasicBlock * block,std::ostream * out,bool * printPropsFlag)1242 static void CheckTryCatch(const BasicBlock *block, std::ostream *out, bool *printPropsFlag)
1243 {
1244     if (block->IsTryBegin()) {
1245         CheckPrintPropsFlag(out, printPropsFlag);
1246         (*out) << "try_begin (id " << block->GetTryId() << ")";
1247     }
1248     if (block->IsTry()) {
1249         CheckPrintPropsFlag(out, printPropsFlag);
1250         (*out) << "try (id " << block->GetTryId() << ")";
1251     }
1252     if (block->IsTryEnd()) {
1253         CheckPrintPropsFlag(out, printPropsFlag);
1254         (*out) << "try_end (id " << block->GetTryId() << ")";
1255     }
1256     if (block->IsCatchBegin()) {
1257         CheckPrintPropsFlag(out, printPropsFlag);
1258         (*out) << "catch_begin";
1259     }
1260     if (block->IsCatch()) {
1261         CheckPrintPropsFlag(out, printPropsFlag);
1262         (*out) << "catch";
1263     }
1264 }
1265 
BlockProps(const BasicBlock * block,std::ostream * out)1266 void BlockProps(const BasicBlock *block, std::ostream *out)
1267 {
1268     bool printPropsFlag = false;
1269     CheckStartEnd(block, out, &printPropsFlag);
1270     CheckLoop(block, out, &printPropsFlag);
1271     CheckTryCatch(block, out, &printPropsFlag);
1272 
1273     if (block->GetGuestPc() != INVALID_PC) {
1274         CheckPrintPropsFlag(out, &printPropsFlag);
1275         (*out) << PcToString(block->GetGuestPc(), block->GetGraph()->GetLocalAllocator());
1276     }
1277     if (printPropsFlag) {
1278         (*out) << std::endl;
1279     }
1280 }
1281 
Dump(std::ostream * out) const1282 void BasicBlock::Dump(std::ostream *out) const
1283 {
1284     const auto &allocator = GetGraph()->GetLocalAllocator();
1285     (*out) << "BB " << IdToString(bbId_, allocator);
1286     // predecessors
1287     if (!preds_.empty()) {
1288         (*out) << "  ";
1289         BBDependence("preds", preds_, out, allocator);
1290     }
1291     (*out) << '\n';
1292     // properties
1293     BlockProps(this, out);
1294     (*out) << "hotness=" << GetHotness() << '\n';
1295     // instructions
1296     for (auto inst : this->AllInsts()) {
1297         inst->Dump(out);
1298     }
1299     // successors
1300     if (!succs_.empty()) {
1301         BBDependence("succs", succs_, out, allocator);
1302         (*out) << '\n';
1303     }
1304 }
1305 
Dump(std::ostream * out) const1306 void Graph::Dump(std::ostream *out) const
1307 {
1308     const auto &runtime = GetRuntime();
1309     const auto &method = GetMethod();
1310     const auto &adapter = GetLocalAllocator()->Adapter();
1311     ArenaString returnType(DataType::ToString(runtime->GetMethodReturnType(method)), adapter);
1312     (*out) << "Method: " << runtime->GetMethodFullName(method, true) << " " << method << std::endl;
1313     if (IsOsrMode()) {
1314         (*out) << "OSR mode\n";
1315     }
1316     (*out) << std::endl;
1317 
1318     auto &blocks = GetAnalysis<LinearOrder>().IsValid() ? GetBlocksLinearOrder() : GetBlocksRPO();
1319     for (const auto &blockIt : blocks) {
1320         if (!blockIt->GetPredsBlocks().empty() || !blockIt->GetSuccsBlocks().empty()) {
1321             blockIt->Dump(out);
1322             (*out) << '\n';
1323         } else {
1324             // to print the dump before cleanup, still unconnected nodes exist
1325             (*out) << "BB " << blockIt->GetId() << " is unconnected\n\n";
1326         }
1327     }
1328 }
1329 }  // namespace ark::compiler
1330