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-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 VE assembly language. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "MCTargetDesc/VEInstPrinter.h" 15 #include "MCTargetDesc/VEMCExpr.h" 16 #include "MCTargetDesc/VETargetStreamer.h" 17 #include "TargetInfo/VETargetInfo.h" 18 #include "VE.h" 19 #include "VEInstrInfo.h" 20 #include "VETargetMachine.h" 21 #include "llvm/CodeGen/AsmPrinter.h" 22 #include "llvm/CodeGen/MachineInstr.h" 23 #include "llvm/CodeGen/MachineModuleInfoImpls.h" 24 #include "llvm/CodeGen/MachineRegisterInfo.h" 25 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 26 #include "llvm/IR/Mangler.h" 27 #include "llvm/MC/MCAsmInfo.h" 28 #include "llvm/MC/MCContext.h" 29 #include "llvm/MC/MCInst.h" 30 #include "llvm/MC/MCInstBuilder.h" 31 #include "llvm/MC/MCStreamer.h" 32 #include "llvm/MC/MCSymbol.h" 33 #include "llvm/Support/TargetRegistry.h" 34 #include "llvm/Support/raw_ostream.h" 35 using namespace llvm; 36 37 #define DEBUG_TYPE "ve-asmprinter" 38 39 namespace { 40 class VEAsmPrinter : public AsmPrinter { 41 VETargetStreamer &getTargetStreamer() { 42 return static_cast<VETargetStreamer &>(*OutStreamer->getTargetStreamer()); 43 } 44 45 public: 46 explicit VEAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer) 47 : AsmPrinter(TM, std::move(Streamer)) {} 48 49 StringRef getPassName() const override { return "VE Assembly Printer"; } 50 51 void lowerGETGOTAndEmitMCInsts(const MachineInstr *MI, 52 const MCSubtargetInfo &STI); 53 void lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI, 54 const MCSubtargetInfo &STI); 55 void lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI, 56 const MCSubtargetInfo &STI); 57 58 void emitInstruction(const MachineInstr *MI) override; 59 60 static const char *getRegisterName(unsigned RegNo) { 61 return VEInstPrinter::getRegisterName(RegNo); 62 } 63 }; 64 } // end of anonymous namespace 65 66 static MCOperand createVEMCOperand(VEMCExpr::VariantKind Kind, MCSymbol *Sym, 67 MCContext &OutContext) { 68 const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, OutContext); 69 const VEMCExpr *expr = VEMCExpr::create(Kind, MCSym, OutContext); 70 return MCOperand::createExpr(expr); 71 } 72 73 static MCOperand createGOTRelExprOp(VEMCExpr::VariantKind Kind, 74 MCSymbol *GOTLabel, MCContext &OutContext) { 75 const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext); 76 const VEMCExpr *expr = VEMCExpr::create(Kind, GOT, OutContext); 77 return MCOperand::createExpr(expr); 78 } 79 80 static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD, 81 const MCSubtargetInfo &STI) { 82 MCInst SICInst; 83 SICInst.setOpcode(VE::SIC); 84 SICInst.addOperand(RD); 85 OutStreamer.emitInstruction(SICInst, STI); 86 } 87 88 static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2, 89 const MCSubtargetInfo &STI) { 90 MCInst BSICInst; 91 BSICInst.setOpcode(VE::BSIC); 92 BSICInst.addOperand(R1); 93 BSICInst.addOperand(R2); 94 OutStreamer.emitInstruction(BSICInst, STI); 95 } 96 97 static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD, 98 const MCSubtargetInfo &STI) { 99 MCInst LEAInst; 100 LEAInst.setOpcode(VE::LEAzii); 101 LEAInst.addOperand(RD); 102 MCOperand CZero = MCOperand::createImm(0); 103 LEAInst.addOperand(CZero); 104 LEAInst.addOperand(CZero); 105 LEAInst.addOperand(Imm); 106 OutStreamer.emitInstruction(LEAInst, STI); 107 } 108 109 static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD, 110 const MCSubtargetInfo &STI) { 111 MCInst LEASLInst; 112 LEASLInst.setOpcode(VE::LEASLzii); 113 LEASLInst.addOperand(RD); 114 MCOperand CZero = MCOperand::createImm(0); 115 LEASLInst.addOperand(CZero); 116 LEASLInst.addOperand(CZero); 117 LEASLInst.addOperand(Imm); 118 OutStreamer.emitInstruction(LEASLInst, STI); 119 } 120 121 static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, 122 MCOperand &RD, const MCSubtargetInfo &STI) { 123 MCInst LEAInst; 124 LEAInst.setOpcode(VE::LEAzii); 125 LEAInst.addOperand(RD); 126 MCOperand CZero = MCOperand::createImm(0); 127 LEAInst.addOperand(CZero); 128 LEAInst.addOperand(RS1); 129 LEAInst.addOperand(Imm); 130 OutStreamer.emitInstruction(LEAInst, STI); 131 } 132 133 static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1, 134 MCOperand &RS2, MCOperand &Imm, MCOperand &RD, 135 const MCSubtargetInfo &STI) { 136 MCInst LEASLInst; 137 LEASLInst.setOpcode(VE::LEASLrri); 138 LEASLInst.addOperand(RD); 139 LEASLInst.addOperand(RS1); 140 LEASLInst.addOperand(RS2); 141 LEASLInst.addOperand(Imm); 142 OutStreamer.emitInstruction(LEASLInst, STI); 143 } 144 145 static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1, 146 MCOperand &Src2, MCOperand &RD, 147 const MCSubtargetInfo &STI) { 148 MCInst Inst; 149 Inst.setOpcode(Opcode); 150 Inst.addOperand(RD); 151 Inst.addOperand(RS1); 152 Inst.addOperand(Src2); 153 OutStreamer.emitInstruction(Inst, STI); 154 } 155 156 static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, 157 MCOperand &RD, const MCSubtargetInfo &STI) { 158 emitBinary(OutStreamer, VE::ANDrm, RS1, Imm, RD, STI); 159 } 160 161 static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym, 162 VEMCExpr::VariantKind HiKind, VEMCExpr::VariantKind LoKind, 163 MCOperand &RD, MCContext &OutContext, 164 const MCSubtargetInfo &STI) { 165 166 MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext); 167 MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext); 168 emitLEAzzi(OutStreamer, lo, RD, STI); 169 MCOperand M032 = MCOperand::createImm(M0(32)); 170 emitANDrm(OutStreamer, RD, M032, RD, STI); 171 emitLEASLzzi(OutStreamer, hi, RD, STI); 172 } 173 174 void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI, 175 const MCSubtargetInfo &STI) { 176 MCSymbol *GOTLabel = 177 OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_")); 178 179 const MachineOperand &MO = MI->getOperand(0); 180 MCOperand MCRegOP = MCOperand::createReg(MO.getReg()); 181 182 if (!isPositionIndependent()) { 183 // Just load the address of GOT to MCRegOP. 184 switch (TM.getCodeModel()) { 185 default: 186 llvm_unreachable("Unsupported absolute code model"); 187 case CodeModel::Small: 188 case CodeModel::Medium: 189 case CodeModel::Large: 190 emitHiLo(*OutStreamer, GOTLabel, VEMCExpr::VK_VE_HI32, 191 VEMCExpr::VK_VE_LO32, MCRegOP, OutContext, STI); 192 break; 193 } 194 return; 195 } 196 197 MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT 198 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT 199 200 // lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24) 201 // and %got, %got, (32)0 202 // sic %plt 203 // lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%got, %plt) 204 MCOperand cim24 = MCOperand::createImm(-24); 205 MCOperand loImm = 206 createGOTRelExprOp(VEMCExpr::VK_VE_PC_LO32, GOTLabel, OutContext); 207 emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI); 208 MCOperand M032 = MCOperand::createImm(M0(32)); 209 emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI); 210 emitSIC(*OutStreamer, RegPLT, STI); 211 MCOperand hiImm = 212 createGOTRelExprOp(VEMCExpr::VK_VE_PC_HI32, GOTLabel, OutContext); 213 emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI); 214 } 215 216 void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI, 217 const MCSubtargetInfo &STI) { 218 const MachineOperand &MO = MI->getOperand(0); 219 MCOperand MCRegOP = MCOperand::createReg(MO.getReg()); 220 const MachineOperand &Addr = MI->getOperand(1); 221 MCSymbol *AddrSym = nullptr; 222 223 switch (Addr.getType()) { 224 default: 225 llvm_unreachable("<unknown operand type>"); 226 return; 227 case MachineOperand::MO_MachineBasicBlock: 228 report_fatal_error("MBB is not supported yet"); 229 return; 230 case MachineOperand::MO_ConstantPoolIndex: 231 report_fatal_error("ConstantPool is not supported yet"); 232 return; 233 case MachineOperand::MO_ExternalSymbol: 234 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName()); 235 break; 236 case MachineOperand::MO_GlobalAddress: 237 AddrSym = getSymbol(Addr.getGlobal()); 238 break; 239 } 240 241 if (!isPositionIndependent()) { 242 llvm_unreachable("Unsupported uses of %plt in not PIC code"); 243 return; 244 } 245 246 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT 247 248 // lea %dst, %plt_lo(func)(-24) 249 // and %dst, %dst, (32)0 250 // sic %plt ; FIXME: is it safe to use %plt here? 251 // lea.sl %dst, %plt_hi(func)(%dst, %plt) 252 MCOperand cim24 = MCOperand::createImm(-24); 253 MCOperand loImm = 254 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, AddrSym, OutContext); 255 emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI); 256 MCOperand M032 = MCOperand::createImm(M0(32)); 257 emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI); 258 emitSIC(*OutStreamer, RegPLT, STI); 259 MCOperand hiImm = 260 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, AddrSym, OutContext); 261 emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI); 262 } 263 264 void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI, 265 const MCSubtargetInfo &STI) { 266 const MachineOperand &Addr = MI->getOperand(0); 267 MCSymbol *AddrSym = nullptr; 268 269 switch (Addr.getType()) { 270 default: 271 llvm_unreachable("<unknown operand type>"); 272 return; 273 case MachineOperand::MO_MachineBasicBlock: 274 report_fatal_error("MBB is not supported yet"); 275 return; 276 case MachineOperand::MO_ConstantPoolIndex: 277 report_fatal_error("ConstantPool is not supported yet"); 278 return; 279 case MachineOperand::MO_ExternalSymbol: 280 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName()); 281 break; 282 case MachineOperand::MO_GlobalAddress: 283 AddrSym = getSymbol(Addr.getGlobal()); 284 break; 285 } 286 287 MCOperand RegLR = MCOperand::createReg(VE::SX10); // LR 288 MCOperand RegS0 = MCOperand::createReg(VE::SX0); // S0 289 MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12 290 MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr")); 291 292 // lea %s0, sym@tls_gd_lo(-24) 293 // and %s0, %s0, (32)0 294 // sic %lr 295 // lea.sl %s0, sym@tls_gd_hi(%s0, %lr) 296 // lea %s12, __tls_get_addr@plt_lo(8) 297 // and %s12, %s12, (32)0 298 // lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr) 299 // bsic %lr, (, %s12) 300 MCOperand cim24 = MCOperand::createImm(-24); 301 MCOperand loImm = 302 createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_LO32, AddrSym, OutContext); 303 emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI); 304 MCOperand M032 = MCOperand::createImm(M0(32)); 305 emitANDrm(*OutStreamer, RegS0, M032, RegS0, STI); 306 emitSIC(*OutStreamer, RegLR, STI); 307 MCOperand hiImm = 308 createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_HI32, AddrSym, OutContext); 309 emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI); 310 MCOperand ci8 = MCOperand::createImm(8); 311 MCOperand loImm2 = 312 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, GetTLSLabel, OutContext); 313 emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI); 314 emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI); 315 MCOperand hiImm2 = 316 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, GetTLSLabel, OutContext); 317 emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI); 318 emitBSIC(*OutStreamer, RegLR, RegS12, STI); 319 } 320 321 void VEAsmPrinter::emitInstruction(const MachineInstr *MI) { 322 323 switch (MI->getOpcode()) { 324 default: 325 break; 326 case TargetOpcode::DBG_VALUE: 327 // FIXME: Debug Value. 328 return; 329 case VE::GETGOT: 330 lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo()); 331 return; 332 case VE::GETFUNPLT: 333 lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo()); 334 return; 335 case VE::GETTLSADDR: 336 lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo()); 337 return; 338 } 339 340 MachineBasicBlock::const_instr_iterator I = MI->getIterator(); 341 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); 342 do { 343 MCInst TmpInst; 344 LowerVEMachineInstrToMCInst(&*I, TmpInst, *this); 345 EmitToStreamer(*OutStreamer, TmpInst); 346 } while ((++I != E) && I->isInsideBundle()); // Delay slot check. 347 } 348 349 // Force static initialization. 350 extern "C" void LLVMInitializeVEAsmPrinter() { 351 RegisterAsmPrinter<VEAsmPrinter> X(getTheVETarget()); 352 } 353