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