Path: blob/main/contrib/llvm-project/llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp
35266 views
//===-- CSKYAsmPrinter.cpp - CSKY LLVM assembly writer --------------------===//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 the CSKY assembly language.10//11//===----------------------------------------------------------------------===//12#include "CSKYAsmPrinter.h"13#include "CSKY.h"14#include "CSKYConstantPoolValue.h"15#include "CSKYTargetMachine.h"16#include "MCTargetDesc/CSKYInstPrinter.h"17#include "MCTargetDesc/CSKYMCExpr.h"18#include "MCTargetDesc/CSKYTargetStreamer.h"19#include "TargetInfo/CSKYTargetInfo.h"20#include "llvm/ADT/Statistic.h"21#include "llvm/CodeGen/AsmPrinter.h"22#include "llvm/CodeGen/MachineConstantPool.h"23#include "llvm/CodeGen/MachineFrameInfo.h"24#include "llvm/IR/DataLayout.h"25#include "llvm/MC/MCAsmInfo.h"26#include "llvm/MC/MCContext.h"27#include "llvm/MC/MCInstBuilder.h"28#include "llvm/MC/MCStreamer.h"29#include "llvm/MC/TargetRegistry.h"3031using namespace llvm;3233#define DEBUG_TYPE "csky-asm-printer"3435STATISTIC(CSKYNumInstrsCompressed,36"Number of C-SKY Compressed instructions emitted");3738CSKYAsmPrinter::CSKYAsmPrinter(llvm::TargetMachine &TM,39std::unique_ptr<llvm::MCStreamer> Streamer)40: AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this) {}4142bool CSKYAsmPrinter::runOnMachineFunction(MachineFunction &MF) {43MCP = MF.getConstantPool();44TII = MF.getSubtarget().getInstrInfo();4546// Set the current MCSubtargetInfo to a copy which has the correct47// feature bits for the current MachineFunction48MCSubtargetInfo &NewSTI =49OutStreamer->getContext().getSubtargetCopy(*TM.getMCSubtargetInfo());50NewSTI.setFeatureBits(MF.getSubtarget().getFeatureBits());51Subtarget = &NewSTI;5253return AsmPrinter::runOnMachineFunction(MF);54}5556#define GEN_COMPRESS_INSTR57#include "CSKYGenCompressInstEmitter.inc"58void CSKYAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {59MCInst CInst;60bool Res = compressInst(CInst, Inst, *Subtarget);61if (Res)62++CSKYNumInstrsCompressed;63AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst);64}6566// Simple pseudo-instructions have their lowering (with expansion to real67// instructions) auto-generated.68#include "CSKYGenMCPseudoLowering.inc"6970void CSKYAsmPrinter::expandTLSLA(const MachineInstr *MI) {71DebugLoc DL = MI->getDebugLoc();7273MCSymbol *PCLabel = OutContext.getOrCreateSymbol(74Twine(MAI->getPrivateGlobalPrefix()) + "PC" + Twine(getFunctionNumber()) +75"_" + Twine(MI->getOperand(3).getImm()));7677OutStreamer->emitLabel(PCLabel);7879auto Instr = BuildMI(*MF, DL, TII->get(CSKY::LRW32))80.add(MI->getOperand(0))81.add(MI->getOperand(2));82MCInst LRWInst;83MCInstLowering.Lower(Instr, LRWInst);84EmitToStreamer(*OutStreamer, LRWInst);8586Instr = BuildMI(*MF, DL, TII->get(CSKY::GRS32))87.add(MI->getOperand(1))88.addSym(PCLabel);89MCInst GRSInst;90MCInstLowering.Lower(Instr, GRSInst);91EmitToStreamer(*OutStreamer, GRSInst);92return;93}9495void CSKYAsmPrinter::emitCustomConstantPool(const MachineInstr *MI) {9697// This instruction represents a floating constant pool in the function.98// The first operand is the ID# for this instruction, the second is the99// index into the MachineConstantPool that this is, the third is the size100// in bytes of this constant pool entry.101// The required alignment is specified on the basic block holding this MI.102unsigned LabelId = (unsigned)MI->getOperand(0).getImm();103unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();104105// If this is the first entry of the pool, mark it.106if (!InConstantPool) {107OutStreamer->emitValueToAlignment(Align(4));108InConstantPool = true;109}110111OutStreamer->emitLabel(GetCPISymbol(LabelId));112113const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];114if (MCPE.isMachineConstantPoolEntry())115emitMachineConstantPoolValue(MCPE.Val.MachineCPVal);116else117emitGlobalConstant(MF->getDataLayout(), MCPE.Val.ConstVal);118return;119}120121void CSKYAsmPrinter::emitFunctionBodyEnd() {122// Make sure to terminate any constant pools that were at the end123// of the function.124if (!InConstantPool)125return;126InConstantPool = false;127}128129void CSKYAsmPrinter::emitStartOfAsmFile(Module &M) {130if (TM.getTargetTriple().isOSBinFormatELF())131emitAttributes();132}133134void CSKYAsmPrinter::emitEndOfAsmFile(Module &M) {135CSKYTargetStreamer &CTS =136static_cast<CSKYTargetStreamer &>(*OutStreamer->getTargetStreamer());137138if (TM.getTargetTriple().isOSBinFormatELF())139CTS.finishAttributeSection();140}141142void CSKYAsmPrinter::emitInstruction(const MachineInstr *MI) {143CSKY_MC::verifyInstructionPredicates(MI->getOpcode(),144getSubtargetInfo().getFeatureBits());145146// Do any auto-generated pseudo lowerings.147if (emitPseudoExpansionLowering(*OutStreamer, MI))148return;149150// If we just ended a constant pool, mark it as such.151if (InConstantPool && MI->getOpcode() != CSKY::CONSTPOOL_ENTRY) {152InConstantPool = false;153}154155if (MI->getOpcode() == CSKY::PseudoTLSLA32)156return expandTLSLA(MI);157158if (MI->getOpcode() == CSKY::CONSTPOOL_ENTRY)159return emitCustomConstantPool(MI);160161MCInst TmpInst;162MCInstLowering.Lower(MI, TmpInst);163EmitToStreamer(*OutStreamer, TmpInst);164}165166// Convert a CSKY-specific constant pool modifier into the associated167// MCSymbolRefExpr variant kind.168static CSKYMCExpr::VariantKind169getModifierVariantKind(CSKYCP::CSKYCPModifier Modifier) {170switch (Modifier) {171case CSKYCP::NO_MOD:172return CSKYMCExpr::VK_CSKY_None;173case CSKYCP::ADDR:174return CSKYMCExpr::VK_CSKY_ADDR;175case CSKYCP::GOT:176return CSKYMCExpr::VK_CSKY_GOT;177case CSKYCP::GOTOFF:178return CSKYMCExpr::VK_CSKY_GOTOFF;179case CSKYCP::PLT:180return CSKYMCExpr::VK_CSKY_PLT;181case CSKYCP::TLSGD:182return CSKYMCExpr::VK_CSKY_TLSGD;183case CSKYCP::TLSLE:184return CSKYMCExpr::VK_CSKY_TLSLE;185case CSKYCP::TLSIE:186return CSKYMCExpr::VK_CSKY_TLSIE;187}188llvm_unreachable("Invalid CSKYCPModifier!");189}190191void CSKYAsmPrinter::emitMachineConstantPoolValue(192MachineConstantPoolValue *MCPV) {193int Size = getDataLayout().getTypeAllocSize(MCPV->getType());194CSKYConstantPoolValue *CCPV = static_cast<CSKYConstantPoolValue *>(MCPV);195MCSymbol *MCSym;196197if (CCPV->isBlockAddress()) {198const BlockAddress *BA =199cast<CSKYConstantPoolConstant>(CCPV)->getBlockAddress();200MCSym = GetBlockAddressSymbol(BA);201} else if (CCPV->isGlobalValue()) {202const GlobalValue *GV = cast<CSKYConstantPoolConstant>(CCPV)->getGV();203MCSym = getSymbol(GV);204} else if (CCPV->isMachineBasicBlock()) {205const MachineBasicBlock *MBB = cast<CSKYConstantPoolMBB>(CCPV)->getMBB();206MCSym = MBB->getSymbol();207} else if (CCPV->isJT()) {208signed JTI = cast<CSKYConstantPoolJT>(CCPV)->getJTI();209MCSym = GetJTISymbol(JTI);210} else if (CCPV->isConstPool()) {211const Constant *C = cast<CSKYConstantPoolConstant>(CCPV)->getConstantPool();212MCSym = GetCPISymbol(MCP->getConstantPoolIndex(C, Align(4)));213} else {214assert(CCPV->isExtSymbol() && "unrecognized constant pool value");215StringRef Sym = cast<CSKYConstantPoolSymbol>(CCPV)->getSymbol();216MCSym = GetExternalSymbolSymbol(Sym);217}218// Create an MCSymbol for the reference.219const MCExpr *Expr =220MCSymbolRefExpr::create(MCSym, MCSymbolRefExpr::VK_None, OutContext);221222if (CCPV->getPCAdjustment()) {223224MCSymbol *PCLabel = OutContext.getOrCreateSymbol(225Twine(MAI->getPrivateGlobalPrefix()) + "PC" +226Twine(getFunctionNumber()) + "_" + Twine(CCPV->getLabelID()));227228const MCExpr *PCRelExpr = MCSymbolRefExpr::create(PCLabel, OutContext);229if (CCPV->mustAddCurrentAddress()) {230// We want "(<expr> - .)", but MC doesn't have a concept of the '.'231// label, so just emit a local label end reference that instead.232MCSymbol *DotSym = OutContext.createTempSymbol();233OutStreamer->emitLabel(DotSym);234const MCExpr *DotExpr = MCSymbolRefExpr::create(DotSym, OutContext);235PCRelExpr = MCBinaryExpr::createSub(PCRelExpr, DotExpr, OutContext);236}237Expr = MCBinaryExpr::createSub(Expr, PCRelExpr, OutContext);238}239240// Create an MCSymbol for the reference.241Expr = CSKYMCExpr::create(Expr, getModifierVariantKind(CCPV->getModifier()),242OutContext);243244OutStreamer->emitValue(Expr, Size);245}246247void CSKYAsmPrinter::emitAttributes() {248CSKYTargetStreamer &CTS =249static_cast<CSKYTargetStreamer &>(*OutStreamer->getTargetStreamer());250251const Triple &TT = TM.getTargetTriple();252StringRef CPU = TM.getTargetCPU();253StringRef FS = TM.getTargetFeatureString();254const CSKYTargetMachine &CTM = static_cast<const CSKYTargetMachine &>(TM);255/* TuneCPU doesn't impact emission of ELF attributes, ELF attributes only256care about arch related features, so we can set TuneCPU as CPU. */257const CSKYSubtarget STI(TT, CPU, /*TuneCPU=*/CPU, FS, CTM);258259CTS.emitTargetAttributes(STI);260}261262bool CSKYAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,263const char *ExtraCode, raw_ostream &OS) {264// First try the generic code, which knows about modifiers like 'c' and 'n'.265if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))266return false;267268const MachineOperand &MO = MI->getOperand(OpNo);269if (ExtraCode && ExtraCode[0]) {270if (ExtraCode[1] != 0)271return true; // Unknown modifier.272273switch (ExtraCode[0]) {274default:275return true; // Unknown modifier.276case 'R':277if (MO.getType() == MachineOperand::MO_Register) {278OS << CSKYInstPrinter::getRegisterName(MO.getReg() + 1);279return false;280}281}282}283284switch (MO.getType()) {285case MachineOperand::MO_Immediate:286OS << MO.getImm();287return false;288case MachineOperand::MO_Register:289if (MO.getReg() == CSKY::C)290return false;291OS << CSKYInstPrinter::getRegisterName(MO.getReg());292return false;293case MachineOperand::MO_GlobalAddress:294PrintSymbolOperand(MO, OS);295return false;296case MachineOperand::MO_BlockAddress: {297MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());298Sym->print(OS, MAI);299return false;300}301default:302break;303}304305return true;306}307308bool CSKYAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,309unsigned OpNo, const char *ExtraCode,310raw_ostream &OS) {311if (!ExtraCode) {312const MachineOperand &MO = MI->getOperand(OpNo);313// For now, we only support register memory operands in registers and314// assume there is no addend315if (!MO.isReg())316return true;317318OS << "(" << CSKYInstPrinter::getRegisterName(MO.getReg()) << ", 0)";319return false;320}321322return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);323}324325extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeCSKYAsmPrinter() {326RegisterAsmPrinter<CSKYAsmPrinter> X(getTheCSKYTarget());327}328329330