• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 panda::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 
BBDependence(const char * type,const ArenaVector<BasicBlock * > & bbVector,std::ostream * out,ArenaAllocator * allocator)154 void BBDependence(const char *type, const ArenaVector<BasicBlock *> &bbVector, std::ostream *out,
155                   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 
DumpInputs(std::ostream * out) const205 bool Inst::DumpInputs(std::ostream *out) const
206 {
207     const auto &allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
208     auto arch = GetBasicBlock()->GetGraph()->GetArch();
209     bool flFirst = true;
210     unsigned i = 0;
211     for (auto nodeInst : GetInputs()) {
212         Inst *input = nodeInst.GetInst();
213         (*out) << (flFirst ? "" : ", ") << InstId(input, allocator);
214         PrintIfValidLocation(GetLocation(i), arch, out, true);
215         i++;
216         flFirst = false;
217     }
218 
219     if (!GetTmpLocation().IsInvalid()) {
220         (*out) << (flFirst ? "" : ", ") << "Tmp(" << GetTmpLocation().ToString(arch) << ")";
221     }
222 
223     return !flFirst;
224 }
225 
DumpInputs(std::ostream * out) const226 bool SaveStateInst::DumpInputs(std::ostream *out) const
227 {
228     const auto &allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
229     const char *sep = "";
230     for (size_t i = 0; i < GetInputsCount(); i++) {
231         (*out) << sep << std::dec << InstId(GetInput(i).GetInst(), allocator);
232         if (GetVirtualRegister(i).IsSpecialReg()) {
233             (*out) << "(" << VRegInfo::VRegTypeToString(GetVirtualRegister(i).GetVRegType()) << ")";
234         } else if (GetVirtualRegister(i).IsBridge()) {
235             (*out) << "(bridge)";
236         } else {
237             (*out) << "(vr" << GetVirtualRegister(i).Value() << ")";
238         }
239         sep = ", ";
240     }
241     if (GetImmediatesCount() > 0) {
242         for (auto imm : *GetImmediates()) {
243             (*out) << sep << std::hex << "0x" << imm.value;
244             if (imm.vregType == VRegType::VREG) {
245                 (*out) << std::dec << "(vr" << imm.vreg << ")";
246             } else {
247                 (*out) << "(" << VRegInfo::VRegTypeToString(imm.vregType) << ")";
248             }
249             sep = ", ";
250         }
251     }
252     if (GetCallerInst() != nullptr) {
253         (*out) << sep << "caller=" << GetCallerInst()->GetId();
254     }
255     (*out) << sep << "inlining_depth=" << GetInliningDepth();
256     return true;
257 }
258 
DumpInputs(std::ostream * out) const259 bool BinaryImmOperation::DumpInputs(std::ostream *out) const
260 {
261     Inst::DumpInputs(out);
262     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
263     return true;
264 }
265 
DumpInputs(std::ostream * out) const266 bool BinaryShiftedRegisterOperation::DumpInputs(std::ostream *out) const
267 {
268     Inst::DumpInputs(out);
269     (*out) << ", " << GetShiftTypeStr(GetShiftType()) << " 0x" << std::hex << GetImm() << std::dec;
270     return true;
271 }
272 
DumpInputs(std::ostream * out) const273 bool UnaryShiftedRegisterOperation::DumpInputs(std::ostream *out) const
274 {
275     Inst::DumpInputs(out);
276     (*out) << ", " << GetShiftTypeStr(GetShiftType()) << " 0x" << std::hex << GetImm() << std::dec;
277     return true;
278 }
279 
DumpInputs(std::ostream * out) const280 bool SelectImmInst::DumpInputs(std::ostream *out) const
281 {
282     Inst::DumpInputs(out);
283     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
284     return true;
285 }
286 
DumpInputs(std::ostream * out) const287 bool IfImmInst::DumpInputs(std::ostream *out) const
288 {
289     Inst::DumpInputs(out);
290     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
291     return true;
292 }
293 
DumpInputs(std::ostream * out) const294 bool PhiInst::DumpInputs(std::ostream *out) const
295 {
296     const auto &allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
297     bool flFirst = true;
298     for (size_t idx = 0; idx < GetInputsCount(); ++idx) {
299         Inst *input = GetInput(idx).GetInst();
300         auto block = GetPhiInputBb(idx);
301         (*out) << (flFirst ? "" : ", ") << InstId(input, allocator) << "(bb" << BBId(block, allocator) << ")";
302         if (flFirst) {
303             flFirst = false;
304         }
305     }
306     return !flFirst;
307 }
308 
DumpInputs(std::ostream * out) const309 bool ConstantInst::DumpInputs(std::ostream *out) const
310 {
311     switch (GetType()) {
312         case DataType::Type::REFERENCE:
313         case DataType::Type::BOOL:
314         case DataType::Type::UINT8:
315         case DataType::Type::INT8:
316         case DataType::Type::UINT16:
317         case DataType::Type::INT16:
318         case DataType::Type::UINT32:
319         case DataType::Type::INT32:
320         case DataType::Type::UINT64:
321         case DataType::Type::INT64:
322             (*out) << "0x" << std::hex << GetIntValue() << std::dec;
323             break;
324         case DataType::Type::FLOAT32:
325             (*out) << GetFloatValue();
326             break;
327         case DataType::Type::FLOAT64:
328             (*out) << GetDoubleValue();
329             break;
330         case DataType::Type::ANY:
331             (*out) << "0x" << std::hex << GetRawValue() << std::dec;
332             break;
333         default:
334             UNREACHABLE();
335     }
336     return true;
337 }
338 
DumpInputs(std::ostream * out) const339 bool SpillFillInst::DumpInputs(std::ostream *out) const
340 {
341     bool first = true;
342     for (auto spillFill : GetSpillFills()) {
343         if (!first) {
344             (*out) << ", ";
345         }
346         first = false;
347         (*out) << sf_data::ToString(spillFill, GetBasicBlock()->GetGraph()->GetArch());
348     }
349     return true;
350 }
351 
DumpInputs(std::ostream * out) const352 bool ParameterInst::DumpInputs(std::ostream *out) const
353 {
354     auto argNum = GetArgNumber();
355     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
356     ArenaString nums("nums", allocator->Adapter());
357     (*out) << "arg " << ((argNum == ParameterInst::DYNAMIC_NUM_ARGS) ? nums : IdToString(argNum, allocator));
358     return true;
359 }
360 
DumpOpcode(std::ostream * out) const361 void CompareInst::DumpOpcode(std::ostream *out) const
362 {
363     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
364     const auto &adapter = allocator->Adapter();
365     ArenaString space(" ", adapter);
366     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
367     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
368     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
369     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
370 }
371 
DumpOpcodeAnyTypeMixin(std::ostream & out,const Inst * inst)372 static void DumpOpcodeAnyTypeMixin(std::ostream &out, const Inst *inst)
373 {
374     const auto *mixinInst = static_cast<const AnyTypeMixin<FixedInputsInst1> *>(inst);
375     ASSERT(mixinInst != nullptr);
376     auto allocator = mixinInst->GetBasicBlock()->GetGraph()->GetLocalAllocator();
377     const auto &adapter = allocator->Adapter();
378     ArenaString space(" ", adapter);
379     ArenaString opcode(GetOpcodeString(mixinInst->GetOpcode()), adapter);
380     ArenaString anyBaseType(AnyTypeTypeToString(mixinInst->GetAnyType()), adapter);
381     out << std::setw(INDENT_OPCODE)
382         << opcode + space + anyBaseType + (mixinInst->IsIntegerWasSeen() ? " i" : "") +
383                (mixinInst->IsSpecialWasSeen() ? " s" : "") + (mixinInst->IsTypeWasProfiled() ? " p" : "") + space;
384 }
385 
DumpOpcode(std::ostream * out) const386 void PhiInst::DumpOpcode(std::ostream *out) const
387 {
388     if (GetBasicBlock()->GetGraph()->IsDynamicMethod()) {
389         DumpOpcodeAnyTypeMixin(*out, this);
390     } else {
391         Inst::DumpOpcode(out);
392     }
393 }
394 
DumpOpcode(std::ostream * out) const395 void CompareAnyTypeInst::DumpOpcode(std::ostream *out) const
396 {
397     DumpOpcodeAnyTypeMixin(*out, this);
398 }
399 
DumpOpcode(std::ostream * out) const400 void GetAnyTypeNameInst::DumpOpcode(std::ostream *out) const
401 {
402     DumpOpcodeAnyTypeMixin(*out, this);
403 }
404 
DumpOpcode(std::ostream * out) const405 void CastAnyTypeValueInst::DumpOpcode(std::ostream *out) const
406 {
407     DumpOpcodeAnyTypeMixin(*out, this);
408 }
409 
DumpOpcode(std::ostream * out) const410 void CastValueToAnyTypeInst::DumpOpcode(std::ostream *out) const
411 {
412     DumpOpcodeAnyTypeMixin(*out, this);
413 }
414 
DumpOpcode(std::ostream * out) const415 void AnyTypeCheckInst::DumpOpcode(std::ostream *out) const
416 {
417     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
418     const auto &adapter = allocator->Adapter();
419     ArenaString space(" ", adapter);
420     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
421     ArenaString anyBaseType(AnyTypeTypeToString(GetAnyType()), adapter);
422     (*out) << std::setw(INDENT_OPCODE)
423            << (opcode + space + anyBaseType + (IsIntegerWasSeen() ? " i" : "") + (IsSpecialWasSeen() ? " s" : "") +
424                (IsTypeWasProfiled() ? " p" : "") + space);
425 }
426 
DumpOpcode(std::ostream * out) const427 void HclassCheckInst::DumpOpcode(std::ostream *out) const
428 {
429     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
430     const auto &adapter = allocator->Adapter();
431     ArenaString space(" ", adapter);
432     ArenaString open("[", adapter);
433     ArenaString close("]", adapter);
434     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
435     bool isFirst = true;
436     ArenaString summary = opcode + space + open;
437     if (GetCheckIsFunction()) {
438         summary += ArenaString("IsFunc", adapter);
439         isFirst = false;
440     }
441     if (GetCheckFunctionIsNotClassConstructor()) {
442         if (!isFirst) {
443             summary += ArenaString(", ", adapter);
444         }
445         summary += ArenaString("IsNotClassConstr", adapter);
446     }
447     summary += close + space;
448     (*out) << std::setw(INDENT_OPCODE) << summary;
449 }
450 
DumpOpcode(std::ostream * out) const451 void LoadImmediateInst::DumpOpcode(std::ostream *out) const
452 {
453     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
454     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
455     ArenaString open("(", adapter);
456     ArenaString close(") ", adapter);
457     if (IsClass()) {
458         ArenaString type("class: ", adapter);
459         ArenaString className(GetBasicBlock()->GetGraph()->GetRuntime()->GetClassName(GetObject()), adapter);
460         (*out) << std::setw(INDENT_OPCODE) << opcode + open + type + className + close;
461     } else if (IsMethod()) {
462         ArenaString type("method: ", adapter);
463         ArenaString methodName(GetBasicBlock()->GetGraph()->GetRuntime()->GetMethodName(GetObject()), adapter);
464         (*out) << std::setw(INDENT_OPCODE) << opcode + open + type + methodName + close;
465     } else if (IsString()) {
466         ArenaString type("string: 0x", adapter);
467         (*out) << std::setw(INDENT_OPCODE) << opcode + open + type << std::hex << GetString() << close;
468     } else if (IsPandaFileOffset()) {
469         ArenaString type("PandaFileOffset: ", adapter);
470         (*out) << std::setw(INDENT_OPCODE) << opcode + open + type << std::hex << GetPandaFileOffset() << close;
471     } else if (IsConstantPool()) {
472         ArenaString type("constpool: 0x", adapter);
473         (*out) << std::setw(INDENT_OPCODE) << opcode + open + type << std::hex << GetConstantPool() << close;
474     } else {
475         UNREACHABLE();
476     }
477 }
478 
DumpOpcode(std::ostream * out) const479 void FunctionImmediateInst::DumpOpcode(std::ostream *out) const
480 {
481     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
482     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
483     ArenaString prefix(" 0x", adapter);
484     (*out) << std::setw(INDENT_OPCODE) << opcode << prefix << std::hex << GetFunctionPtr() << " ";
485 }
486 
DumpOpcode(std::ostream * out) const487 void LoadObjFromConstInst::DumpOpcode(std::ostream *out) const
488 {
489     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
490     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
491     ArenaString prefix(" 0x", adapter);
492     (*out) << std::setw(INDENT_OPCODE) << opcode << prefix << std::hex << GetObjPtr() << " ";
493 }
494 
DumpOpcode(std::ostream * out) const495 void SelectInst::DumpOpcode(std::ostream *out) const
496 {
497     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
498     const auto &adapter = allocator->Adapter();
499     ArenaString space(" ", adapter);
500     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
501     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
502     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
503     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
504 }
505 
DumpOpcode(std::ostream * out) const506 void SelectImmInst::DumpOpcode(std::ostream *out) const
507 {
508     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
509     const auto &adapter = allocator->Adapter();
510     ArenaString space(" ", adapter);
511     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
512     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
513     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
514     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
515 }
516 
DumpOpcode(std::ostream * out) const517 void IfInst::DumpOpcode(std::ostream *out) const
518 {
519     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
520     const auto &adapter = allocator->Adapter();
521     ArenaString space(" ", adapter);
522     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
523     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
524     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
525     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
526 }
527 
DumpOpcode(std::ostream * out) const528 void IfImmInst::DumpOpcode(std::ostream *out) const
529 {
530     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
531     const auto &adapter = allocator->Adapter();
532     ArenaString space(" ", adapter);
533     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
534     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
535     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
536     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
537 }
538 
DumpOpcode(std::ostream * out) const539 void MonitorInst::DumpOpcode(std::ostream *out) const
540 {
541     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
542     ArenaString suffix(IsExit() ? ".Exit" : ".Entry", adapter);
543     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
544     (*out) << std::setw(INDENT_OPCODE) << opcode + suffix;
545 }
546 
DumpOpcode(std::ostream * out) const547 void CmpInst::DumpOpcode(std::ostream *out) const
548 {
549     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
550     auto type = GetOperandsType();
551     ArenaString suffix = ArenaString(" ", adapter) + ArenaString(DataType::ToString(type), adapter);
552     if (IsFloatType(type)) {
553         (*out) << std::setw(INDENT_OPCODE) << ArenaString(IsFcmpg() ? "Fcmpg" : "Fcmpl", adapter) + suffix;
554     } else if (IsTypeSigned(type)) {
555         (*out) << std::setw(INDENT_OPCODE) << ArenaString("Cmp", adapter) + ArenaString(" ", adapter) + suffix;
556     } else {
557         (*out) << std::setw(INDENT_OPCODE) << ArenaString("Ucmp", adapter) + suffix;
558     }
559 }
560 
DumpOpcode(std::ostream * out) const561 void CastInst::DumpOpcode(std::ostream *out) const
562 {
563     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
564     ArenaString space(" ", adapter);
565     (*out) << std::setw(INDENT_OPCODE)
566            << (ArenaString(GetOpcodeString(GetOpcode()), adapter) + space +
567                ArenaString(DataType::ToString(GetOperandsType()), adapter));
568 }
569 
DumpOpcode(std::ostream * out) const570 void NewObjectInst::DumpOpcode(std::ostream *out) const
571 {
572     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
573 }
574 
DumpOpcode(std::ostream * out) const575 void NewArrayInst::DumpOpcode(std::ostream *out) const
576 {
577     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
578 }
579 
DumpOpcode(std::ostream * out) const580 void LoadConstArrayInst::DumpOpcode(std::ostream *out) const
581 {
582     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
583 }
584 
DumpOpcode(std::ostream * out) const585 void FillConstArrayInst::DumpOpcode(std::ostream *out) const
586 {
587     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
588 }
589 
DumpOpcode(std::ostream * out) const590 void LoadObjectInst::DumpOpcode(std::ostream *out) const
591 {
592     auto graph = GetBasicBlock()->GetGraph();
593     auto fieldName = FieldToString(graph->GetRuntime(), GetObjectType(), GetObjField(), graph->GetLocalAllocator());
594     DumpTypedFieldOpcode(out, GetOpcode(), GetTypeId(), fieldName, graph->GetLocalAllocator());
595 }
596 
DumpOpcode(std::ostream * out) const597 void LoadMemInst::DumpOpcode(std::ostream *out) const
598 {
599     DumpTypedOpcode(out, GetOpcode(), GetType(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
600 }
601 
DumpOpcode(std::ostream * out) const602 void ResolveObjectFieldInst::DumpOpcode(std::ostream *out) const
603 {
604     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
605 }
606 
DumpOpcode(std::ostream * out) const607 void LoadResolvedObjectFieldInst::DumpOpcode(std::ostream *out) const
608 {
609     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
610 }
611 
DumpOpcode(std::ostream * out) const612 void StoreObjectInst::DumpOpcode(std::ostream *out) const
613 {
614     auto graph = GetBasicBlock()->GetGraph();
615     auto fieldName = FieldToString(graph->GetRuntime(), GetObjectType(), GetObjField(), graph->GetLocalAllocator());
616     DumpTypedFieldOpcode(out, GetOpcode(), GetTypeId(), fieldName, graph->GetLocalAllocator());
617 }
618 
DumpOpcode(std::ostream * out) const619 void StoreResolvedObjectFieldInst::DumpOpcode(std::ostream *out) const
620 {
621     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
622 }
623 
DumpOpcode(std::ostream * out) const624 void StoreMemInst::DumpOpcode(std::ostream *out) const
625 {
626     DumpTypedOpcode(out, GetOpcode(), GetType(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
627 }
628 
DumpOpcode(std::ostream * out) const629 void LoadStaticInst::DumpOpcode(std::ostream *out) const
630 {
631     auto graph = GetBasicBlock()->GetGraph();
632     auto fieldName =
633         FieldToString(graph->GetRuntime(), ObjectType::MEM_STATIC, GetObjField(), graph->GetLocalAllocator());
634     DumpTypedFieldOpcode(out, GetOpcode(), GetTypeId(), fieldName, graph->GetLocalAllocator());
635 }
636 
DumpOpcode(std::ostream * out) const637 void ResolveObjectFieldStaticInst::DumpOpcode(std::ostream *out) const
638 {
639     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
640 }
641 
DumpOpcode(std::ostream * out) const642 void LoadResolvedObjectFieldStaticInst::DumpOpcode(std::ostream *out) const
643 {
644     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
645 }
646 
DumpOpcode(std::ostream * out) const647 void StoreStaticInst::DumpOpcode(std::ostream *out) const
648 {
649     auto graph = GetBasicBlock()->GetGraph();
650     auto fieldName =
651         FieldToString(graph->GetRuntime(), ObjectType::MEM_STATIC, GetObjField(), graph->GetLocalAllocator());
652     DumpTypedFieldOpcode(out, GetOpcode(), GetTypeId(), fieldName, graph->GetLocalAllocator());
653 }
654 
DumpOpcode(std::ostream * out) const655 void UnresolvedStoreStaticInst::DumpOpcode(std::ostream *out) const
656 {
657     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
658 }
659 
DumpOpcode(std::ostream * out) const660 void StoreResolvedObjectFieldStaticInst::DumpOpcode(std::ostream *out) const
661 {
662     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
663 }
664 
DumpOpcode(std::ostream * out) const665 void LoadFromPool::DumpOpcode(std::ostream *out) const
666 {
667     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
668 }
669 
DumpOpcode(std::ostream * out) const670 void LoadFromPoolDynamic::DumpOpcode(std::ostream *out) const
671 {
672     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
673 }
674 
DumpOpcode(std::ostream * out) const675 void ClassInst::DumpOpcode(std::ostream *out) const
676 {
677     auto graph = GetBasicBlock()->GetGraph();
678     auto allocator = graph->GetLocalAllocator();
679     const auto &adapter = allocator->Adapter();
680 
681     ArenaString space(" ", adapter);
682     ArenaString qt("'", adapter);
683     ArenaString opc(GetOpcodeString(GetOpcode()), adapter);
684     ArenaString className(GetClass() == nullptr ? ArenaString("", adapter)
685                                                 : ArenaString(graph->GetRuntime()->GetClassName(GetClass()), adapter));
686     (*out) << std::setw(INDENT_OPCODE) << opc + space + qt + className + qt << " ";
687 }
688 
DumpOpcode(std::ostream * out) const689 void RuntimeClassInst::DumpOpcode(std::ostream *out) const
690 {
691     auto graph = GetBasicBlock()->GetGraph();
692     auto allocator = graph->GetLocalAllocator();
693     const auto &adapter = allocator->Adapter();
694 
695     ArenaString space(" ", adapter);
696     ArenaString qt("'", adapter);
697     ArenaString opc(GetOpcodeString(GetOpcode()), adapter);
698     ArenaString className(GetClass() == nullptr ? ArenaString("", adapter)
699                                                 : ArenaString(graph->GetRuntime()->GetClassName(GetClass()), adapter));
700     (*out) << std::setw(INDENT_OPCODE) << opc + space + qt + className + qt << " ";
701 }
702 
DumpOpcode(std::ostream * out) const703 void GlobalVarInst::DumpOpcode(std::ostream *out) const
704 {
705     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
706 }
707 
DumpOpcode(std::ostream * out) const708 void CheckCastInst::DumpOpcode(std::ostream *out) const
709 {
710     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
711 }
712 
DumpOpcode(std::ostream * out) const713 void IsInstanceInst::DumpOpcode(std::ostream *out) const
714 {
715     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
716 }
717 
DumpOpcode(std::ostream * out) const718 void IntrinsicInst::DumpOpcode(std::ostream *out) const
719 {
720     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
721     ArenaString intrinsic(IsBuiltin() ? ArenaString("BuiltinIntrinsic.", adapter) : ArenaString("Intrinsic.", adapter));
722     ArenaString opcode(GetIntrinsicName(intrinsicId_), adapter);
723     (*out) << std::setw(INDENT_OPCODE) << intrinsic + opcode << " ";
724 }
725 
DumpOpcode(std::ostream * out) const726 void Inst::DumpOpcode(std::ostream *out) const
727 {
728     auto graph = GetBasicBlock()->GetGraph();
729     auto allocator = graph->GetLocalAllocator();
730     const auto &adapter = allocator->Adapter();
731     ArenaString space(" ", adapter);
732     ArenaString flags("", adapter);
733     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
734     if (CanDeoptimize()) {
735         flags += "D";
736     }
737     if (GetFlag(inst_flags::MEM_BARRIER)) {
738         static constexpr auto FENCE = "F";
739         flags += FENCE;
740     }
741     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
742     (*out) << std::setw(INDENT_OPCODE) << opcode + space + flags;
743 }
744 
DumpOpcode(std::ostream * out) const745 void ResolveStaticInst::DumpOpcode(std::ostream *out) const
746 {
747     auto graph = GetBasicBlock()->GetGraph();
748     auto allocator = graph->GetLocalAllocator();
749     const auto &adapter = allocator->Adapter();
750     ArenaString space(" ", adapter);
751     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
752     ArenaString methodId(ToArenaString(GetCallMethodId(), allocator));
753     if (GetCallMethod() != nullptr) {
754         ArenaString method(graph->GetRuntime()->GetMethodFullName(GetCallMethod()), adapter);
755         (*out) << std::setw(INDENT_OPCODE) << opcode + ' ' + methodId + ' ' + method << ' ';
756     } else {
757         (*out) << std::setw(INDENT_OPCODE) << opcode + ' ' + methodId << ' ';
758     }
759 }
760 
DumpOpcode(std::ostream * out) const761 void ResolveVirtualInst::DumpOpcode(std::ostream *out) const
762 {
763     auto graph = GetBasicBlock()->GetGraph();
764     auto allocator = graph->GetLocalAllocator();
765     const auto &adapter = allocator->Adapter();
766     ArenaString space(" ", adapter);
767     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
768     ArenaString methodId(ToArenaString(GetCallMethodId(), allocator));
769     if (GetCallMethod() != nullptr) {
770         ArenaString method(graph->GetRuntime()->GetMethodFullName(GetCallMethod()), adapter);
771         (*out) << std::setw(INDENT_OPCODE) << opcode + ' ' + methodId + ' ' + method << ' ';
772     } else {
773         (*out) << std::setw(INDENT_OPCODE) << opcode + ' ' + methodId << ' ';
774     }
775 }
776 
DumpOpcode(std::ostream * out) const777 void InitStringInst::DumpOpcode(std::ostream *out) const
778 {
779     auto graph = GetBasicBlock()->GetGraph();
780     auto allocator = graph->GetLocalAllocator();
781     const auto &adapter = allocator->Adapter();
782     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
783     if (IsFromString()) {
784         ArenaString mode(" FromString", adapter);
785         (*out) << std::setw(INDENT_OPCODE) << opcode + mode << ' ';
786     } else {
787         ASSERT(IsFromCharArray());
788         ArenaString mode(" FromCharArray", adapter);
789         (*out) << std::setw(INDENT_OPCODE) << opcode + mode << ' ';
790     }
791 }
792 
DumpOpcode(std::ostream * out) const793 void CallInst::DumpOpcode(std::ostream *out) const
794 {
795     auto graph = GetBasicBlock()->GetGraph();
796     auto allocator = graph->GetLocalAllocator();
797     const auto &adapter = allocator->Adapter();
798     ArenaString space(" ", adapter);
799     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
800     ArenaString inlined(IsInlined() ? ".Inlined " : " ", adapter);
801     ArenaString methodId(ToArenaString(GetCallMethodId(), allocator));
802     if (!IsUnresolved() && GetCallMethod() != nullptr) {
803         ArenaString method(graph->GetRuntime()->GetMethodFullName(GetCallMethod()), adapter);
804         (*out) << std::setw(INDENT_OPCODE) << opcode + inlined + methodId + ' ' + method << ' ';
805     } else {
806         (*out) << std::setw(INDENT_OPCODE) << opcode + inlined + methodId << ' ';
807     }
808 }
809 
DumpOpcode(std::ostream * out) const810 void DeoptimizeInst::DumpOpcode(std::ostream *out) const
811 {
812     auto graph = GetBasicBlock()->GetGraph();
813     auto allocator = graph->GetLocalAllocator();
814     const auto &adapter = allocator->Adapter();
815     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
816     ArenaString type(DeoptimizeTypeToString(GetDeoptimizeType()), adapter);
817     (*out) << std::setw(INDENT_OPCODE) << opcode + ArenaString(" ", adapter) + type << ' ';
818 }
819 
DumpOpcode(std::ostream * out) const820 void DeoptimizeIfInst::DumpOpcode(std::ostream *out) const
821 {
822     auto graph = GetBasicBlock()->GetGraph();
823     auto allocator = graph->GetLocalAllocator();
824     const auto &adapter = allocator->Adapter();
825     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
826     ArenaString type(DeoptimizeTypeToString(GetDeoptimizeType()), adapter);
827     (*out) << std::setw(INDENT_OPCODE) << opcode + ArenaString(" ", adapter) + type << ' ';
828 }
829 
DumpOpcode(std::ostream * out) const830 void DeoptimizeCompareInst::DumpOpcode(std::ostream *out) const
831 {
832     auto graph = GetBasicBlock()->GetGraph();
833     auto allocator = graph->GetLocalAllocator();
834     const auto &adapter = allocator->Adapter();
835     ArenaString opcode(ArenaString(GetOpcodeString(GetOpcode()), adapter).append(" "));
836     ArenaString cc(ArenaString(GetCondCodeToString(GetCc(), allocator), adapter).append(" "));
837     ArenaString type(ArenaString(DeoptimizeTypeToString(GetDeoptimizeType()), adapter).append(" "));
838     ArenaString cmpType(ArenaString(DataType::ToString(GetOperandsType()), adapter).append(" "));
839     (*out) << std::setw(INDENT_OPCODE) << opcode.append(cc).append(cmpType).append(type);
840 }
841 
DumpOpcode(std::ostream * out) const842 void DeoptimizeCompareImmInst::DumpOpcode(std::ostream *out) const
843 {
844     auto graph = GetBasicBlock()->GetGraph();
845     auto allocator = graph->GetLocalAllocator();
846     const auto &adapter = allocator->Adapter();
847     ArenaString opcode(ArenaString(GetOpcodeString(GetOpcode()), adapter).append(" "));
848     ArenaString cc(ArenaString(GetCondCodeToString(GetCc(), allocator), adapter).append(" "));
849     ArenaString type(ArenaString(DeoptimizeTypeToString(GetDeoptimizeType()), adapter).append(" "));
850     ArenaString cmpType(ArenaString(DataType::ToString(GetOperandsType()), adapter).append(" "));
851     (*out) << std::setw(INDENT_OPCODE) << opcode.append(cc).append(cmpType).append(type);
852 }
853 
DumpInputs(std::ostream * out) const854 bool DeoptimizeCompareImmInst::DumpInputs(std::ostream *out) const
855 {
856     Inst::DumpInputs(out);
857     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
858     return true;
859 }
860 
DumpInputs(std::ostream * out) const861 bool BoundsCheckInstI::DumpInputs(std::ostream *out) const
862 {
863     Inst *lenInput = GetInput(0).GetInst();
864     Inst *ssInput = GetInput(1).GetInst();
865     auto graph = GetBasicBlock()->GetGraph();
866     auto allocator = graph->GetLocalAllocator();
867 
868     (*out) << InstId(lenInput, allocator);
869     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
870     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
871     (*out) << ", " << InstId(ssInput, allocator);
872     return true;
873 }
874 
DumpInputs(std::ostream * out) const875 bool StoreInstI::DumpInputs(std::ostream *out) const
876 {
877     Inst *arrInput = GetInput(0).GetInst();
878     Inst *ssInput = GetInput(1).GetInst();
879     auto graph = GetBasicBlock()->GetGraph();
880     auto arch = graph->GetArch();
881     const auto &allocator = graph->GetLocalAllocator();
882 
883     (*out) << InstId(arrInput, allocator);
884     PrintIfValidLocation(GetLocation(0), arch, out, true);
885     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
886     (*out) << ", " << InstId(ssInput, allocator);
887     PrintIfValidLocation(GetLocation(1), arch, out, true);
888     return true;
889 }
890 
DumpInputs(std::ostream * out) const891 bool StoreMemInstI::DumpInputs(std::ostream *out) const
892 {
893     Inst *arrInput = GetInput(0).GetInst();
894     Inst *ssInput = GetInput(1).GetInst();
895     auto graph = GetBasicBlock()->GetGraph();
896     const auto &allocator = graph->GetLocalAllocator();
897 
898     (*out) << InstId(arrInput, allocator);
899     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
900     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
901     (*out) << ", " << InstId(ssInput, allocator);
902     return true;
903 }
904 
DumpInputs(std::ostream * out) const905 bool LoadInstI::DumpInputs(std::ostream *out) const
906 {
907     Inst::DumpInputs(out);
908     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
909     return true;
910 }
911 
DumpInputs(std::ostream * out) const912 bool LoadMemInstI::DumpInputs(std::ostream *out) const
913 {
914     Inst::DumpInputs(out);
915     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
916     return true;
917 }
918 
DumpInputs(std::ostream * out) const919 bool LoadMemInst::DumpInputs(std::ostream *out) const
920 {
921     Inst::DumpInputs(out);
922     if (GetScale() != 0) {
923         (*out) << " Scale " << GetScale();
924     }
925     return true;
926 }
927 
DumpInputs(std::ostream * out) const928 bool StoreMemInst::DumpInputs(std::ostream *out) const
929 {
930     Inst::DumpInputs(out);
931     if (GetScale() != 0) {
932         (*out) << " Scale " << GetScale();
933     }
934     return true;
935 }
936 
DumpInputs(std::ostream * out) const937 bool LoadPairPartInst::DumpInputs(std::ostream *out) const
938 {
939     Inst *arrInput = GetInput(0).GetInst();
940     auto graph = GetBasicBlock()->GetGraph();
941     const auto &allocator = graph->GetLocalAllocator();
942 
943     (*out) << InstId(arrInput, allocator);
944     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
945     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
946     return true;
947 }
948 
DumpInputs(std::ostream * out) const949 bool LoadArrayPairInst::DumpInputs(std::ostream *out) const
950 {
951     Inst::DumpInputs(out);
952     if (GetImm() > 0) {
953         (*out) << ", 0x" << std::hex << GetImm() << std::dec;
954     }
955     return true;
956 }
957 
DumpInputs(std::ostream * out) const958 bool LoadArrayPairInstI::DumpInputs(std::ostream *out) const
959 {
960     Inst *arrInput = GetInput(0).GetInst();
961     auto graph = GetBasicBlock()->GetGraph();
962     const auto &allocator = graph->GetLocalAllocator();
963     (*out) << InstId(arrInput, allocator);
964     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
965     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
966     return true;
967 }
968 
DumpInputs(std::ostream * out) const969 bool StoreArrayPairInst::DumpInputs(std::ostream *out) const
970 {
971     Inst::DumpInputs(out);
972     if (GetImm() > 0) {
973         (*out) << ", 0x" << std::hex << GetImm() << std::dec;
974     }
975     return true;
976 }
977 
DumpInputs(std::ostream * out) const978 bool StoreArrayPairInstI::DumpInputs(std::ostream *out) const
979 {
980     Inst *arrInput = GetInput(0).GetInst();
981     Inst *fssInput = GetInput(1).GetInst();
982     constexpr auto IMM_2 = 2;
983     Inst *sssInput = GetInput(IMM_2).GetInst();
984     auto graph = GetBasicBlock()->GetGraph();
985     auto allocator = graph->GetLocalAllocator();
986 
987     (*out) << InstId(arrInput, allocator);
988     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
989     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
990     (*out) << ", " << InstId(fssInput, allocator);
991     (*out) << ", " << InstId(sssInput, allocator);
992     return true;
993 }
994 
DumpInputs(std::ostream * out) const995 bool ReturnInstI::DumpInputs(std::ostream *out) const
996 {
997     (*out) << "0x" << std::hex << GetImm() << std::dec;
998     return true;
999 }
1000 
DumpImms(std::ostream * out) const1001 void IntrinsicInst::DumpImms(std::ostream *out) const
1002 {
1003     if (!HasImms()) {
1004         return;
1005     }
1006 
1007     const auto &imms = GetImms();
1008     ASSERT(!imms.empty());
1009     (*out) << "0x" << std::hex << imms[0U];
1010     for (size_t i = 1U; i < imms.size(); ++i) {
1011         (*out) << ", 0x" << imms[i];
1012     }
1013     (*out) << ' ' << std::dec;
1014 }
1015 
DumpInputs(std::ostream * out) const1016 bool IntrinsicInst::DumpInputs(std::ostream *out) const
1017 {
1018     DumpImms(out);
1019     return Inst::DumpInputs(out);
1020 }
1021 
DumpBytecode(std::ostream * out) const1022 void Inst::DumpBytecode(std::ostream *out) const
1023 {
1024     if (pc_ != INVALID_PC) {
1025         auto graph = GetBasicBlock()->GetGraph();
1026         auto byteCode = graph->GetRuntime()->GetBytecodeString(graph->GetMethod(), pc_);
1027         if (!byteCode.empty()) {
1028             (*out) << byteCode << '\n';
1029         }
1030     }
1031 }
1032 
1033 #ifdef PANDA_COMPILER_DEBUG_INFO
DumpSourceLine(std::ostream * out) const1034 void Inst::DumpSourceLine(std::ostream *out) const
1035 {
1036     auto currentMethod = GetCurrentMethod();
1037     auto pc = GetPc();
1038     if (currentMethod != nullptr && pc != INVALID_PC) {
1039         auto line = GetBasicBlock()->GetGraph()->GetRuntime()->GetLineNumberAndSourceFile(currentMethod, pc);
1040         (*out) << " (" << line << " )";
1041     }
1042 }
1043 #endif  // PANDA_COMPILER_DEBUG_INFO
1044 
Dump(std::ostream * out,bool newLine) const1045 void Inst::Dump(std::ostream *out, bool newLine) const
1046 {
1047     if (g_options.IsCompilerDumpCompact() && IsSaveState()) {
1048         return;
1049     }
1050     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
1051     // Id
1052     (*out) << std::setw(INDENT_ID) << std::setfill(' ') << std::right
1053            << IdToString(id_, allocator, false, IsPhi()) + '.';
1054     // Type
1055     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
1056     (*out) << std::setw(INDENT_TYPE) << std::left << DataType::ToString(GetType());
1057     // opcode
1058     DumpOpcode(out);
1059     auto operandsPos = out->tellp();
1060     // inputs
1061     bool hasInput = DumpInputs(out);
1062     // users
1063     if (hasInput && !GetUsers().Empty()) {
1064         (*out) << " -> ";
1065     }
1066     DumpUsers(this, out);
1067     // Align rest of the instruction info
1068     static constexpr auto ALIGN_BUF_SIZE = 64;
1069     if (auto posDiff = out->tellp() - operandsPos; posDiff < ALIGN_BUF_SIZE) {
1070         posDiff = ALIGN_BUF_SIZE - posDiff;
1071         static std::array<char, ALIGN_BUF_SIZE + 1> spaceBuf;
1072         if (spaceBuf[0] != ' ') {
1073             std::fill(spaceBuf.begin(), spaceBuf.end(), ' ');
1074         }
1075         spaceBuf[posDiff] = 0;
1076         (*out) << spaceBuf.data();
1077         spaceBuf[posDiff] = ' ';
1078     }
1079     // bytecode pointer
1080     if (pc_ != INVALID_PC && !g_options.IsCompilerDumpCompact()) {
1081         (*out) << ' ' << PcToString(pc_, allocator);
1082     }
1083 #ifdef PANDA_COMPILER_DEBUG_INFO
1084     if (g_options.IsCompilerDumpSourceLine()) {
1085         DumpSourceLine(out);
1086     }
1087 #endif
1088     if (newLine) {
1089         (*out) << '\n';
1090     }
1091     if (g_options.IsCompilerDumpBytecode()) {
1092         DumpBytecode(out);
1093     }
1094     if (GetOpcode() == Opcode::Parameter) {
1095         auto spillFill = static_cast<const ParameterInst *>(this)->GetLocationData();
1096         if (spillFill.DstValue() != INVALID_REG) {
1097             (*out) << sf_data::ToString(spillFill, GetBasicBlock()->GetGraph()->GetArch());
1098             if (newLine) {
1099                 *out << std::endl;
1100             }
1101         }
1102     }
1103 }
1104 
CheckPrintPropsFlag(std::ostream * out,bool * printPropsFlag)1105 void CheckPrintPropsFlag(std::ostream *out, bool *printPropsFlag)
1106 {
1107     if (!(*printPropsFlag)) {
1108         (*out) << "prop: ";
1109         (*printPropsFlag) = true;
1110     } else {
1111         (*out) << ", ";
1112     }
1113 }
1114 
PrintLoopInfo(std::ostream * out,Loop * loop)1115 void PrintLoopInfo(std::ostream *out, Loop *loop)
1116 {
1117     (*out) << "loop" << (loop->IsIrreducible() ? " (irreducible) " : " ") << loop->GetId();
1118     if (loop->GetDepth() > 0) {
1119         (*out) << ", depth " << loop->GetDepth();
1120     }
1121 }
1122 
BlockProps(const BasicBlock * block,std::ostream * out)1123 void BlockProps(const BasicBlock *block, std::ostream *out)
1124 {
1125     bool printPropsFlag = false;
1126     if (block->IsStartBlock()) {
1127         CheckPrintPropsFlag(out, &printPropsFlag);
1128         (*out) << "start";
1129     }
1130     if (block->IsEndBlock()) {
1131         CheckPrintPropsFlag(out, &printPropsFlag);
1132         (*out) << "end";
1133     }
1134     if (block->IsLoopPreHeader()) {
1135         CheckPrintPropsFlag(out, &printPropsFlag);
1136         (*out) << "prehead";
1137     }
1138     if (block->IsLoopValid() && !block->GetLoop()->IsRoot()) {
1139         if (block->IsLoopHeader()) {
1140             CheckPrintPropsFlag(out, &printPropsFlag);
1141             (*out) << "head";
1142         }
1143         CheckPrintPropsFlag(out, &printPropsFlag);
1144         PrintLoopInfo(out, block->GetLoop());
1145     }
1146     if (block->IsTryBegin()) {
1147         CheckPrintPropsFlag(out, &printPropsFlag);
1148         (*out) << "try_begin (id " << block->GetTryId() << ")";
1149     }
1150     if (block->IsTry()) {
1151         CheckPrintPropsFlag(out, &printPropsFlag);
1152         (*out) << "try (id " << block->GetTryId() << ")";
1153     }
1154     if (block->IsTryEnd()) {
1155         CheckPrintPropsFlag(out, &printPropsFlag);
1156         (*out) << "try_end (id " << block->GetTryId() << ")";
1157     }
1158     if (block->IsCatchBegin()) {
1159         CheckPrintPropsFlag(out, &printPropsFlag);
1160         (*out) << "catch_begin";
1161     }
1162     if (block->IsCatch()) {
1163         CheckPrintPropsFlag(out, &printPropsFlag);
1164         (*out) << "catch";
1165     }
1166     if (block->IsCatchEnd()) {
1167         CheckPrintPropsFlag(out, &printPropsFlag);
1168         (*out) << "catch_end";
1169     }
1170 
1171     if (block->GetGuestPc() != INVALID_PC) {
1172         CheckPrintPropsFlag(out, &printPropsFlag);
1173         (*out) << PcToString(block->GetGuestPc(), block->GetGraph()->GetLocalAllocator());
1174     }
1175     if (printPropsFlag) {
1176         (*out) << std::endl;
1177     }
1178 }
1179 
Dump(std::ostream * out) const1180 void BasicBlock::Dump(std::ostream *out) const
1181 {
1182     const auto &allocator = GetGraph()->GetLocalAllocator();
1183     (*out) << "BB " << IdToString(bbId_, allocator);
1184     // predecessors
1185     if (!preds_.empty()) {
1186         (*out) << "  ";
1187         BBDependence("preds", preds_, out, allocator);
1188     }
1189     (*out) << '\n';
1190     // properties
1191     BlockProps(this, out);
1192     // instructions
1193     for (auto inst : this->AllInsts()) {
1194         inst->Dump(out);
1195     }
1196     // successors
1197     if (!succs_.empty()) {
1198         BBDependence("succs", succs_, out, allocator);
1199         (*out) << '\n';
1200     }
1201 }
1202 
Dump(std::ostream * out) const1203 void Graph::Dump(std::ostream *out) const
1204 {
1205     const auto &runtime = GetRuntime();
1206     const auto &method = GetMethod();
1207     const auto &adapter = GetLocalAllocator()->Adapter();
1208     ArenaString returnType(DataType::ToString(runtime->GetMethodReturnType(method)), adapter);
1209     (*out) << "Method: " << runtime->GetMethodFullName(method, true) << " " << method << std::endl;
1210     if (IsOsrMode()) {
1211         (*out) << "OSR mode\n";
1212     }
1213     (*out) << std::endl;
1214 
1215     auto &blocks = GetAnalysis<LinearOrder>().IsValid() ? GetBlocksLinearOrder() : GetBlocksRPO();
1216     for (const auto &blockIt : blocks) {
1217         if (!blockIt->GetPredsBlocks().empty() || !blockIt->GetSuccsBlocks().empty()) {
1218             blockIt->Dump(out);
1219             (*out) << '\n';
1220         } else {
1221             // to print the dump before cleanup, still unconnected nodes exist
1222             (*out) << "BB " << blockIt->GetId() << " is unconnected\n\n";
1223         }
1224     }
1225 }
1226 }  // namespace panda::compiler
1227