Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
35267 views
//===- LoongArchAsmPrinter.cpp - LoongArch LLVM Assembly Printer -*- C++ -*--=//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains a printer that converts from our internal representation9// of machine-dependent LLVM code to GAS-format LoongArch assembly language.10//11//===----------------------------------------------------------------------===//1213#include "LoongArchAsmPrinter.h"14#include "LoongArch.h"15#include "LoongArchTargetMachine.h"16#include "MCTargetDesc/LoongArchInstPrinter.h"17#include "TargetInfo/LoongArchTargetInfo.h"18#include "llvm/CodeGen/AsmPrinter.h"19#include "llvm/MC/MCContext.h"20#include "llvm/MC/MCInstBuilder.h"21#include "llvm/MC/TargetRegistry.h"2223using namespace llvm;2425#define DEBUG_TYPE "loongarch-asm-printer"2627// Simple pseudo-instructions have their lowering (with expansion to real28// instructions) auto-generated.29#include "LoongArchGenMCPseudoLowering.inc"3031void LoongArchAsmPrinter::emitInstruction(const MachineInstr *MI) {32LoongArch_MC::verifyInstructionPredicates(33MI->getOpcode(), getSubtargetInfo().getFeatureBits());3435// Do any auto-generated pseudo lowerings.36if (emitPseudoExpansionLowering(*OutStreamer, MI))37return;3839switch (MI->getOpcode()) {40case TargetOpcode::PATCHABLE_FUNCTION_ENTER:41LowerPATCHABLE_FUNCTION_ENTER(*MI);42return;43case TargetOpcode::PATCHABLE_FUNCTION_EXIT:44LowerPATCHABLE_FUNCTION_EXIT(*MI);45return;46case TargetOpcode::PATCHABLE_TAIL_CALL:47LowerPATCHABLE_TAIL_CALL(*MI);48return;49}5051MCInst TmpInst;52if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this))53EmitToStreamer(*OutStreamer, TmpInst);54}5556bool LoongArchAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,57const char *ExtraCode,58raw_ostream &OS) {59// First try the generic code, which knows about modifiers like 'c' and 'n'.60if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))61return false;6263const MachineOperand &MO = MI->getOperand(OpNo);64if (ExtraCode && ExtraCode[0]) {65if (ExtraCode[1] != 0)66return true; // Unknown modifier.6768switch (ExtraCode[0]) {69default:70return true; // Unknown modifier.71case 'z': // Print $zero register if zero, regular printing otherwise.72if (MO.isImm() && MO.getImm() == 0) {73OS << '$' << LoongArchInstPrinter::getRegisterName(LoongArch::R0);74return false;75}76break;77case 'w': // Print LSX registers.78if (MO.getReg().id() >= LoongArch::VR0 &&79MO.getReg().id() <= LoongArch::VR31)80break;81// The modifier is 'w' but the operand is not an LSX register; Report an82// unknown operand error.83return true;84case 'u': // Print LASX registers.85if (MO.getReg().id() >= LoongArch::XR0 &&86MO.getReg().id() <= LoongArch::XR31)87break;88// The modifier is 'u' but the operand is not an LASX register; Report an89// unknown operand error.90return true;91// TODO: handle other extra codes if any.92}93}9495switch (MO.getType()) {96case MachineOperand::MO_Immediate:97OS << MO.getImm();98return false;99case MachineOperand::MO_Register:100OS << '$' << LoongArchInstPrinter::getRegisterName(MO.getReg());101return false;102case MachineOperand::MO_GlobalAddress:103PrintSymbolOperand(MO, OS);104return false;105default:106llvm_unreachable("not implemented");107}108109return true;110}111112bool LoongArchAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,113unsigned OpNo,114const char *ExtraCode,115raw_ostream &OS) {116// TODO: handle extra code.117if (ExtraCode)118return true;119120// We only support memory operands like "Base + Offset", where base must be a121// register, and offset can be a register or an immediate value.122const MachineOperand &BaseMO = MI->getOperand(OpNo);123// Base address must be a register.124if (!BaseMO.isReg())125return true;126// Print the base address register.127OS << "$" << LoongArchInstPrinter::getRegisterName(BaseMO.getReg());128// Print the offset operand.129const MachineOperand &OffsetMO = MI->getOperand(OpNo + 1);130if (OffsetMO.isReg())131OS << ", $" << LoongArchInstPrinter::getRegisterName(OffsetMO.getReg());132else if (OffsetMO.isImm())133OS << ", " << OffsetMO.getImm();134else135return true;136137return false;138}139140void LoongArchAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(141const MachineInstr &MI) {142const Function &F = MF->getFunction();143if (F.hasFnAttribute("patchable-function-entry")) {144unsigned Num;145if (F.getFnAttribute("patchable-function-entry")146.getValueAsString()147.getAsInteger(10, Num))148return;149emitNops(Num);150return;151}152153emitSled(MI, SledKind::FUNCTION_ENTER);154}155156void LoongArchAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) {157emitSled(MI, SledKind::FUNCTION_EXIT);158}159160void LoongArchAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) {161emitSled(MI, SledKind::TAIL_CALL);162}163164void LoongArchAsmPrinter::emitSled(const MachineInstr &MI, SledKind Kind) {165// For loongarch64 we want to emit the following pattern:166//167// .Lxray_sled_beginN:168// B .Lxray_sled_endN169// 11 NOPs (44 bytes)170// .Lxray_sled_endN:171//172// We need the extra bytes because at runtime they may be used for the173// actual pattern defined at compiler-rt/lib/xray/xray_loongarch64.cpp.174// The count here should be adjusted accordingly if the implementation175// changes.176const int8_t NoopsInSledCount = 11;177OutStreamer->emitCodeAlignment(Align(4), &getSubtargetInfo());178MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_begin");179MCSymbol *EndOfSled = OutContext.createTempSymbol("xray_sled_end");180OutStreamer->emitLabel(BeginOfSled);181EmitToStreamer(*OutStreamer,182MCInstBuilder(LoongArch::B)183.addExpr(MCSymbolRefExpr::create(EndOfSled, OutContext)));184emitNops(NoopsInSledCount);185OutStreamer->emitLabel(EndOfSled);186recordSled(BeginOfSled, MI, Kind, 2);187}188189bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) {190AsmPrinter::runOnMachineFunction(MF);191// Emit the XRay table for this function.192emitXRayTable();193return true;194}195196// Force static initialization.197extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmPrinter() {198RegisterAsmPrinter<LoongArchAsmPrinter> X(getTheLoongArch32Target());199RegisterAsmPrinter<LoongArchAsmPrinter> Y(getTheLoongArch64Target());200}201202203