• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 "optimizer/analysis/linear_order.h"
25 #include "optimizer/analysis/rpo.h"
26 #include "optimizer/analysis/loop_analyzer.h"
27 #include "optimizer/code_generator/target_info.h"
28 #include "dump.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 v_reg,bool is_phi)50 ArenaString IdToString(uint32_t id, ArenaAllocator *allocator, bool v_reg, bool is_phi)
51 {
52     ArenaString reg(v_reg ? "v" : "", allocator->Adapter());
53     ArenaString phi(is_phi ? "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 with_brackets=false)58 void PrintIfValidLocation(Location location, Arch arch, std::ostream *out, bool with_brackets = false)
59 {
60     if (!location.IsInvalid() && !location.IsUnallocatedRegister()) {
61         auto string = location.ToString(arch);
62         if (with_brackets) {
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() && 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(), arch, out);
98     }
99     bool fl_first = true;
100     for (auto &node_inst : inst->GetUsers()) {
101         auto user = node_inst.GetInst();
102         (*out) << (fl_first ? "(" : ", ") << InstId(user, allocator);
103         if (fl_first) {
104             fl_first = false;
105         }
106     }
107     if (!fl_first) {
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 out_string;
150     out_string << "bc: 0x" << std::setfill('0') << std::setw(HEX_PTR_SIZE) << std::hex << pc;
151     return ArenaString(out_string.str(), allocator->Adapter());
152 }
153 
BBDependence(const char * type,const ArenaVector<BasicBlock * > & bb_vector,std::ostream * out,ArenaAllocator * allocator)154 void BBDependence(const char *type, const ArenaVector<BasicBlock *> &bb_vector, std::ostream *out,
155                   ArenaAllocator *allocator)
156 {
157     bool fl_first = true;
158     (*out) << type << ": [";
159     for (auto block_it : bb_vector) {
160         (*out) << (fl_first ? "" : ", ") << "bb " << BBId(block_it, allocator);
161         if (fl_first) {
162             fl_first = false;
163         }
164     }
165     (*out) << ']';
166 }
167 
FieldToString(RuntimeInterface * runtime,RuntimeInterface::FieldPtr field,ArenaAllocator * allocator)168 ArenaString FieldToString(RuntimeInterface *runtime, RuntimeInterface::FieldPtr field, ArenaAllocator *allocator)
169 {
170     const auto &adapter = allocator->Adapter();
171     if (!runtime->HasFieldMetadata(field)) {
172         auto offset = runtime->GetFieldOffset(field);
173         return ArenaString("Unknown.Unknown", adapter) + ArenaString(std::to_string(offset), adapter);
174     }
175 
176     ArenaString dot(".", adapter);
177     ArenaString cls_name(runtime->GetClassName(runtime->GetClassForField(field)), adapter);
178     ArenaString field_name(runtime->GetFieldName(field), adapter);
179     return cls_name + dot + field_name;
180 }
181 
DumpTypedFieldOpcode(std::ostream * out,Opcode opcode,uint32_t type_id,const ArenaString & field_name,ArenaAllocator * allocator)182 void DumpTypedFieldOpcode(std::ostream *out, Opcode opcode, uint32_t type_id, const ArenaString &field_name,
183                           ArenaAllocator *allocator)
184 {
185     const auto &adapter = allocator->Adapter();
186     ArenaString space(" ", adapter);
187     ArenaString opc(GetOpcodeString(opcode), adapter);
188     ArenaString id(IdToString(type_id, allocator), adapter);
189     (*out) << std::setw(INDENT_OPCODE) << opc + space + id + space + field_name + space;
190 }
191 
DumpTypedOpcode(std::ostream * out,Opcode opcode,uint32_t type_id,ArenaAllocator * allocator)192 void DumpTypedOpcode(std::ostream *out, Opcode opcode, uint32_t type_id, ArenaAllocator *allocator)
193 {
194     ArenaString space(" ", allocator->Adapter());
195     ArenaString opc(GetOpcodeString(opcode), allocator->Adapter());
196     ArenaString id(IdToString(type_id, allocator), allocator->Adapter());
197     (*out) << std::setw(INDENT_OPCODE) << opc + space + id;
198 }
199 
DumpInputs(std::ostream * out) const200 bool Inst::DumpInputs(std::ostream *out) const
201 {
202     const auto &allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
203     auto arch = GetBasicBlock()->GetGraph()->GetArch();
204     bool fl_first = true;
205     unsigned i = 0;
206     for (auto node_inst : GetInputs()) {
207         Inst *input = node_inst.GetInst();
208         (*out) << (fl_first ? "" : ", ") << InstId(input, allocator);
209         PrintIfValidLocation(GetLocation(i), arch, out, true);
210         i++;
211         fl_first = false;
212     }
213     return !fl_first;
214 }
215 
DumpInputs(std::ostream * out) const216 bool SaveStateInst::DumpInputs(std::ostream *out) const
217 {
218     const auto &allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
219     const char *sep = "";
220     for (size_t i = 0; i < GetInputsCount(); i++) {
221         (*out) << sep << std::dec << InstId(GetInput(i).GetInst(), allocator);
222         if (GetVirtualRegister(i).IsAccumulator()) {
223             (*out) << "(acc)";
224         } else {
225             (*out) << "(vr" << GetVirtualRegister(i).Value() << ")";
226         }
227         sep = ", ";
228     }
229     if (GetImmediatesCount() > 0) {
230         for (auto imm : *GetImmediates()) {
231             (*out) << sep << std::hex << "0x" << imm.value;
232             if (imm.is_acc) {
233                 (*out) << "(acc)";
234             } else {
235                 (*out) << std::dec << "(vr" << imm.vreg << ")";
236             }
237             sep = ", ";
238         }
239     }
240     if (GetCallerInst() != nullptr) {
241         (*out) << sep << "caller=" << GetCallerInst()->GetId();
242     }
243     return true;
244 }
245 
DumpInputs(std::ostream * out) const246 bool BinaryImmOperation::DumpInputs(std::ostream *out) const
247 {
248     Inst::DumpInputs(out);
249     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
250     return true;
251 }
252 
DumpInputs(std::ostream * out) const253 bool BinaryShiftedRegisterOperation::DumpInputs(std::ostream *out) const
254 {
255     Inst::DumpInputs(out);
256     (*out) << ", " << GetShiftTypeStr(GetShiftType()) << " 0x" << std::hex << GetImm() << std::dec;
257     return true;
258 }
259 
DumpInputs(std::ostream * out) const260 bool UnaryShiftedRegisterOperation::DumpInputs(std::ostream *out) const
261 {
262     Inst::DumpInputs(out);
263     (*out) << ", " << GetShiftTypeStr(GetShiftType()) << " 0x" << std::hex << GetImm() << std::dec;
264     return true;
265 }
266 
DumpInputs(std::ostream * out) const267 bool SelectImmInst::DumpInputs(std::ostream *out) const
268 {
269     Inst::DumpInputs(out);
270     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
271     return true;
272 }
273 
DumpInputs(std::ostream * out) const274 bool IfImmInst::DumpInputs(std::ostream *out) const
275 {
276     Inst::DumpInputs(out);
277     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
278     return true;
279 }
280 
DumpInputs(std::ostream * out) const281 bool PhiInst::DumpInputs(std::ostream *out) const
282 {
283     const auto &allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
284     bool fl_first = true;
285     for (size_t idx = 0; idx < GetInputsCount(); ++idx) {
286         Inst *input = GetInput(idx).GetInst();
287         auto block = GetPhiInputBb(idx);
288         (*out) << (fl_first ? "" : ", ") << InstId(input, allocator) << "(bb" << BBId(block, allocator) << ")";
289         if (fl_first) {
290             fl_first = false;
291         }
292     }
293     return !fl_first;
294 }
295 
DumpInputs(std::ostream * out) const296 bool ConstantInst::DumpInputs(std::ostream *out) const
297 {
298     switch (GetType()) {
299         case DataType::Type::REFERENCE:
300         case DataType::Type::BOOL:
301         case DataType::Type::UINT8:
302         case DataType::Type::INT8:
303         case DataType::Type::UINT16:
304         case DataType::Type::INT16:
305         case DataType::Type::UINT32:
306         case DataType::Type::INT32:
307         case DataType::Type::UINT64:
308         case DataType::Type::INT64:
309             (*out) << "0x" << std::hex << GetIntValue() << std::dec;
310             break;
311         case DataType::Type::FLOAT32:
312             (*out) << GetFloatValue();
313             break;
314         case DataType::Type::FLOAT64:
315             (*out) << GetDoubleValue();
316             break;
317         case DataType::Type::ANY:
318             (*out) << "0x" << std::hex << GetRawValue();
319             break;
320         default:
321             UNREACHABLE();
322     }
323     return true;
324 }
325 
DumpInputs(std::ostream * out) const326 bool SpillFillInst::DumpInputs(std::ostream *out) const
327 {
328     bool first = true;
329     for (auto spill_fill : GetSpillFills()) {
330         if (!first) {
331             (*out) << ", ";
332         }
333         first = false;
334         (*out) << sf_data::ToString(spill_fill, GetBasicBlock()->GetGraph()->GetArch());
335     }
336     return true;
337 }
338 
DumpInputs(std::ostream * out) const339 bool ParameterInst::DumpInputs(std::ostream *out) const
340 {
341     (*out) << "arg " << IdToString(GetArgNumber(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
342     return true;
343 }
344 
DumpOpcode(std::ostream * out) const345 void CompareInst::DumpOpcode(std::ostream *out) const
346 {
347     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
348     const auto &adapter = allocator->Adapter();
349     ArenaString space(" ", adapter);
350     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
351     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
352     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
353     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
354 }
355 
DumpOpcodeAnyTypeMixin(std::ostream & out,const Inst * inst)356 static void DumpOpcodeAnyTypeMixin(std::ostream &out, const Inst *inst)
357 {
358     const auto *mixin_inst = static_cast<const AnyTypeMixin<FixedInputsInst1> *>(inst);
359     ASSERT(mixin_inst != nullptr);
360     auto allocator = mixin_inst->GetBasicBlock()->GetGraph()->GetLocalAllocator();
361     const auto &adapter = allocator->Adapter();
362     ArenaString space(" ", adapter);
363     ArenaString opcode(GetOpcodeString(mixin_inst->GetOpcode()), adapter);
364     ArenaString any_base_type(AnyTypeTypeToString(mixin_inst->GetAnyType()), adapter);
365     out << std::setw(INDENT_OPCODE) << opcode + space + any_base_type + space;
366 }
367 
DumpOpcode(std::ostream * out) const368 void CompareAnyTypeInst::DumpOpcode(std::ostream *out) const
369 {
370     DumpOpcodeAnyTypeMixin(*out, this);
371 }
372 
DumpOpcode(std::ostream * out) const373 void CastAnyTypeValueInst::DumpOpcode(std::ostream *out) const
374 {
375     DumpOpcodeAnyTypeMixin(*out, this);
376 }
377 
DumpOpcode(std::ostream * out) const378 void CastValueToAnyTypeInst::DumpOpcode(std::ostream *out) const
379 {
380     DumpOpcodeAnyTypeMixin(*out, this);
381 }
382 
DumpOpcode(std::ostream * out) const383 void AnyTypeCheckInst::DumpOpcode(std::ostream *out) const
384 {
385     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
386     const auto &adapter = allocator->Adapter();
387     ArenaString space(" ", adapter);
388     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
389     ArenaString any_base_type(AnyTypeTypeToString(GetAnyType()), adapter);
390     (*out) << std::setw(INDENT_OPCODE) << opcode + space + any_base_type + space;
391 }
392 
DumpOpcode(std::ostream * out) const393 void ClassImmediateInst::DumpOpcode(std::ostream *out) const
394 {
395     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
396     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
397     ArenaString open("(", adapter);
398     ArenaString close(")", adapter);
399     ArenaString class_name(GetBasicBlock()->GetGraph()->GetRuntime()->GetClassName(GetClassPtr()), adapter);
400     (*out) << std::setw(INDENT_OPCODE) << opcode + open + class_name + close;
401 }
402 
DumpOpcode(std::ostream * out) const403 void SelectInst::DumpOpcode(std::ostream *out) const
404 {
405     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
406     const auto &adapter = allocator->Adapter();
407     ArenaString space(" ", adapter);
408     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
409     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
410     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
411     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
412 }
413 
DumpOpcode(std::ostream * out) const414 void SelectImmInst::DumpOpcode(std::ostream *out) const
415 {
416     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
417     const auto &adapter = allocator->Adapter();
418     ArenaString space(" ", adapter);
419     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
420     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
421     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
422     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
423 }
424 
DumpOpcode(std::ostream * out) const425 void IfInst::DumpOpcode(std::ostream *out) const
426 {
427     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
428     const auto &adapter = allocator->Adapter();
429     ArenaString space(" ", adapter);
430     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
431     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
432     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
433     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
434 }
435 
DumpOpcode(std::ostream * out) const436 void IfImmInst::DumpOpcode(std::ostream *out) const
437 {
438     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
439     const auto &adapter = allocator->Adapter();
440     ArenaString space(" ", adapter);
441     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
442     ArenaString cc(GetCondCodeToString(GetCc(), allocator), adapter);
443     ArenaString type(DataType::ToString(GetOperandsType()), adapter);
444     (*out) << std::setw(INDENT_OPCODE) << opcode + space + cc + space + type;
445 }
446 
DumpOpcode(std::ostream * out) const447 void MonitorInst::DumpOpcode(std::ostream *out) const
448 {
449     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
450     ArenaString suffix(IsExit() ? ".Exit" : ".Entry", adapter);
451     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
452     (*out) << std::setw(INDENT_OPCODE) << opcode + suffix;
453 }
454 
DumpOpcode(std::ostream * out) const455 void CmpInst::DumpOpcode(std::ostream *out) const
456 {
457     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
458     auto type = GetOperandsType();
459     ArenaString suffix = ArenaString(" ", adapter) + ArenaString(DataType::ToString(type), adapter);
460     if (IsFloatType(type)) {
461         (*out) << std::setw(INDENT_OPCODE) << ArenaString(IsFcmpg() ? "Fcmpg" : "Fcmpl", adapter) + suffix;
462     } else if (IsTypeSigned(type)) {
463         (*out) << std::setw(INDENT_OPCODE) << ArenaString("Cmp", adapter) + ArenaString(" ", adapter) + suffix;
464     } else {
465         (*out) << std::setw(INDENT_OPCODE) << ArenaString("Ucmp", adapter) + suffix;
466     }
467 }
468 
DumpOpcode(std::ostream * out) const469 void CastInst::DumpOpcode(std::ostream *out) const
470 {
471     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
472     ArenaString space(" ", adapter);
473     (*out) << std::setw(INDENT_OPCODE)
474            << ArenaString(GetOpcodeString(GetOpcode()), adapter) + space +
475                   ArenaString(DataType::ToString(GetOperandsType()), adapter);
476 }
477 
DumpOpcode(std::ostream * out) const478 void NewObjectInst::DumpOpcode(std::ostream *out) const
479 {
480     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
481 }
482 
DumpOpcode(std::ostream * out) const483 void NewArrayInst::DumpOpcode(std::ostream *out) const
484 {
485     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
486 }
487 
DumpOpcode(std::ostream * out) const488 void LoadConstArrayInst::DumpOpcode(std::ostream *out) const
489 {
490     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
491 }
492 
DumpOpcode(std::ostream * out) const493 void FillConstArrayInst::DumpOpcode(std::ostream *out) const
494 {
495     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
496 }
497 
DumpOpcode(std::ostream * out) const498 void LoadObjectInst::DumpOpcode(std::ostream *out) const
499 {
500     auto graph = GetBasicBlock()->GetGraph();
501     auto field_name = FieldToString(graph->GetRuntime(), GetObjField(), graph->GetLocalAllocator());
502     DumpTypedFieldOpcode(out, GetOpcode(), GetTypeId(), field_name, graph->GetLocalAllocator());
503 }
504 
DumpOpcode(std::ostream * out) const505 void LoadMemInst::DumpOpcode(std::ostream *out) const
506 {
507     DumpTypedOpcode(out, GetOpcode(), GetType(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
508 }
509 
DumpOpcode(std::ostream * out) const510 void UnresolvedLoadObjectInst::DumpOpcode(std::ostream *out) const
511 {
512     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
513 }
514 
DumpOpcode(std::ostream * out) const515 void StoreObjectInst::DumpOpcode(std::ostream *out) const
516 {
517     auto graph = GetBasicBlock()->GetGraph();
518     auto field_name = FieldToString(graph->GetRuntime(), GetObjField(), graph->GetLocalAllocator());
519     DumpTypedFieldOpcode(out, GetOpcode(), GetTypeId(), field_name, graph->GetLocalAllocator());
520 }
521 
DumpOpcode(std::ostream * out) const522 void UnresolvedStoreObjectInst::DumpOpcode(std::ostream *out) const
523 {
524     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
525 }
526 
DumpOpcode(std::ostream * out) const527 void StoreMemInst::DumpOpcode(std::ostream *out) const
528 {
529     DumpTypedOpcode(out, GetOpcode(), GetType(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
530 }
531 
DumpOpcode(std::ostream * out) const532 void LoadStaticInst::DumpOpcode(std::ostream *out) const
533 {
534     auto graph = GetBasicBlock()->GetGraph();
535     auto field_name = FieldToString(graph->GetRuntime(), GetObjField(), graph->GetLocalAllocator());
536     DumpTypedFieldOpcode(out, GetOpcode(), GetTypeId(), field_name, graph->GetLocalAllocator());
537 }
538 
DumpOpcode(std::ostream * out) const539 void UnresolvedLoadStaticInst::DumpOpcode(std::ostream *out) const
540 {
541     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
542 }
543 
DumpOpcode(std::ostream * out) const544 void StoreStaticInst::DumpOpcode(std::ostream *out) const
545 {
546     auto graph = GetBasicBlock()->GetGraph();
547     auto field_name = FieldToString(graph->GetRuntime(), GetObjField(), graph->GetLocalAllocator());
548     DumpTypedFieldOpcode(out, GetOpcode(), GetTypeId(), field_name, graph->GetLocalAllocator());
549 }
550 
DumpOpcode(std::ostream * out) const551 void UnresolvedStoreStaticInst::DumpOpcode(std::ostream *out) const
552 {
553     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
554 }
555 
DumpOpcode(std::ostream * out) const556 void LoadFromPool::DumpOpcode(std::ostream *out) const
557 {
558     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
559 }
560 
DumpOpcode(std::ostream * out) const561 void ClassInst::DumpOpcode(std::ostream *out) const
562 {
563     auto graph = GetBasicBlock()->GetGraph();
564     auto allocator = graph->GetLocalAllocator();
565     const auto &adapter = allocator->Adapter();
566 
567     ArenaString space(" ", adapter);
568     ArenaString qt("'", adapter);
569     ArenaString opc(GetOpcodeString(GetOpcode()), adapter);
570     ArenaString class_name(GetClass() == nullptr ? ArenaString("", adapter)
571                                                  : ArenaString(graph->GetRuntime()->GetClassName(GetClass()), adapter));
572     (*out) << std::setw(INDENT_OPCODE) << opc + space + qt + class_name + qt << " ";
573 }
574 
DumpOpcode(std::ostream * out) const575 void CheckCastInst::DumpOpcode(std::ostream *out) const
576 {
577     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
578 }
579 
DumpOpcode(std::ostream * out) const580 void IsInstanceInst::DumpOpcode(std::ostream *out) const
581 {
582     DumpTypedOpcode(out, GetOpcode(), GetTypeId(), GetBasicBlock()->GetGraph()->GetLocalAllocator());
583 }
584 
DumpOpcode(std::ostream * out) const585 void IntrinsicInst::DumpOpcode(std::ostream *out) const
586 {
587     const auto &adapter = GetBasicBlock()->GetGraph()->GetLocalAllocator()->Adapter();
588     ArenaString intrinsic(IsBuiltin() ? ArenaString("BuiltinIntrinsic.", adapter) : ArenaString("Intrinsic.", adapter));
589     ArenaString opcode(GetIntrinsicName(intrinsic_id_), adapter);
590     (*out) << std::setw(INDENT_OPCODE) << intrinsic + opcode << " ";
591 }
592 
DumpOpcode(std::ostream * out) const593 void Inst::DumpOpcode(std::ostream *out) const
594 {
595     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
596     (*out) << std::setw(INDENT_OPCODE) << GetOpcodeString(opcode_);
597 }
598 
DumpOpcode(std::ostream * out) const599 void CallInst::DumpOpcode(std::ostream *out) const
600 {
601     auto graph = GetBasicBlock()->GetGraph();
602     auto allocator = graph->GetLocalAllocator();
603     const auto &adapter = allocator->Adapter();
604     ArenaString space(" ", adapter);
605     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
606     ArenaString inlined(IsInlined() ? ".Inlined " : " ", adapter);
607     ArenaString method_id(ToArenaString(GetCallMethodId(), allocator));
608     if (!IsUnresolved() && GetCallMethod() != nullptr) {
609         ArenaString method(graph->GetRuntime()->GetMethodFullName(GetCallMethod()), adapter);
610         (*out) << std::setw(INDENT_OPCODE) << opcode + inlined + method_id + ' ' + method << ' ';
611     } else {
612         (*out) << std::setw(INDENT_OPCODE) << opcode + inlined + method_id << ' ';
613     }
614 }
615 
DumpOpcode(std::ostream * out) const616 void DeoptimizeInst::DumpOpcode(std::ostream *out) const
617 {
618     auto graph = GetBasicBlock()->GetGraph();
619     auto allocator = graph->GetLocalAllocator();
620     const auto &adapter = allocator->Adapter();
621     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
622     ArenaString type(DeoptimizeTypeToString(GetDeoptimizeType()), adapter);
623     (*out) << std::setw(INDENT_OPCODE) << opcode + ArenaString(" ", adapter) + type << ' ';
624 }
625 
DumpOpcode(std::ostream * out) const626 void DeoptimizeIfInst::DumpOpcode(std::ostream *out) const
627 {
628     auto graph = GetBasicBlock()->GetGraph();
629     auto allocator = graph->GetLocalAllocator();
630     const auto &adapter = allocator->Adapter();
631     ArenaString opcode(GetOpcodeString(GetOpcode()), adapter);
632     ArenaString type(DeoptimizeTypeToString(GetDeoptimizeType()), adapter);
633     (*out) << std::setw(INDENT_OPCODE) << opcode + ArenaString(" ", adapter) + type << ' ';
634 }
635 
DumpOpcode(std::ostream * out) const636 void DeoptimizeCompareInst::DumpOpcode(std::ostream *out) const
637 {
638     auto graph = GetBasicBlock()->GetGraph();
639     auto allocator = graph->GetLocalAllocator();
640     const auto &adapter = allocator->Adapter();
641     ArenaString opcode(ArenaString(GetOpcodeString(GetOpcode()), adapter).append(" "));
642     ArenaString cc(ArenaString(GetCondCodeToString(GetCc(), allocator), adapter).append(" "));
643     ArenaString type(ArenaString(DeoptimizeTypeToString(GetDeoptimizeType()), adapter).append(" "));
644     ArenaString cmp_type(ArenaString(DataType::ToString(GetOperandsType()), adapter).append(" "));
645     (*out) << std::setw(INDENT_OPCODE) << opcode.append(cc).append(cmp_type).append(type);
646 }
647 
DumpOpcode(std::ostream * out) const648 void DeoptimizeCompareImmInst::DumpOpcode(std::ostream *out) const
649 {
650     auto graph = GetBasicBlock()->GetGraph();
651     auto allocator = graph->GetLocalAllocator();
652     const auto &adapter = allocator->Adapter();
653     ArenaString opcode(ArenaString(GetOpcodeString(GetOpcode()), adapter).append(" "));
654     ArenaString cc(ArenaString(GetCondCodeToString(GetCc(), allocator), adapter).append(" "));
655     ArenaString type(ArenaString(DeoptimizeTypeToString(GetDeoptimizeType()), adapter).append(" "));
656     ArenaString cmp_type(ArenaString(DataType::ToString(GetOperandsType()), adapter).append(" "));
657     (*out) << std::setw(INDENT_OPCODE) << opcode.append(cc).append(cmp_type).append(type);
658 }
659 
DumpInputs(std::ostream * out) const660 bool DeoptimizeCompareImmInst::DumpInputs(std::ostream *out) const
661 {
662     Inst::DumpInputs(out);
663     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
664     return true;
665 }
666 
DumpInputs(std::ostream * out) const667 bool BoundsCheckInstI::DumpInputs(std::ostream *out) const
668 {
669     Inst *len_input = GetInput(0).GetInst();
670     Inst *ss_input = GetInput(1).GetInst();
671     auto graph = GetBasicBlock()->GetGraph();
672     auto allocator = graph->GetLocalAllocator();
673 
674     (*out) << InstId(len_input, allocator);
675     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
676     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
677     (*out) << ", " << InstId(ss_input, allocator);
678     return true;
679 }
680 
DumpInputs(std::ostream * out) const681 bool StoreInstI::DumpInputs(std::ostream *out) const
682 {
683     Inst *arr_input = GetInput(0).GetInst();
684     Inst *ss_input = GetInput(1).GetInst();
685     auto graph = GetBasicBlock()->GetGraph();
686     auto arch = graph->GetArch();
687     const auto &allocator = graph->GetLocalAllocator();
688 
689     (*out) << InstId(arr_input, allocator);
690     PrintIfValidLocation(GetLocation(0), arch, out, true);
691     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
692     (*out) << ", " << InstId(ss_input, allocator);
693     PrintIfValidLocation(GetLocation(1), arch, out, true);
694     return true;
695 }
696 
DumpInputs(std::ostream * out) const697 bool StoreMemInstI::DumpInputs(std::ostream *out) const
698 {
699     Inst *arr_input = GetInput(0).GetInst();
700     Inst *ss_input = GetInput(1).GetInst();
701     auto graph = GetBasicBlock()->GetGraph();
702     const auto &allocator = graph->GetLocalAllocator();
703 
704     (*out) << InstId(arr_input, allocator);
705     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
706     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
707     (*out) << ", " << InstId(ss_input, allocator);
708     return true;
709 }
710 
DumpInputs(std::ostream * out) const711 bool LoadInstI::DumpInputs(std::ostream *out) const
712 {
713     Inst::DumpInputs(out);
714     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
715     return true;
716 }
717 
DumpInputs(std::ostream * out) const718 bool LoadMemInstI::DumpInputs(std::ostream *out) const
719 {
720     Inst::DumpInputs(out);
721     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
722     return true;
723 }
724 
DumpInputs(std::ostream * out) const725 bool LoadMemInst::DumpInputs(std::ostream *out) const
726 {
727     Inst::DumpInputs(out);
728     if (GetScale() != 0) {
729         (*out) << " Scale " << GetScale();
730     }
731     return true;
732 }
733 
DumpInputs(std::ostream * out) const734 bool StoreMemInst::DumpInputs(std::ostream *out) const
735 {
736     Inst::DumpInputs(out);
737     if (GetScale() != 0) {
738         (*out) << " Scale " << GetScale();
739     }
740     return true;
741 }
742 
DumpInputs(std::ostream * out) const743 bool LoadPairPartInst::DumpInputs(std::ostream *out) const
744 {
745     Inst *arr_input = GetInput(0).GetInst();
746     auto graph = GetBasicBlock()->GetGraph();
747     const auto &allocator = graph->GetLocalAllocator();
748 
749     (*out) << InstId(arr_input, allocator);
750     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
751     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
752     return true;
753 }
754 
DumpInputs(std::ostream * out) const755 bool LoadArrayPairInstI::DumpInputs(std::ostream *out) const
756 {
757     Inst *arr_input = GetInput(0).GetInst();
758     auto graph = GetBasicBlock()->GetGraph();
759     const auto &allocator = graph->GetLocalAllocator();
760     (*out) << InstId(arr_input, allocator);
761     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
762     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
763     return true;
764 }
765 
DumpInputs(std::ostream * out) const766 bool StoreArrayPairInstI::DumpInputs(std::ostream *out) const
767 {
768     Inst *arr_input = GetInput(0).GetInst();
769     Inst *fss_input = GetInput(1).GetInst();
770     constexpr auto IMM_2 = 2;
771     Inst *sss_input = GetInput(IMM_2).GetInst();
772     auto graph = GetBasicBlock()->GetGraph();
773     auto allocator = graph->GetLocalAllocator();
774 
775     (*out) << InstId(arr_input, allocator);
776     PrintIfValidLocation(GetLocation(0), graph->GetArch(), out, true);
777     (*out) << ", 0x" << std::hex << GetImm() << std::dec;
778     (*out) << ", " << InstId(fss_input, allocator);
779     (*out) << ", " << InstId(sss_input, allocator);
780     return true;
781 }
782 
DumpInputs(std::ostream * out) const783 bool ReturnInstI::DumpInputs(std::ostream *out) const
784 {
785     (*out) << "0x" << std::hex << GetImm() << std::dec;
786     return true;
787 }
788 
Dump(std::ostream * out,bool new_line) const789 void Inst::Dump(std::ostream *out, bool new_line) const
790 {
791     if (options.IsCompilerDumpCompact() && IsSaveState()) {
792         return;
793     }
794     auto allocator = GetBasicBlock()->GetGraph()->GetLocalAllocator();
795     // Id
796     (*out) << std::setw(INDENT_ID) << std::setfill(' ') << std::right
797            << IdToString(id_, allocator, false, IsPhi()) + '.';
798     // Type
799     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
800     (*out) << std::setw(INDENT_TYPE) << std::left << DataType::ToString(GetType());
801     // opcode
802     DumpOpcode(out);
803     auto operands_pos = out->tellp();
804     // inputs
805     bool has_input = DumpInputs(out);
806     // users
807     if (has_input && !GetUsers().Empty()) {
808         (*out) << " -> ";
809     }
810     DumpUsers(this, out);
811     // Align rest of the instruction info
812     static constexpr auto ALIGN_BUF_SIZE = 64;
813     if (auto pos_diff = out->tellp() - operands_pos; pos_diff < ALIGN_BUF_SIZE) {
814         pos_diff = ALIGN_BUF_SIZE - pos_diff;
815         static std::array<char, ALIGN_BUF_SIZE + 1> space_buf;
816         if (space_buf[0] != ' ') {
817             std::fill(space_buf.begin(), space_buf.end(), ' ');
818         }
819         space_buf[pos_diff] = 0;
820         (*out) << space_buf.data();
821         space_buf[pos_diff] = ' ';
822     }
823     // bytecode pointer
824     if (pc_ != INVALID_PC && !options.IsCompilerDumpCompact()) {
825         (*out) << ' ' << PcToString(pc_, allocator);
826     }
827     if (new_line) {
828         (*out) << '\n';
829     }
830     if (options.IsCompilerDumpBytecode()) {
831         if (pc_ != INVALID_PC) {
832             auto graph = GetBasicBlock()->GetGraph();
833             auto byte_code = graph->GetRuntime()->GetBytecodeString(graph->GetMethod(), pc_);
834             if (!byte_code.empty()) {
835                 (*out) << byte_code << '\n';
836             }
837         }
838     }
839     if (GetOpcode() == Opcode::Parameter) {
840         auto spill_fill = static_cast<const ParameterInst *>(this)->GetLocationData();
841         if (spill_fill.DstValue() != INVALID_REG) {
842             (*out) << sf_data::ToString(spill_fill, GetBasicBlock()->GetGraph()->GetArch());
843             if (new_line) {
844                 *out << std::endl;
845             }
846         }
847     }
848 }
849 
CheckPrintPropsFlag(std::ostream * out,bool * print_props_flag)850 void CheckPrintPropsFlag(std::ostream *out, bool *print_props_flag)
851 {
852     if (!(*print_props_flag)) {
853         (*out) << "prop: ";
854         (*print_props_flag) = true;
855     } else {
856         (*out) << ", ";
857     }
858 }
859 
BlockProps(const BasicBlock * block,std::ostream * out)860 void BlockProps(const BasicBlock *block, std::ostream *out)
861 {
862     bool print_props_flag = false;
863     if (block->IsStartBlock()) {
864         CheckPrintPropsFlag(out, &print_props_flag);
865         (*out) << "start";
866     }
867     if (block->IsEndBlock()) {
868         CheckPrintPropsFlag(out, &print_props_flag);
869         (*out) << "end";
870     }
871     if (block->IsLoopValid() && !block->GetLoop()->IsRoot()) {
872         if (block->IsLoopHeader()) {
873             CheckPrintPropsFlag(out, &print_props_flag);
874             (*out) << "head";
875         }
876         CheckPrintPropsFlag(out, &print_props_flag);
877         (*out) << "loop" << (block->GetLoop()->IsIrreducible() ? " (irreducible) " : " ") << block->GetLoop()->GetId();
878     }
879     if (block->IsTryBegin()) {
880         CheckPrintPropsFlag(out, &print_props_flag);
881         (*out) << "try_begin (id " << block->GetTryId() << ")";
882     }
883     if (block->IsTry()) {
884         CheckPrintPropsFlag(out, &print_props_flag);
885         (*out) << "try (id " << block->GetTryId() << ")";
886     }
887     if (block->IsTryEnd()) {
888         CheckPrintPropsFlag(out, &print_props_flag);
889         (*out) << "try_end (id " << block->GetTryId() << ")";
890     }
891     if (block->IsCatchBegin()) {
892         CheckPrintPropsFlag(out, &print_props_flag);
893         (*out) << "catch_begin";
894     }
895     if (block->IsCatch()) {
896         CheckPrintPropsFlag(out, &print_props_flag);
897         (*out) << "catch";
898     }
899     if (block->IsCatchEnd()) {
900         CheckPrintPropsFlag(out, &print_props_flag);
901         (*out) << "catch_end";
902     }
903 
904     if (block->GetGuestPc() != INVALID_PC) {
905         CheckPrintPropsFlag(out, &print_props_flag);
906         (*out) << PcToString(block->GetGuestPc(), block->GetGraph()->GetLocalAllocator());
907     }
908     if (print_props_flag) {
909         (*out) << std::endl;
910     }
911 }
912 
Dump(std::ostream * out) const913 void BasicBlock::Dump(std::ostream *out) const
914 {
915     const auto &allocator = GetGraph()->GetLocalAllocator();
916     (*out) << "BB " << IdToString(bb_id_, allocator);
917     // predecessors
918     if (!preds_.empty()) {
919         (*out) << "  ";
920         BBDependence("preds", preds_, out, allocator);
921     }
922     (*out) << '\n';
923     // properties
924     BlockProps(this, out);
925     // instructions
926     for (auto inst : this->AllInsts()) {
927         inst->Dump(out);
928     }
929     // successors
930     if (!succs_.empty()) {
931         BBDependence("succs", succs_, out, allocator);
932         (*out) << '\n';
933     }
934 }
935 
Dump(std::ostream * out) const936 void Graph::Dump(std::ostream *out) const
937 {
938     const auto &runtime = GetRuntime();
939     const auto &method = GetMethod();
940     const auto &adapter = GetLocalAllocator()->Adapter();
941     ArenaString return_type(DataType::ToString(runtime->GetMethodReturnType(method)), adapter);
942     (*out) << "Method: " << runtime->GetMethodFullName(method, true) << std::endl;
943     if (IsOsrMode()) {
944         (*out) << "OSR mode\n";
945     }
946     (*out) << std::endl;
947 
948     auto &blocks = GetAnalysis<LinearOrder>().IsValid() ? GetBlocksLinearOrder() : GetBlocksRPO();
949     for (const auto &block_it : blocks) {
950         block_it->Dump(out);
951         (*out) << '\n';
952     }
953 }
954 }  // namespace panda::compiler
955