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