426 lines · cpp
1//===-- VEAsmPrinter.cpp - VE LLVM assembly writer ------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains a printer that converts from our internal representation10// of machine-dependent LLVM code to GAS-format VE assembly language.11//12//===----------------------------------------------------------------------===//13 14#include "MCTargetDesc/VEInstPrinter.h"15#include "MCTargetDesc/VEMCAsmInfo.h"16#include "MCTargetDesc/VETargetStreamer.h"17#include "TargetInfo/VETargetInfo.h"18#include "VE.h"19#include "VEInstrInfo.h"20#include "llvm/CodeGen/AsmPrinter.h"21#include "llvm/CodeGen/MachineInstr.h"22#include "llvm/CodeGen/MachineModuleInfoImpls.h"23#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"24#include "llvm/IR/Mangler.h"25#include "llvm/MC/MCAsmInfo.h"26#include "llvm/MC/MCContext.h"27#include "llvm/MC/MCInst.h"28#include "llvm/MC/MCStreamer.h"29#include "llvm/MC/MCSymbol.h"30#include "llvm/MC/TargetRegistry.h"31#include "llvm/Support/Compiler.h"32#include "llvm/Support/raw_ostream.h"33using namespace llvm;34 35#define DEBUG_TYPE "ve-asmprinter"36 37namespace {38class VEAsmPrinter : public AsmPrinter {39 VETargetStreamer &getTargetStreamer() {40 return static_cast<VETargetStreamer &>(*OutStreamer->getTargetStreamer());41 }42 43public:44 explicit VEAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)45 : AsmPrinter(TM, std::move(Streamer), ID) {}46 47 StringRef getPassName() const override { return "VE Assembly Printer"; }48 49 void lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,50 const MCSubtargetInfo &STI);51 void lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,52 const MCSubtargetInfo &STI);53 void lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,54 const MCSubtargetInfo &STI);55 56 void emitInstruction(const MachineInstr *MI) override;57 58 static const char *getRegisterName(MCRegister Reg) {59 return VEInstPrinter::getRegisterName(Reg);60 }61 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS);62 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,63 const char *ExtraCode, raw_ostream &O) override;64 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,65 const char *ExtraCode, raw_ostream &O) override;66 67 static char ID;68};69} // end of anonymous namespace70 71static MCOperand createVEMCOperand(VE::Specifier Kind, MCSymbol *Sym,72 MCContext &OutContext) {73 const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, OutContext);74 return MCOperand::createExpr(75 MCSpecifierExpr::create(MCSym, Kind, OutContext));76}77 78static MCOperand createGOTRelExprOp(VE::Specifier Kind, MCSymbol *GOTLabel,79 MCContext &OutContext) {80 const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);81 return MCOperand::createExpr(MCSpecifierExpr::create(GOT, Kind, OutContext));82}83 84static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD,85 const MCSubtargetInfo &STI) {86 MCInst SICInst;87 SICInst.setOpcode(VE::SIC);88 SICInst.addOperand(RD);89 OutStreamer.emitInstruction(SICInst, STI);90}91 92static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2,93 const MCSubtargetInfo &STI) {94 MCInst BSICInst;95 BSICInst.setOpcode(VE::BSICrii);96 BSICInst.addOperand(R1);97 BSICInst.addOperand(R2);98 MCOperand czero = MCOperand::createImm(0);99 BSICInst.addOperand(czero);100 BSICInst.addOperand(czero);101 OutStreamer.emitInstruction(BSICInst, STI);102}103 104static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,105 const MCSubtargetInfo &STI) {106 MCInst LEAInst;107 LEAInst.setOpcode(VE::LEAzii);108 LEAInst.addOperand(RD);109 MCOperand CZero = MCOperand::createImm(0);110 LEAInst.addOperand(CZero);111 LEAInst.addOperand(CZero);112 LEAInst.addOperand(Imm);113 OutStreamer.emitInstruction(LEAInst, STI);114}115 116static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,117 const MCSubtargetInfo &STI) {118 MCInst LEASLInst;119 LEASLInst.setOpcode(VE::LEASLzii);120 LEASLInst.addOperand(RD);121 MCOperand CZero = MCOperand::createImm(0);122 LEASLInst.addOperand(CZero);123 LEASLInst.addOperand(CZero);124 LEASLInst.addOperand(Imm);125 OutStreamer.emitInstruction(LEASLInst, STI);126}127 128static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,129 MCOperand &RD, const MCSubtargetInfo &STI) {130 MCInst LEAInst;131 LEAInst.setOpcode(VE::LEAzii);132 LEAInst.addOperand(RD);133 MCOperand CZero = MCOperand::createImm(0);134 LEAInst.addOperand(CZero);135 LEAInst.addOperand(RS1);136 LEAInst.addOperand(Imm);137 OutStreamer.emitInstruction(LEAInst, STI);138}139 140static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1,141 MCOperand &RS2, MCOperand &Imm, MCOperand &RD,142 const MCSubtargetInfo &STI) {143 MCInst LEASLInst;144 LEASLInst.setOpcode(VE::LEASLrri);145 LEASLInst.addOperand(RD);146 LEASLInst.addOperand(RS1);147 LEASLInst.addOperand(RS2);148 LEASLInst.addOperand(Imm);149 OutStreamer.emitInstruction(LEASLInst, STI);150}151 152static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1,153 MCOperand &Src2, MCOperand &RD,154 const MCSubtargetInfo &STI) {155 MCInst Inst;156 Inst.setOpcode(Opcode);157 Inst.addOperand(RD);158 Inst.addOperand(RS1);159 Inst.addOperand(Src2);160 OutStreamer.emitInstruction(Inst, STI);161}162 163static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,164 MCOperand &RD, const MCSubtargetInfo &STI) {165 emitBinary(OutStreamer, VE::ANDrm, RS1, Imm, RD, STI);166}167 168static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,169 VE::Specifier HiKind, VE::Specifier LoKind, MCOperand &RD,170 MCContext &OutContext, const MCSubtargetInfo &STI) {171 172 MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext);173 MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext);174 emitLEAzzi(OutStreamer, lo, RD, STI);175 MCOperand M032 = MCOperand::createImm(M0(32));176 emitANDrm(OutStreamer, RD, M032, RD, STI);177 emitLEASLzzi(OutStreamer, hi, RD, STI);178}179 180void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,181 const MCSubtargetInfo &STI) {182 MCSymbol *GOTLabel =183 OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));184 185 const MachineOperand &MO = MI->getOperand(0);186 MCOperand MCRegOP = MCOperand::createReg(MO.getReg());187 188 if (!isPositionIndependent()) {189 // Just load the address of GOT to MCRegOP.190 switch (TM.getCodeModel()) {191 default:192 llvm_unreachable("Unsupported absolute code model");193 case CodeModel::Small:194 case CodeModel::Medium:195 case CodeModel::Large:196 emitHiLo(*OutStreamer, GOTLabel, VE::S_HI32, VE::S_LO32, MCRegOP,197 OutContext, STI);198 break;199 }200 return;201 }202 203 MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT204 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT205 206 // lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24)207 // and %got, %got, (32)0208 // sic %plt209 // lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%plt, %got)210 MCOperand cim24 = MCOperand::createImm(-24);211 MCOperand loImm = createGOTRelExprOp(VE::S_PC_LO32, GOTLabel, OutContext);212 emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);213 MCOperand M032 = MCOperand::createImm(M0(32));214 emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);215 emitSIC(*OutStreamer, RegPLT, STI);216 MCOperand hiImm = createGOTRelExprOp(VE::S_PC_HI32, GOTLabel, OutContext);217 emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI);218}219 220void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,221 const MCSubtargetInfo &STI) {222 const MachineOperand &MO = MI->getOperand(0);223 MCOperand MCRegOP = MCOperand::createReg(MO.getReg());224 const MachineOperand &Addr = MI->getOperand(1);225 MCSymbol *AddrSym = nullptr;226 227 switch (Addr.getType()) {228 default:229 llvm_unreachable("<unknown operand type>");230 return;231 case MachineOperand::MO_MachineBasicBlock:232 report_fatal_error("MBB is not supported yet");233 return;234 case MachineOperand::MO_ConstantPoolIndex:235 report_fatal_error("ConstantPool is not supported yet");236 return;237 case MachineOperand::MO_ExternalSymbol:238 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());239 break;240 case MachineOperand::MO_GlobalAddress:241 AddrSym = getSymbol(Addr.getGlobal());242 break;243 }244 245 if (!isPositionIndependent()) {246 llvm_unreachable("Unsupported uses of %plt in not PIC code");247 return;248 }249 250 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT251 252 // lea %dst, func@plt_lo(-24)253 // and %dst, %dst, (32)0254 // sic %plt ; FIXME: is it safe to use %plt here?255 // lea.sl %dst, func@plt_hi(%plt, %dst)256 MCOperand cim24 = MCOperand::createImm(-24);257 MCOperand loImm = createGOTRelExprOp(VE::S_PLT_LO32, AddrSym, OutContext);258 emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);259 MCOperand M032 = MCOperand::createImm(M0(32));260 emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);261 emitSIC(*OutStreamer, RegPLT, STI);262 MCOperand hiImm = createGOTRelExprOp(VE::S_PLT_HI32, AddrSym, OutContext);263 emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI);264}265 266void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,267 const MCSubtargetInfo &STI) {268 const MachineOperand &Addr = MI->getOperand(0);269 MCSymbol *AddrSym = nullptr;270 271 switch (Addr.getType()) {272 default:273 llvm_unreachable("<unknown operand type>");274 return;275 case MachineOperand::MO_MachineBasicBlock:276 report_fatal_error("MBB is not supported yet");277 return;278 case MachineOperand::MO_ConstantPoolIndex:279 report_fatal_error("ConstantPool is not supported yet");280 return;281 case MachineOperand::MO_ExternalSymbol:282 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());283 break;284 case MachineOperand::MO_GlobalAddress:285 AddrSym = getSymbol(Addr.getGlobal());286 break;287 }288 289 MCOperand RegLR = MCOperand::createReg(VE::SX10); // LR290 MCOperand RegS0 = MCOperand::createReg(VE::SX0); // S0291 MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12292 MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr"));293 294 // lea %s0, sym@tls_gd_lo(-24)295 // and %s0, %s0, (32)0296 // sic %lr297 // lea.sl %s0, sym@tls_gd_hi(%lr, %s0)298 // lea %s12, __tls_get_addr@plt_lo(8)299 // and %s12, %s12, (32)0300 // lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr)301 // bsic %lr, (, %s12)302 MCOperand cim24 = MCOperand::createImm(-24);303 MCOperand loImm = createGOTRelExprOp(VE::S_TLS_GD_LO32, AddrSym, OutContext);304 emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI);305 MCOperand M032 = MCOperand::createImm(M0(32));306 emitANDrm(*OutStreamer, RegS0, M032, RegS0, STI);307 emitSIC(*OutStreamer, RegLR, STI);308 MCOperand hiImm = createGOTRelExprOp(VE::S_TLS_GD_HI32, AddrSym, OutContext);309 emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI);310 MCOperand ci8 = MCOperand::createImm(8);311 MCOperand loImm2 =312 createGOTRelExprOp(VE::S_PLT_LO32, GetTLSLabel, OutContext);313 emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI);314 emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI);315 MCOperand hiImm2 =316 createGOTRelExprOp(VE::S_PLT_HI32, GetTLSLabel, OutContext);317 emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI);318 emitBSIC(*OutStreamer, RegLR, RegS12, STI);319}320 321void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {322 VE_MC::verifyInstructionPredicates(MI->getOpcode(),323 getSubtargetInfo().getFeatureBits());324 325 switch (MI->getOpcode()) {326 default:327 break;328 case TargetOpcode::DBG_VALUE:329 // FIXME: Debug Value.330 return;331 case VE::GETGOT:332 lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo());333 return;334 case VE::GETFUNPLT:335 lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo());336 return;337 case VE::GETTLSADDR:338 lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo());339 return;340 }341 342 MachineBasicBlock::const_instr_iterator I = MI->getIterator();343 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();344 do {345 MCInst TmpInst;346 LowerVEMachineInstrToMCInst(&*I, TmpInst, *this);347 EmitToStreamer(*OutStreamer, TmpInst);348 } while ((++I != E) && I->isInsideBundle()); // Delay slot check.349}350 351void VEAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,352 raw_ostream &O) {353 const MachineOperand &MO = MI->getOperand(OpNum);354 355 switch (MO.getType()) {356 case MachineOperand::MO_Register:357 O << "%" << StringRef(getRegisterName(MO.getReg())).lower();358 break;359 case MachineOperand::MO_Immediate:360 O << (int)MO.getImm();361 break;362 default:363 llvm_unreachable("<unknown operand type>");364 }365}366 367// PrintAsmOperand - Print out an operand for an inline asm expression.368bool VEAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,369 const char *ExtraCode, raw_ostream &O) {370 if (ExtraCode && ExtraCode[0]) {371 if (ExtraCode[1] != 0)372 return true; // Unknown modifier.373 374 switch (ExtraCode[0]) {375 default:376 // See if this is a generic print operand377 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);378 case 'r':379 case 'v':380 break;381 }382 }383 384 printOperand(MI, OpNo, O);385 386 return false;387}388 389bool VEAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,390 const char *ExtraCode,391 raw_ostream &O) {392 if (ExtraCode && ExtraCode[0])393 return true; // Unknown modifier394 395 if (MI->getOperand(OpNo+1).isImm() &&396 MI->getOperand(OpNo+1).getImm() == 0) {397 // don't print "+0"398 } else {399 printOperand(MI, OpNo+1, O);400 }401 if (MI->getOperand(OpNo).isImm() &&402 MI->getOperand(OpNo).getImm() == 0) {403 if (MI->getOperand(OpNo+1).isImm() &&404 MI->getOperand(OpNo+1).getImm() == 0) {405 O << "0";406 } else {407 // don't print "(0)"408 }409 } else {410 O << "(";411 printOperand(MI, OpNo, O);412 O << ")";413 }414 return false;415}416 417char VEAsmPrinter::ID = 0;418 419INITIALIZE_PASS(VEAsmPrinter, "ve-asm-printer", "VE Assembly Printer", false,420 false)421 422// Force static initialization.423extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmPrinter() {424 RegisterAsmPrinter<VEAsmPrinter> X(getTheVETarget());425}426