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