1 //===- LoongArchAsmPrinter.cpp - LoongArch LLVM Assembly Printer -*- C++ -*--=//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to GAS-format LoongArch assembly language.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "LoongArchAsmPrinter.h"
15 #include "LoongArch.h"
16 #include "LoongArchTargetMachine.h"
17 #include "MCTargetDesc/LoongArchInstPrinter.h"
18 #include "TargetInfo/LoongArchTargetInfo.h"
19 #include "llvm/CodeGen/AsmPrinter.h"
20 #include "llvm/MC/TargetRegistry.h"
21
22 using namespace llvm;
23
24 #define DEBUG_TYPE "loongarch-asm-printer"
25
26 // Simple pseudo-instructions have their lowering (with expansion to real
27 // instructions) auto-generated.
28 #include "LoongArchGenMCPseudoLowering.inc"
29
emitInstruction(const MachineInstr * MI)30 void LoongArchAsmPrinter::emitInstruction(const MachineInstr *MI) {
31 LoongArch_MC::verifyInstructionPredicates(
32 MI->getOpcode(), getSubtargetInfo().getFeatureBits());
33
34 // Do any auto-generated pseudo lowerings.
35 if (emitPseudoExpansionLowering(*OutStreamer, MI))
36 return;
37
38 MCInst TmpInst;
39 if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this))
40 EmitToStreamer(*OutStreamer, TmpInst);
41 }
42
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & OS)43 bool LoongArchAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
44 const char *ExtraCode,
45 raw_ostream &OS) {
46 // First try the generic code, which knows about modifiers like 'c' and 'n'.
47 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
48 return false;
49
50 const MachineOperand &MO = MI->getOperand(OpNo);
51 if (ExtraCode && ExtraCode[0]) {
52 if (ExtraCode[1] != 0)
53 return true; // Unknown modifier.
54
55 switch (ExtraCode[0]) {
56 default:
57 return true; // Unknown modifier.
58 case 'z': // Print $zero register if zero, regular printing otherwise.
59 if (MO.isImm() && MO.getImm() == 0) {
60 OS << '$' << LoongArchInstPrinter::getRegisterName(LoongArch::R0);
61 return false;
62 }
63 break;
64 // TODO: handle other extra codes if any.
65 }
66 }
67
68 switch (MO.getType()) {
69 case MachineOperand::MO_Immediate:
70 OS << MO.getImm();
71 return false;
72 case MachineOperand::MO_Register:
73 OS << '$' << LoongArchInstPrinter::getRegisterName(MO.getReg());
74 return false;
75 case MachineOperand::MO_GlobalAddress:
76 PrintSymbolOperand(MO, OS);
77 return false;
78 default:
79 llvm_unreachable("not implemented");
80 }
81
82 return true;
83 }
84
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & OS)85 bool LoongArchAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
86 unsigned OpNo,
87 const char *ExtraCode,
88 raw_ostream &OS) {
89 // TODO: handle extra code.
90 if (ExtraCode)
91 return true;
92
93 // We only support memory operands like "Base + Offset", where base must be a
94 // register, and offset can be a register or an immediate value.
95 const MachineOperand &BaseMO = MI->getOperand(OpNo);
96 // Base address must be a register.
97 if (!BaseMO.isReg())
98 return true;
99 // Print the base address register.
100 OS << "$" << LoongArchInstPrinter::getRegisterName(BaseMO.getReg());
101 // Print the offset operand.
102 const MachineOperand &OffsetMO = MI->getOperand(OpNo + 1);
103 if (OffsetMO.isReg())
104 OS << ", $" << LoongArchInstPrinter::getRegisterName(OffsetMO.getReg());
105 else if (OffsetMO.isImm())
106 OS << ", " << OffsetMO.getImm();
107 else
108 return true;
109
110 return false;
111 }
112
runOnMachineFunction(MachineFunction & MF)113 bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
114 AsmPrinter::runOnMachineFunction(MF);
115 return true;
116 }
117
118 // Force static initialization.
LLVMInitializeLoongArchAsmPrinter()119 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmPrinter() {
120 RegisterAsmPrinter<LoongArchAsmPrinter> X(getTheLoongArch32Target());
121 RegisterAsmPrinter<LoongArchAsmPrinter> Y(getTheLoongArch64Target());
122 }
123