Path: blob/main/contrib/llvm-project/llvm/lib/Target/VE/VEAsmPrinter.cpp
35294 views
//===-- VEAsmPrinter.cpp - VE 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 GAS-format VE assembly language.10//11//===----------------------------------------------------------------------===//1213#include "MCTargetDesc/VEInstPrinter.h"14#include "MCTargetDesc/VEMCExpr.h"15#include "MCTargetDesc/VETargetStreamer.h"16#include "TargetInfo/VETargetInfo.h"17#include "VE.h"18#include "VEInstrInfo.h"19#include "VETargetMachine.h"20#include "llvm/CodeGen/AsmPrinter.h"21#include "llvm/CodeGen/MachineInstr.h"22#include "llvm/CodeGen/MachineModuleInfoImpls.h"23#include "llvm/CodeGen/MachineRegisterInfo.h"24#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"25#include "llvm/IR/Mangler.h"26#include "llvm/MC/MCAsmInfo.h"27#include "llvm/MC/MCContext.h"28#include "llvm/MC/MCInst.h"29#include "llvm/MC/MCInstBuilder.h"30#include "llvm/MC/MCStreamer.h"31#include "llvm/MC/MCSymbol.h"32#include "llvm/MC/TargetRegistry.h"33#include "llvm/Support/raw_ostream.h"34using namespace llvm;3536#define DEBUG_TYPE "ve-asmprinter"3738namespace {39class VEAsmPrinter : public AsmPrinter {40VETargetStreamer &getTargetStreamer() {41return static_cast<VETargetStreamer &>(*OutStreamer->getTargetStreamer());42}4344public:45explicit VEAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)46: AsmPrinter(TM, std::move(Streamer)) {}4748StringRef getPassName() const override { return "VE Assembly Printer"; }4950void lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,51const MCSubtargetInfo &STI);52void lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,53const MCSubtargetInfo &STI);54void lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,55const MCSubtargetInfo &STI);5657void emitInstruction(const MachineInstr *MI) override;5859static const char *getRegisterName(MCRegister Reg) {60return VEInstPrinter::getRegisterName(Reg);61}62void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS);63bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,64const char *ExtraCode, raw_ostream &O) override;65bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,66const char *ExtraCode, raw_ostream &O) override;67};68} // end of anonymous namespace6970static MCOperand createVEMCOperand(VEMCExpr::VariantKind Kind, MCSymbol *Sym,71MCContext &OutContext) {72const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, OutContext);73const VEMCExpr *expr = VEMCExpr::create(Kind, MCSym, OutContext);74return MCOperand::createExpr(expr);75}7677static MCOperand createGOTRelExprOp(VEMCExpr::VariantKind Kind,78MCSymbol *GOTLabel, MCContext &OutContext) {79const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);80const VEMCExpr *expr = VEMCExpr::create(Kind, GOT, OutContext);81return MCOperand::createExpr(expr);82}8384static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD,85const MCSubtargetInfo &STI) {86MCInst SICInst;87SICInst.setOpcode(VE::SIC);88SICInst.addOperand(RD);89OutStreamer.emitInstruction(SICInst, STI);90}9192static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2,93const MCSubtargetInfo &STI) {94MCInst BSICInst;95BSICInst.setOpcode(VE::BSICrii);96BSICInst.addOperand(R1);97BSICInst.addOperand(R2);98MCOperand czero = MCOperand::createImm(0);99BSICInst.addOperand(czero);100BSICInst.addOperand(czero);101OutStreamer.emitInstruction(BSICInst, STI);102}103104static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,105const MCSubtargetInfo &STI) {106MCInst LEAInst;107LEAInst.setOpcode(VE::LEAzii);108LEAInst.addOperand(RD);109MCOperand CZero = MCOperand::createImm(0);110LEAInst.addOperand(CZero);111LEAInst.addOperand(CZero);112LEAInst.addOperand(Imm);113OutStreamer.emitInstruction(LEAInst, STI);114}115116static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,117const MCSubtargetInfo &STI) {118MCInst LEASLInst;119LEASLInst.setOpcode(VE::LEASLzii);120LEASLInst.addOperand(RD);121MCOperand CZero = MCOperand::createImm(0);122LEASLInst.addOperand(CZero);123LEASLInst.addOperand(CZero);124LEASLInst.addOperand(Imm);125OutStreamer.emitInstruction(LEASLInst, STI);126}127128static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,129MCOperand &RD, const MCSubtargetInfo &STI) {130MCInst LEAInst;131LEAInst.setOpcode(VE::LEAzii);132LEAInst.addOperand(RD);133MCOperand CZero = MCOperand::createImm(0);134LEAInst.addOperand(CZero);135LEAInst.addOperand(RS1);136LEAInst.addOperand(Imm);137OutStreamer.emitInstruction(LEAInst, STI);138}139140static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1,141MCOperand &RS2, MCOperand &Imm, MCOperand &RD,142const MCSubtargetInfo &STI) {143MCInst LEASLInst;144LEASLInst.setOpcode(VE::LEASLrri);145LEASLInst.addOperand(RD);146LEASLInst.addOperand(RS1);147LEASLInst.addOperand(RS2);148LEASLInst.addOperand(Imm);149OutStreamer.emitInstruction(LEASLInst, STI);150}151152static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1,153MCOperand &Src2, MCOperand &RD,154const MCSubtargetInfo &STI) {155MCInst Inst;156Inst.setOpcode(Opcode);157Inst.addOperand(RD);158Inst.addOperand(RS1);159Inst.addOperand(Src2);160OutStreamer.emitInstruction(Inst, STI);161}162163static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,164MCOperand &RD, const MCSubtargetInfo &STI) {165emitBinary(OutStreamer, VE::ANDrm, RS1, Imm, RD, STI);166}167168static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,169VEMCExpr::VariantKind HiKind, VEMCExpr::VariantKind LoKind,170MCOperand &RD, MCContext &OutContext,171const MCSubtargetInfo &STI) {172173MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext);174MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext);175emitLEAzzi(OutStreamer, lo, RD, STI);176MCOperand M032 = MCOperand::createImm(M0(32));177emitANDrm(OutStreamer, RD, M032, RD, STI);178emitLEASLzzi(OutStreamer, hi, RD, STI);179}180181void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,182const MCSubtargetInfo &STI) {183MCSymbol *GOTLabel =184OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));185186const MachineOperand &MO = MI->getOperand(0);187MCOperand MCRegOP = MCOperand::createReg(MO.getReg());188189if (!isPositionIndependent()) {190// Just load the address of GOT to MCRegOP.191switch (TM.getCodeModel()) {192default:193llvm_unreachable("Unsupported absolute code model");194case CodeModel::Small:195case CodeModel::Medium:196case CodeModel::Large:197emitHiLo(*OutStreamer, GOTLabel, VEMCExpr::VK_VE_HI32,198VEMCExpr::VK_VE_LO32, MCRegOP, OutContext, STI);199break;200}201return;202}203204MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT205MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT206207// lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24)208// and %got, %got, (32)0209// sic %plt210// lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%plt, %got)211MCOperand cim24 = MCOperand::createImm(-24);212MCOperand loImm =213createGOTRelExprOp(VEMCExpr::VK_VE_PC_LO32, GOTLabel, OutContext);214emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);215MCOperand M032 = MCOperand::createImm(M0(32));216emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);217emitSIC(*OutStreamer, RegPLT, STI);218MCOperand hiImm =219createGOTRelExprOp(VEMCExpr::VK_VE_PC_HI32, GOTLabel, OutContext);220emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI);221}222223void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,224const MCSubtargetInfo &STI) {225const MachineOperand &MO = MI->getOperand(0);226MCOperand MCRegOP = MCOperand::createReg(MO.getReg());227const MachineOperand &Addr = MI->getOperand(1);228MCSymbol *AddrSym = nullptr;229230switch (Addr.getType()) {231default:232llvm_unreachable("<unknown operand type>");233return;234case MachineOperand::MO_MachineBasicBlock:235report_fatal_error("MBB is not supported yet");236return;237case MachineOperand::MO_ConstantPoolIndex:238report_fatal_error("ConstantPool is not supported yet");239return;240case MachineOperand::MO_ExternalSymbol:241AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());242break;243case MachineOperand::MO_GlobalAddress:244AddrSym = getSymbol(Addr.getGlobal());245break;246}247248if (!isPositionIndependent()) {249llvm_unreachable("Unsupported uses of %plt in not PIC code");250return;251}252253MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT254255// lea %dst, func@plt_lo(-24)256// and %dst, %dst, (32)0257// sic %plt ; FIXME: is it safe to use %plt here?258// lea.sl %dst, func@plt_hi(%plt, %dst)259MCOperand cim24 = MCOperand::createImm(-24);260MCOperand loImm =261createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, AddrSym, OutContext);262emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);263MCOperand M032 = MCOperand::createImm(M0(32));264emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);265emitSIC(*OutStreamer, RegPLT, STI);266MCOperand hiImm =267createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, AddrSym, OutContext);268emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI);269}270271void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,272const MCSubtargetInfo &STI) {273const MachineOperand &Addr = MI->getOperand(0);274MCSymbol *AddrSym = nullptr;275276switch (Addr.getType()) {277default:278llvm_unreachable("<unknown operand type>");279return;280case MachineOperand::MO_MachineBasicBlock:281report_fatal_error("MBB is not supported yet");282return;283case MachineOperand::MO_ConstantPoolIndex:284report_fatal_error("ConstantPool is not supported yet");285return;286case MachineOperand::MO_ExternalSymbol:287AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());288break;289case MachineOperand::MO_GlobalAddress:290AddrSym = getSymbol(Addr.getGlobal());291break;292}293294MCOperand RegLR = MCOperand::createReg(VE::SX10); // LR295MCOperand RegS0 = MCOperand::createReg(VE::SX0); // S0296MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12297MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr"));298299// lea %s0, sym@tls_gd_lo(-24)300// and %s0, %s0, (32)0301// sic %lr302// lea.sl %s0, sym@tls_gd_hi(%lr, %s0)303// lea %s12, __tls_get_addr@plt_lo(8)304// and %s12, %s12, (32)0305// lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr)306// bsic %lr, (, %s12)307MCOperand cim24 = MCOperand::createImm(-24);308MCOperand loImm =309createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_LO32, AddrSym, OutContext);310emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI);311MCOperand M032 = MCOperand::createImm(M0(32));312emitANDrm(*OutStreamer, RegS0, M032, RegS0, STI);313emitSIC(*OutStreamer, RegLR, STI);314MCOperand hiImm =315createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_HI32, AddrSym, OutContext);316emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI);317MCOperand ci8 = MCOperand::createImm(8);318MCOperand loImm2 =319createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, GetTLSLabel, OutContext);320emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI);321emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI);322MCOperand hiImm2 =323createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, GetTLSLabel, OutContext);324emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI);325emitBSIC(*OutStreamer, RegLR, RegS12, STI);326}327328void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {329VE_MC::verifyInstructionPredicates(MI->getOpcode(),330getSubtargetInfo().getFeatureBits());331332switch (MI->getOpcode()) {333default:334break;335case TargetOpcode::DBG_VALUE:336// FIXME: Debug Value.337return;338case VE::GETGOT:339lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo());340return;341case VE::GETFUNPLT:342lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo());343return;344case VE::GETTLSADDR:345lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo());346return;347}348349MachineBasicBlock::const_instr_iterator I = MI->getIterator();350MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();351do {352MCInst TmpInst;353LowerVEMachineInstrToMCInst(&*I, TmpInst, *this);354EmitToStreamer(*OutStreamer, TmpInst);355} while ((++I != E) && I->isInsideBundle()); // Delay slot check.356}357358void VEAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,359raw_ostream &O) {360const MachineOperand &MO = MI->getOperand(OpNum);361362switch (MO.getType()) {363case MachineOperand::MO_Register:364O << "%" << StringRef(getRegisterName(MO.getReg())).lower();365break;366case MachineOperand::MO_Immediate:367O << (int)MO.getImm();368break;369default:370llvm_unreachable("<unknown operand type>");371}372}373374// PrintAsmOperand - Print out an operand for an inline asm expression.375bool VEAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,376const char *ExtraCode, raw_ostream &O) {377if (ExtraCode && ExtraCode[0]) {378if (ExtraCode[1] != 0)379return true; // Unknown modifier.380381switch (ExtraCode[0]) {382default:383// See if this is a generic print operand384return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);385case 'r':386case 'v':387break;388}389}390391printOperand(MI, OpNo, O);392393return false;394}395396bool VEAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,397const char *ExtraCode,398raw_ostream &O) {399if (ExtraCode && ExtraCode[0])400return true; // Unknown modifier401402if (MI->getOperand(OpNo+1).isImm() &&403MI->getOperand(OpNo+1).getImm() == 0) {404// don't print "+0"405} else {406printOperand(MI, OpNo+1, O);407}408if (MI->getOperand(OpNo).isImm() &&409MI->getOperand(OpNo).getImm() == 0) {410if (MI->getOperand(OpNo+1).isImm() &&411MI->getOperand(OpNo+1).getImm() == 0) {412O << "0";413} else {414// don't print "(0)"415}416} else {417O << "(";418printOperand(MI, OpNo, O);419O << ")";420}421return false;422}423424// Force static initialization.425extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmPrinter() {426RegisterAsmPrinter<VEAsmPrinter> X(getTheVETarget());427}428429430