1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "aarch64_insn.h"
17 #include "aarch64_cg.h"
18 #include "common_utils.h"
19 #include "insn.h"
20 #include "metadata_layout.h"
21 #include <fstream>
22
23 namespace maplebe {
24
EmitIntReg(const RegOperand & v,uint8 opndSz)25 void A64OpndEmitVisitor::EmitIntReg(const RegOperand &v, uint8 opndSz)
26 {
27 CHECK_FATAL(v.GetRegisterType() == kRegTyInt, "wrong Type");
28 uint8 opndSize = (opndSz == kMaxSimm32) ? v.GetSize() : opndSz;
29 DEBUG_ASSERT((opndSize == k32BitSize || opndSize == k64BitSize), "illegal register size");
30 #ifdef USE_32BIT_REF
31 bool r32 = (opndSize == k32BitSize) || isRefField;
32 #else
33 bool r32 = (opndSize == k32BitSize);
34 #endif /* USE_32BIT_REF */
35 (void)emitter.Emit(
36 AArch64CG::intRegNames[(r32 ? AArch64CG::kR32List : AArch64CG::kR64List)][v.GetRegisterNumber()]);
37 }
38
Visit(maplebe::RegOperand * v)39 void A64OpndEmitVisitor::Visit(maplebe::RegOperand *v)
40 {
41 DEBUG_ASSERT(opndProp == nullptr || opndProp->IsRegister(), "operand type doesn't match");
42 uint32 size = v->GetSize();
43 regno_t regNO = v->GetRegisterNumber();
44 uint8 opndSize = (opndProp != nullptr) ? opndProp->GetSize() : size;
45 switch (v->GetRegisterType()) {
46 case kRegTyInt: {
47 EmitIntReg(*v, opndSize);
48 break;
49 }
50 case kRegTyFloat: {
51 DEBUG_ASSERT((opndSize == k8BitSize || opndSize == k16BitSize || opndSize == k32BitSize ||
52 opndSize == k64BitSize || opndSize == k128BitSize),
53 "illegal register size");
54 if (opndProp->IsVectorOperand() && v->GetVecLaneSize() != 0) {
55 EmitVectorOperand(*v);
56 } else {
57 /* FP reg cannot be reffield. 8~0, 16~1, 32~2, 64~3. 8 is 1000b, has 3 zero. */
58 uint32 regSet = static_cast<uint32>(__builtin_ctz(static_cast<uint32>(opndSize)) - 3);
59 (void)emitter.Emit(AArch64CG::intRegNames[regSet][regNO]);
60 }
61 break;
62 }
63 default:
64 DEBUG_ASSERT(false, "NYI");
65 break;
66 }
67 }
68
Visit(maplebe::ImmOperand * v)69 void A64OpndEmitVisitor::Visit(maplebe::ImmOperand *v)
70 {
71 if (v->IsOfstImmediate()) {
72 return Visit(static_cast<OfstOperand *>(v));
73 }
74
75 if (v->IsStImmediate()) {
76 Visit(*v->GetSymbol(), v->GetValue());
77 return;
78 }
79
80 int64 value = v->GetValue();
81 if (!v->IsFmov()) {
82 (void)emitter.Emit((opndProp != nullptr && opndProp->IsLoadLiteral()) ? "=" : "#")
83 .Emit((v->GetSize() == k64BitSize) ? value : static_cast<int64>(static_cast<int32>(value)));
84 return;
85 }
86 if (v->GetKind() == Operand::kOpdFPImmediate) {
87 CHECK_FATAL(value == 0, "NIY");
88 emitter.Emit("#0.0");
89 }
90 /*
91 * compute float value
92 * use top 4 bits expect MSB of value . then calculate its fourth power
93 */
94 int32 exp = static_cast<int32>((((static_cast<uint32>(value) & 0x70) >> 4) ^ 0x4) - 3);
95 /* use the lower four bits of value in this expression */
96 const float mantissa = 1.0 + (static_cast<float>(static_cast<uint64>(value) & 0xf) / 16.0);
97 float result = std::pow(2, exp) * mantissa;
98
99 std::stringstream ss;
100 ss << std::setprecision(10) << result; // float aligned with 10 characters
101 std::string res;
102 ss >> res;
103 size_t dot = res.find('.');
104 if (dot == std::string::npos) {
105 res += ".0";
106 dot = res.find('.');
107 CHECK_FATAL(dot != std::string::npos, "cannot find in string");
108 }
109 (void)res.erase(dot, 1);
110 std::string integer(res, 0, 1);
111 std::string fraction(res, 1);
112 DEBUG_ASSERT(fraction.size() >= 1, "fraction must not be empty");
113 while (fraction.size() != 1 && fraction[fraction.size() - 1] == '0') {
114 fraction.pop_back();
115 }
116 /* fetch the sign bit of this value */
117 std::string sign = static_cast<uint64>(value) & 0x80 ? "-" : "";
118 (void)emitter.Emit(sign + integer + "." + fraction + "e+").Emit(static_cast<int64>(dot) - 1);
119 }
120
Visit(maplebe::MemOperand * v)121 void A64OpndEmitVisitor::Visit(maplebe::MemOperand *v)
122 {
123 auto a64v = static_cast<MemOperand *>(v);
124 MemOperand::AArch64AddressingMode addressMode = a64v->GetAddrMode();
125 #if DEBUG
126 const InsnDesc *md = &AArch64CG::kMd[emitter.GetCurrentMOP()];
127 bool isLDSTpair = md->IsLoadStorePair();
128 DEBUG_ASSERT(md->Is64Bit() || md->GetOperandSize() <= k32BitSize || md->GetOperandSize() == k128BitSize,
129 "unexpected opnd size");
130 #endif
131 if (addressMode == MemOperand::kAddrModeBOi) {
132 (void)emitter.Emit("[");
133 auto *baseReg = v->GetBaseRegister();
134 DEBUG_ASSERT(baseReg != nullptr, "expect an RegOperand here");
135 uint32 baseSize = baseReg->GetSize();
136 if (baseSize != k64BitSize) {
137 baseReg->SetSize(k64BitSize);
138 }
139 EmitIntReg(*baseReg);
140 baseReg->SetSize(baseSize);
141 ImmOperand *offset = a64v->GetOffsetImmediate();
142 if (offset != nullptr) {
143 #ifndef USE_32BIT_REF /* can be load a ref here */
144 /*
145 * Cortex-A57 Software Optimization Guide:
146 * The ARMv8-A architecture allows many types of load and store accesses to be arbitrarily aligned
147 * The Cortex- A57 processor handles most unaligned accesses without performance penalties
148 */
149 #if DEBUG
150 if (a64v->IsOffsetMisaligned(md->GetOperandSize())) {
151 INFO(kLncInfo, "The Memory operand's offset is misaligned:", "");
152 }
153 #endif
154 #endif /* USE_32BIT_REF */
155 if (a64v->IsPostIndexed()) {
156 DEBUG_ASSERT(!a64v->IsSIMMOffsetOutOfRange(offset->GetValue(), md->Is64Bit(), isLDSTpair),
157 "should not be SIMMOffsetOutOfRange");
158 (void)emitter.Emit("]");
159 if (!offset->IsZero()) {
160 (void)emitter.Emit(", ");
161 Visit(offset);
162 }
163 } else if (a64v->IsPreIndexed()) {
164 DEBUG_ASSERT(!a64v->IsSIMMOffsetOutOfRange(offset->GetValue(), md->Is64Bit(), isLDSTpair),
165 "should not be SIMMOffsetOutOfRange");
166 if (!offset->IsZero()) {
167 (void)emitter.Emit(",");
168 Visit(offset);
169 }
170 (void)emitter.Emit("]!");
171 } else {
172 if (!offset->IsZero() || static_cast<OfstOperand *>(offset)->IsSymAndImmOffset() ||
173 static_cast<OfstOperand *>(offset)->IsSymOffset()) {
174 (void)emitter.Emit(",");
175 Visit(offset);
176 }
177 (void)emitter.Emit("]");
178 }
179 } else {
180 (void)emitter.Emit("]");
181 }
182 } else if (addressMode == MemOperand::kAddrModeBOrX) {
183 /*
184 * Base plus offset | [base{, #imm}] [base, Xm{, LSL #imm}] [base, Wm, (S|U)XTW {#imm}]
185 * offset_opnds=nullptr
186 * offset_opnds=64 offset_opnds=32
187 * imm=0 or 3 imm=0 or 2, s/u
188 */
189 (void)emitter.Emit("[");
190 auto *baseReg = v->GetBaseRegister();
191 // After ssa version support different size, the value is changed back
192 baseReg->SetSize(k64BitSize);
193
194 EmitIntReg(*baseReg);
195 (void)emitter.Emit(",");
196 EmitIntReg(*a64v->GetIndexRegister());
197 if (a64v->ShouldEmitExtend() || v->GetBaseRegister()->GetSize() > a64v->GetIndexRegister()->GetSize()) {
198 (void)emitter.Emit(",");
199 /* extend, #0, of #3/#2 */
200 (void)emitter.Emit(a64v->GetExtendAsString());
201 if (a64v->GetExtendAsString() == "LSL" || a64v->ShiftAmount() != 0) {
202 (void)emitter.Emit(" #");
203 (void)emitter.Emit(a64v->ShiftAmount());
204 }
205 }
206 (void)emitter.Emit("]");
207 } else if (addressMode == MemOperand::kAddrModeLiteral) {
208 CHECK_FATAL(opndProp != nullptr, "prop is nullptr in MemOperand::Emit");
209 if (opndProp->IsMemLow12()) {
210 (void)emitter.Emit("#:lo12:");
211 }
212 CHECK_NULL_FATAL(emitter.GetCG()->GetMIRModule()->CurFunction());
213 PUIdx pIdx = emitter.GetCG()->GetMIRModule()->CurFunction()->GetPuidx();
214 (void)emitter.Emit(v->GetSymbol()->GetName() + std::to_string(pIdx));
215 } else if (addressMode == MemOperand::kAddrModeLo12Li) {
216 (void)emitter.Emit("[");
217 EmitIntReg(*v->GetBaseRegister());
218
219 OfstOperand *offset = a64v->GetOffsetImmediate();
220 DEBUG_ASSERT(offset != nullptr, "nullptr check");
221
222 (void)emitter.Emit(", #:lo12:");
223 if (v->GetSymbol()->GetAsmAttr() != UStrIdx(0) &&
224 (v->GetSymbol()->GetStorageClass() == kScPstatic || v->GetSymbol()->GetStorageClass() == kScPstatic)) {
225 std::string asmSection = GlobalTables::GetUStrTable().GetStringFromStrIdx(v->GetSymbol()->GetAsmAttr());
226 (void)emitter.Emit(asmSection);
227 } else {
228 if (v->GetSymbol()->GetStorageClass() == kScPstatic && v->GetSymbol()->IsLocal()) {
229 CHECK_NULL_FATAL(emitter.GetCG()->GetMIRModule()->CurFunction());
230 PUIdx pIdx = emitter.GetCG()->GetMIRModule()->CurFunction()->GetPuidx();
231 (void)emitter.Emit(a64v->GetSymbolName() + std::to_string(pIdx));
232 } else {
233 (void)emitter.Emit(a64v->GetSymbolName());
234 }
235 }
236 if (!offset->IsZero()) {
237 (void)emitter.Emit("+");
238 (void)emitter.Emit(std::to_string(offset->GetOffsetValue()));
239 }
240 (void)emitter.Emit("]");
241 } else {
242 DEBUG_ASSERT(false, "nyi");
243 }
244 }
245
Visit(LabelOperand * v)246 void A64OpndEmitVisitor::Visit(LabelOperand *v)
247 {
248 emitter.EmitLabelRef(v->GetLabelIndex());
249 }
250
Visit(CondOperand * v)251 void A64OpndEmitVisitor::Visit(CondOperand *v)
252 {
253 (void)emitter.Emit(CondOperand::ccStrs[v->GetCode()]);
254 }
255
Visit(ExtendShiftOperand * v)256 void A64OpndEmitVisitor::Visit(ExtendShiftOperand *v)
257 {
258 DEBUG_ASSERT(v->GetShiftAmount() <= k4BitSize && v->GetShiftAmount() >= 0,
259 "shift amount out of range in ExtendShiftOperand");
260 auto emitExtendShift = [this, v](const std::string &extendKind) -> void {
261 (void)emitter.Emit(extendKind);
262 if (v->GetShiftAmount() != 0) {
263 (void)emitter.Emit(" #").Emit(v->GetShiftAmount());
264 }
265 };
266 switch (v->GetExtendOp()) {
267 case ExtendShiftOperand::kUXTB:
268 emitExtendShift("UXTB");
269 break;
270 case ExtendShiftOperand::kUXTH:
271 emitExtendShift("UXTH");
272 break;
273 case ExtendShiftOperand::kUXTW:
274 emitExtendShift("UXTW");
275 break;
276 case ExtendShiftOperand::kUXTX:
277 emitExtendShift("UXTX");
278 break;
279 case ExtendShiftOperand::kSXTB:
280 emitExtendShift("SXTB");
281 break;
282 case ExtendShiftOperand::kSXTH:
283 emitExtendShift("SXTH");
284 break;
285 case ExtendShiftOperand::kSXTW:
286 emitExtendShift("SXTW");
287 break;
288 case ExtendShiftOperand::kSXTX:
289 emitExtendShift("SXTX");
290 break;
291 default:
292 DEBUG_ASSERT(false, "should not be here");
293 break;
294 }
295 }
296
Visit(BitShiftOperand * v)297 void A64OpndEmitVisitor::Visit(BitShiftOperand *v)
298 {
299 (void)emitter
300 .Emit((v->GetShiftOp() == BitShiftOperand::kLSL)
301 ? "LSL #"
302 : ((v->GetShiftOp() == BitShiftOperand::kLSR) ? "LSR #" : "ASR #"))
303 .Emit(v->GetShiftAmount());
304 }
305
Visit(StImmOperand * v)306 void A64OpndEmitVisitor::Visit(StImmOperand *v)
307 {
308 CHECK_FATAL(opndProp != nullptr, "opndProp is nullptr in StImmOperand::Emit");
309 const MIRSymbol *symbol = v->GetSymbol();
310 const bool isThreadLocal = symbol->IsThreadLocal();
311 const bool isLiteralLow12 = opndProp->IsLiteralLow12();
312 const bool hasGotEntry = CGOptions::IsPIC() && symbol->NeedPIC();
313 bool hasPrefix = false;
314 if (isThreadLocal) {
315 (void)emitter.Emit(":tlsdesc");
316 hasPrefix = true;
317 }
318 if (!hasPrefix && hasGotEntry) {
319 (void)emitter.Emit(":got");
320 hasPrefix = true;
321 }
322 if (isLiteralLow12) {
323 std::string lo12String = hasPrefix ? "_lo12" : ":lo12";
324 (void)emitter.Emit(lo12String);
325 hasPrefix = true;
326 }
327 if (hasPrefix) {
328 (void)emitter.Emit(":");
329 }
330 if (symbol->GetAsmAttr() != UStrIdx(0) &&
331 (symbol->GetStorageClass() == kScPstatic || symbol->GetStorageClass() == kScPstatic)) {
332 std::string asmSection = GlobalTables::GetUStrTable().GetStringFromStrIdx(symbol->GetAsmAttr());
333 (void)emitter.Emit(asmSection);
334 } else {
335 if (symbol->GetStorageClass() == kScPstatic && symbol->GetSKind() != kStConst && symbol->IsLocal()) {
336 CHECK_NULL_FATAL(emitter.GetCG()->GetMIRModule()->CurFunction());
337 (void)emitter.Emit(symbol->GetName() +
338 std::to_string(emitter.GetCG()->GetMIRModule()->CurFunction()->GetPuidx()));
339 } else {
340 (void)emitter.Emit(v->GetName());
341 }
342 }
343 if (!hasGotEntry && v->GetOffset() != 0) {
344 (void)emitter.Emit("+" + std::to_string(v->GetOffset()));
345 }
346 }
347
Visit(FuncNameOperand * v)348 void A64OpndEmitVisitor::Visit(FuncNameOperand *v)
349 {
350 (void)emitter.Emit(v->GetName());
351 }
352
Visit(CommentOperand * v)353 void A64OpndEmitVisitor::Visit(CommentOperand *v)
354 {
355 (void)emitter.Emit(v->GetComment());
356 }
357
Visit(ListOperand * v)358 void A64OpndEmitVisitor::Visit(ListOperand *v)
359 {
360 (void)opndProp;
361 size_t nLeft = v->GetOperands().size();
362 if (nLeft == 0) {
363 return;
364 }
365
366 for (auto it = v->GetOperands().begin(); it != v->GetOperands().end(); ++it) {
367 Visit(*it);
368 if (--nLeft >= 1) {
369 (void)emitter.Emit(", ");
370 }
371 }
372 }
373
Visit(OfstOperand * v)374 void A64OpndEmitVisitor::Visit(OfstOperand *v)
375 {
376 int64 value = v->GetValue();
377 if (v->IsImmOffset()) {
378 (void)emitter.Emit((opndProp != nullptr && opndProp->IsLoadLiteral()) ? "=" : "#")
379 .Emit((v->GetSize() == k64BitSize) ? value : static_cast<int64>(static_cast<int32>(value)));
380 return;
381 }
382 const MIRSymbol *symbol = v->GetSymbol();
383 CHECK_NULL_FATAL(symbol);
384 if (CGOptions::IsPIC() && symbol->NeedPIC()) {
385 (void)emitter.Emit("#:got_lo12:" + symbol->GetName());
386 } else if (symbol->GetStorageClass() == kScPstatic && symbol->GetSKind() != kStConst && symbol->IsLocal()) {
387 CHECK_NULL_FATAL(emitter.GetCG()->GetMIRModule()->CurFunction());
388 (void)emitter.Emit(symbol->GetName() +
389 std::to_string(emitter.GetCG()->GetMIRModule()->CurFunction()->GetPuidx()));
390 } else {
391 (void)emitter.Emit(symbol->GetName());
392 }
393 if (value != 0) {
394 (void)emitter.Emit("+" + std::to_string(value));
395 }
396 }
397
EmitVectorOperand(const RegOperand & v)398 void A64OpndEmitVisitor::EmitVectorOperand(const RegOperand &v)
399 {
400 std::string width;
401 switch (v.GetVecElementSize()) {
402 case k8BitSize:
403 width = "b";
404 break;
405 case k16BitSize:
406 width = "h";
407 break;
408 case k32BitSize:
409 width = "s";
410 break;
411 case k64BitSize:
412 width = "d";
413 break;
414 default:
415 CHECK_FATAL(false, "unexpected value size for vector element");
416 break;
417 }
418 (void)emitter.Emit(AArch64CG::vectorRegNames[v.GetRegisterNumber()]);
419 int32 lanePos = v.GetVecLanePosition();
420 if (lanePos == -1) {
421 (void)emitter.Emit("." + std::to_string(v.GetVecLaneSize()) + width);
422 } else {
423 (void)emitter.Emit("." + width + "[" + std::to_string(lanePos) + "]");
424 }
425 }
426
Visit(RegOperand * v)427 void A64OpndDumpVisitor::Visit(RegOperand *v)
428 {
429 std::array<const std::string, kRegTyLast> prims = {"U", "R", "V", "C", "X", "Vra"};
430 std::array<const std::string, kRegTyLast> classes = {"[U]", "[I]", "[F]", "[CC]", "[X87]", "[Vra]"};
431 uint32 regType = v->GetRegisterType();
432 DEBUG_ASSERT(regType < kRegTyLast, "unexpected regType");
433
434 regno_t reg = v->GetRegisterNumber();
435 reg = v->IsVirtualRegister() ? reg : (reg - 1);
436 uint32 vb = v->GetValidBitsNum();
437 LogInfo::MapleLogger() << (v->IsVirtualRegister() ? "vreg:" : " reg:") << prims[regType] << reg << " "
438 << classes[regType];
439 if (v->GetBaseRefOpnd()) {
440 LogInfo::MapleLogger() << " base ref:R" << v->GetBaseRefOpnd()->GetRegisterNumber() << " ";
441 }
442 if (v->GetValidBitsNum() != v->GetSize()) {
443 LogInfo::MapleLogger() << " Vb: [" << vb << "]";
444 }
445 LogInfo::MapleLogger() << " Sz: [" << v->GetSize() << "]";
446 }
447
Visit(ImmOperand * v)448 void A64OpndDumpVisitor::Visit(ImmOperand *v)
449 {
450 LogInfo::MapleLogger() << "imm:" << v->GetValue();
451 }
452
Visit(MemOperand * a64v)453 void A64OpndDumpVisitor::Visit(MemOperand *a64v)
454 {
455 LogInfo::MapleLogger() << "Mem:";
456 LogInfo::MapleLogger() << " size:" << a64v->GetSize() << " ";
457 LogInfo::MapleLogger() << " isStack:" << a64v->IsStackMem() << "-" << a64v->IsStackArgMem() << " ";
458 switch (a64v->GetAddrMode()) {
459 case MemOperand::kAddrModeBOi: {
460 LogInfo::MapleLogger() << "base:";
461 Visit(a64v->GetBaseRegister());
462 LogInfo::MapleLogger() << "offset:";
463 Visit(a64v->GetOffsetOperand());
464 switch (a64v->GetIndexOpt()) {
465 case MemOperand::kIntact:
466 LogInfo::MapleLogger() << " intact";
467 break;
468 case MemOperand::kPreIndex:
469 LogInfo::MapleLogger() << " pre-index";
470 break;
471 case MemOperand::kPostIndex:
472 LogInfo::MapleLogger() << " post-index";
473 break;
474 default:
475 break;
476 }
477 break;
478 }
479 case MemOperand::kAddrModeBOrX: {
480 LogInfo::MapleLogger() << "base:";
481 Visit(a64v->GetBaseRegister());
482 LogInfo::MapleLogger() << "offset:";
483 Visit(a64v->GetIndexRegister());
484 LogInfo::MapleLogger() << " " << a64v->GetExtendAsString();
485 LogInfo::MapleLogger() << " shift: " << a64v->ShiftAmount();
486 LogInfo::MapleLogger() << " extend: " << a64v->GetExtendAsString();
487 break;
488 }
489 case MemOperand::kAddrModeLiteral:
490 LogInfo::MapleLogger() << "literal: " << a64v->GetSymbolName();
491 break;
492 case MemOperand::kAddrModeLo12Li: {
493 LogInfo::MapleLogger() << "base:";
494 Visit(a64v->GetBaseRegister());
495 LogInfo::MapleLogger() << "offset:";
496 OfstOperand *offOpnd = a64v->GetOffsetImmediate();
497 LogInfo::MapleLogger() << "#:lo12:";
498 if (a64v->GetSymbol()->GetStorageClass() == kScPstatic && a64v->GetSymbol()->IsLocal()) {
499 CHECK_NULL_FATAL(CG::GetCurCGFunc()->GetMirModule().CurFunction());
500 PUIdx pIdx = CG::GetCurCGFunc()->GetMirModule().CurFunction()->GetPuidx();
501 LogInfo::MapleLogger() << a64v->GetSymbolName() << std::to_string(pIdx);
502 } else {
503 LogInfo::MapleLogger() << a64v->GetSymbolName();
504 }
505 LogInfo::MapleLogger() << "+" << std::to_string(offOpnd->GetOffsetValue());
506 break;
507 }
508 default:
509 DEBUG_ASSERT(false, "error memoperand dump");
510 break;
511 }
512 }
513
Visit(CondOperand * v)514 void A64OpndDumpVisitor::Visit(CondOperand *v)
515 {
516 LogInfo::MapleLogger() << "CC: " << CondOperand::ccStrs[v->GetCode()];
517 }
Visit(StImmOperand * v)518 void A64OpndDumpVisitor::Visit(StImmOperand *v)
519 {
520 LogInfo::MapleLogger() << v->GetName();
521 LogInfo::MapleLogger() << "+offset:" << v->GetOffset();
522 }
Visit(BitShiftOperand * v)523 void A64OpndDumpVisitor::Visit(BitShiftOperand *v)
524 {
525 BitShiftOperand::ShiftOp shiftOp = v->GetShiftOp();
526 uint32 shiftAmount = v->GetShiftAmount();
527 LogInfo::MapleLogger() << ((shiftOp == BitShiftOperand::kLSL)
528 ? "LSL: "
529 : ((shiftOp == BitShiftOperand::kLSR) ? "LSR: " : "ASR: "));
530 LogInfo::MapleLogger() << shiftAmount;
531 }
Visit(ExtendShiftOperand * v)532 void A64OpndDumpVisitor::Visit(ExtendShiftOperand *v)
533 {
534 auto dumpExtendShift = [v](const std::string &extendKind) -> void {
535 LogInfo::MapleLogger() << extendKind;
536 if (v->GetShiftAmount() != 0) {
537 LogInfo::MapleLogger() << " : " << v->GetShiftAmount();
538 }
539 };
540 switch (v->GetExtendOp()) {
541 case ExtendShiftOperand::kUXTB:
542 dumpExtendShift("UXTB");
543 break;
544 case ExtendShiftOperand::kUXTH:
545 dumpExtendShift("UXTH");
546 break;
547 case ExtendShiftOperand::kUXTW:
548 dumpExtendShift("UXTW");
549 break;
550 case ExtendShiftOperand::kUXTX:
551 dumpExtendShift("UXTX");
552 break;
553 case ExtendShiftOperand::kSXTB:
554 dumpExtendShift("SXTB");
555 break;
556 case ExtendShiftOperand::kSXTH:
557 dumpExtendShift("SXTH");
558 break;
559 case ExtendShiftOperand::kSXTW:
560 dumpExtendShift("SXTW");
561 break;
562 case ExtendShiftOperand::kSXTX:
563 dumpExtendShift("SXTX");
564 break;
565 default:
566 DEBUG_ASSERT(false, "should not be here");
567 break;
568 }
569 }
Visit(LabelOperand * v)570 void A64OpndDumpVisitor::Visit(LabelOperand *v)
571 {
572 LogInfo::MapleLogger() << "label:" << v->GetLabelIndex();
573 }
Visit(FuncNameOperand * v)574 void A64OpndDumpVisitor::Visit(FuncNameOperand *v)
575 {
576 LogInfo::MapleLogger() << "func :" << v->GetName();
577 }
Visit(CommentOperand * v)578 void A64OpndDumpVisitor::Visit(CommentOperand *v)
579 {
580 LogInfo::MapleLogger() << " #" << v->GetComment();
581 }
Visit(PhiOperand * v)582 void A64OpndDumpVisitor::Visit(PhiOperand *v)
583 {
584 auto &phiList = v->GetOperands();
585 for (auto it = phiList.begin(); it != phiList.end();) {
586 Visit(it->second);
587 LogInfo::MapleLogger() << " fBB<" << it->first << ">";
588 LogInfo::MapleLogger() << (++it == phiList.end() ? "" : " ,");
589 }
590 }
Visit(ListOperand * v)591 void A64OpndDumpVisitor::Visit(ListOperand *v)
592 {
593 auto &opndList = v->GetOperands();
594 for (auto it = opndList.begin(); it != opndList.end();) {
595 Visit(*it);
596 LogInfo::MapleLogger() << (++it == opndList.end() ? "" : " ,");
597 }
598 }
599
Visit(const MIRSymbol & symbol,int64 offset)600 void A64OpndEmitVisitor::Visit(const MIRSymbol &symbol, int64 offset)
601 {
602 CHECK_FATAL(opndProp != nullptr, "opndProp is nullptr in StImmOperand::Emit");
603 const bool isThreadLocal = symbol.IsThreadLocal();
604 const bool isLiteralLow12 = opndProp->IsLiteralLow12();
605 bool hasPrefix = false;
606 if (isThreadLocal) {
607 (void)emitter.Emit(":tlsdesc");
608 hasPrefix = true;
609 }
610 if (isLiteralLow12) {
611 std::string lo12String = hasPrefix ? "_lo12" : ":lo12";
612 (void)emitter.Emit(lo12String);
613 hasPrefix = true;
614 }
615 if (hasPrefix) {
616 (void)emitter.Emit(":");
617 }
618 if (symbol.GetAsmAttr() != UStrIdx(0) && symbol.GetStorageClass() == kScPstatic) {
619 std::string asmSection = GlobalTables::GetUStrTable().GetStringFromStrIdx(symbol.GetAsmAttr());
620 (void)emitter.Emit(asmSection);
621 } else {
622 if (symbol.GetStorageClass() == kScPstatic && symbol.GetSKind() != kStConst) {
623 CHECK_NULL_FATAL(emitter.GetCG()->GetMIRModule()->CurFunction());
624 (void)emitter.Emit(symbol.GetName() +
625 std::to_string(emitter.GetCG()->GetMIRModule()->CurFunction()->GetPuidx()));
626 } else {
627 (void)emitter.Emit(symbol.GetName());
628 }
629 }
630 if (offset != 0) {
631 (void)emitter.Emit("+" + std::to_string(offset));
632 }
633 }
634 } /* namespace maplebe */
635