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