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 
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 
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 
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 
113 bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
114   AsmPrinter::runOnMachineFunction(MF);
115   return true;
116 }
117 
118 // Force static initialization.
119 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmPrinter() {
120   RegisterAsmPrinter<LoongArchAsmPrinter> X(getTheLoongArch32Target());
121   RegisterAsmPrinter<LoongArchAsmPrinter> Y(getTheLoongArch64Target());
122 }
123