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::BSICrii); 92 BSICInst.addOperand(R1); 93 BSICInst.addOperand(R2); 94 MCOperand czero = MCOperand::createImm(0); 95 BSICInst.addOperand(czero); 96 BSICInst.addOperand(czero); 97 OutStreamer.emitInstruction(BSICInst, STI); 98 } 99 100 static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD, 101 const MCSubtargetInfo &STI) { 102 MCInst LEAInst; 103 LEAInst.setOpcode(VE::LEAzii); 104 LEAInst.addOperand(RD); 105 MCOperand CZero = MCOperand::createImm(0); 106 LEAInst.addOperand(CZero); 107 LEAInst.addOperand(CZero); 108 LEAInst.addOperand(Imm); 109 OutStreamer.emitInstruction(LEAInst, STI); 110 } 111 112 static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD, 113 const MCSubtargetInfo &STI) { 114 MCInst LEASLInst; 115 LEASLInst.setOpcode(VE::LEASLzii); 116 LEASLInst.addOperand(RD); 117 MCOperand CZero = MCOperand::createImm(0); 118 LEASLInst.addOperand(CZero); 119 LEASLInst.addOperand(CZero); 120 LEASLInst.addOperand(Imm); 121 OutStreamer.emitInstruction(LEASLInst, STI); 122 } 123 124 static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, 125 MCOperand &RD, const MCSubtargetInfo &STI) { 126 MCInst LEAInst; 127 LEAInst.setOpcode(VE::LEAzii); 128 LEAInst.addOperand(RD); 129 MCOperand CZero = MCOperand::createImm(0); 130 LEAInst.addOperand(CZero); 131 LEAInst.addOperand(RS1); 132 LEAInst.addOperand(Imm); 133 OutStreamer.emitInstruction(LEAInst, STI); 134 } 135 136 static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1, 137 MCOperand &RS2, MCOperand &Imm, MCOperand &RD, 138 const MCSubtargetInfo &STI) { 139 MCInst LEASLInst; 140 LEASLInst.setOpcode(VE::LEASLrri); 141 LEASLInst.addOperand(RD); 142 LEASLInst.addOperand(RS1); 143 LEASLInst.addOperand(RS2); 144 LEASLInst.addOperand(Imm); 145 OutStreamer.emitInstruction(LEASLInst, STI); 146 } 147 148 static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1, 149 MCOperand &Src2, MCOperand &RD, 150 const MCSubtargetInfo &STI) { 151 MCInst Inst; 152 Inst.setOpcode(Opcode); 153 Inst.addOperand(RD); 154 Inst.addOperand(RS1); 155 Inst.addOperand(Src2); 156 OutStreamer.emitInstruction(Inst, STI); 157 } 158 159 static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, 160 MCOperand &RD, const MCSubtargetInfo &STI) { 161 emitBinary(OutStreamer, VE::ANDrm, RS1, Imm, RD, STI); 162 } 163 164 static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym, 165 VEMCExpr::VariantKind HiKind, VEMCExpr::VariantKind LoKind, 166 MCOperand &RD, MCContext &OutContext, 167 const MCSubtargetInfo &STI) { 168 169 MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext); 170 MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext); 171 emitLEAzzi(OutStreamer, lo, RD, STI); 172 MCOperand M032 = MCOperand::createImm(M0(32)); 173 emitANDrm(OutStreamer, RD, M032, RD, STI); 174 emitLEASLzzi(OutStreamer, hi, RD, STI); 175 } 176 177 void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI, 178 const MCSubtargetInfo &STI) { 179 MCSymbol *GOTLabel = 180 OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_")); 181 182 const MachineOperand &MO = MI->getOperand(0); 183 MCOperand MCRegOP = MCOperand::createReg(MO.getReg()); 184 185 if (!isPositionIndependent()) { 186 // Just load the address of GOT to MCRegOP. 187 switch (TM.getCodeModel()) { 188 default: 189 llvm_unreachable("Unsupported absolute code model"); 190 case CodeModel::Small: 191 case CodeModel::Medium: 192 case CodeModel::Large: 193 emitHiLo(*OutStreamer, GOTLabel, VEMCExpr::VK_VE_HI32, 194 VEMCExpr::VK_VE_LO32, MCRegOP, OutContext, STI); 195 break; 196 } 197 return; 198 } 199 200 MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT 201 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT 202 203 // lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24) 204 // and %got, %got, (32)0 205 // sic %plt 206 // lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%got, %plt) 207 MCOperand cim24 = MCOperand::createImm(-24); 208 MCOperand loImm = 209 createGOTRelExprOp(VEMCExpr::VK_VE_PC_LO32, GOTLabel, OutContext); 210 emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI); 211 MCOperand M032 = MCOperand::createImm(M0(32)); 212 emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI); 213 emitSIC(*OutStreamer, RegPLT, STI); 214 MCOperand hiImm = 215 createGOTRelExprOp(VEMCExpr::VK_VE_PC_HI32, GOTLabel, OutContext); 216 emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI); 217 } 218 219 void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI, 220 const MCSubtargetInfo &STI) { 221 const MachineOperand &MO = MI->getOperand(0); 222 MCOperand MCRegOP = MCOperand::createReg(MO.getReg()); 223 const MachineOperand &Addr = MI->getOperand(1); 224 MCSymbol *AddrSym = nullptr; 225 226 switch (Addr.getType()) { 227 default: 228 llvm_unreachable("<unknown operand type>"); 229 return; 230 case MachineOperand::MO_MachineBasicBlock: 231 report_fatal_error("MBB is not supported yet"); 232 return; 233 case MachineOperand::MO_ConstantPoolIndex: 234 report_fatal_error("ConstantPool is not supported yet"); 235 return; 236 case MachineOperand::MO_ExternalSymbol: 237 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName()); 238 break; 239 case MachineOperand::MO_GlobalAddress: 240 AddrSym = getSymbol(Addr.getGlobal()); 241 break; 242 } 243 244 if (!isPositionIndependent()) { 245 llvm_unreachable("Unsupported uses of %plt in not PIC code"); 246 return; 247 } 248 249 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT 250 251 // lea %dst, %plt_lo(func)(-24) 252 // and %dst, %dst, (32)0 253 // sic %plt ; FIXME: is it safe to use %plt here? 254 // lea.sl %dst, %plt_hi(func)(%dst, %plt) 255 MCOperand cim24 = MCOperand::createImm(-24); 256 MCOperand loImm = 257 createGOTRelExprOp(VEMCExpr::VK_VE_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 = 263 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, AddrSym, OutContext); 264 emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI); 265 } 266 267 void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI, 268 const MCSubtargetInfo &STI) { 269 const MachineOperand &Addr = MI->getOperand(0); 270 MCSymbol *AddrSym = nullptr; 271 272 switch (Addr.getType()) { 273 default: 274 llvm_unreachable("<unknown operand type>"); 275 return; 276 case MachineOperand::MO_MachineBasicBlock: 277 report_fatal_error("MBB is not supported yet"); 278 return; 279 case MachineOperand::MO_ConstantPoolIndex: 280 report_fatal_error("ConstantPool is not supported yet"); 281 return; 282 case MachineOperand::MO_ExternalSymbol: 283 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName()); 284 break; 285 case MachineOperand::MO_GlobalAddress: 286 AddrSym = getSymbol(Addr.getGlobal()); 287 break; 288 } 289 290 MCOperand RegLR = MCOperand::createReg(VE::SX10); // LR 291 MCOperand RegS0 = MCOperand::createReg(VE::SX0); // S0 292 MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12 293 MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr")); 294 295 // lea %s0, sym@tls_gd_lo(-24) 296 // and %s0, %s0, (32)0 297 // sic %lr 298 // lea.sl %s0, sym@tls_gd_hi(%s0, %lr) 299 // lea %s12, __tls_get_addr@plt_lo(8) 300 // and %s12, %s12, (32)0 301 // lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr) 302 // bsic %lr, (, %s12) 303 MCOperand cim24 = MCOperand::createImm(-24); 304 MCOperand loImm = 305 createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_LO32, AddrSym, OutContext); 306 emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI); 307 MCOperand M032 = MCOperand::createImm(M0(32)); 308 emitANDrm(*OutStreamer, RegS0, M032, RegS0, STI); 309 emitSIC(*OutStreamer, RegLR, STI); 310 MCOperand hiImm = 311 createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_HI32, AddrSym, OutContext); 312 emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI); 313 MCOperand ci8 = MCOperand::createImm(8); 314 MCOperand loImm2 = 315 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, GetTLSLabel, OutContext); 316 emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI); 317 emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI); 318 MCOperand hiImm2 = 319 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, GetTLSLabel, OutContext); 320 emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI); 321 emitBSIC(*OutStreamer, RegLR, RegS12, STI); 322 } 323 324 void VEAsmPrinter::emitInstruction(const MachineInstr *MI) { 325 326 switch (MI->getOpcode()) { 327 default: 328 break; 329 case TargetOpcode::DBG_VALUE: 330 // FIXME: Debug Value. 331 return; 332 case VE::GETGOT: 333 lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo()); 334 return; 335 case VE::GETFUNPLT: 336 lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo()); 337 return; 338 case VE::GETTLSADDR: 339 lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo()); 340 return; 341 } 342 343 MachineBasicBlock::const_instr_iterator I = MI->getIterator(); 344 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); 345 do { 346 MCInst TmpInst; 347 LowerVEMachineInstrToMCInst(&*I, TmpInst, *this); 348 EmitToStreamer(*OutStreamer, TmpInst); 349 } while ((++I != E) && I->isInsideBundle()); // Delay slot check. 350 } 351 352 // Force static initialization. 353 extern "C" void LLVMInitializeVEAsmPrinter() { 354 RegisterAsmPrinter<VEAsmPrinter> X(getTheVETarget()); 355 } 356