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 "InstPrinter/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 55 void emitInstruction(const MachineInstr *MI) override; 56 57 static const char *getRegisterName(unsigned RegNo) { 58 return VEInstPrinter::getRegisterName(RegNo); 59 } 60 }; 61 } // end of anonymous namespace 62 63 static MCOperand createVEMCOperand(VEMCExpr::VariantKind Kind, MCSymbol *Sym, 64 MCContext &OutContext) { 65 const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, OutContext); 66 const VEMCExpr *expr = VEMCExpr::create(Kind, MCSym, OutContext); 67 return MCOperand::createExpr(expr); 68 } 69 70 static MCOperand createGOTRelExprOp(VEMCExpr::VariantKind Kind, 71 MCSymbol *GOTLabel, MCContext &OutContext) { 72 const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext); 73 const VEMCExpr *expr = VEMCExpr::create(Kind, GOT, OutContext); 74 return MCOperand::createExpr(expr); 75 } 76 77 static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD, 78 const MCSubtargetInfo &STI) { 79 MCInst SICInst; 80 SICInst.setOpcode(VE::SIC); 81 SICInst.addOperand(RD); 82 OutStreamer.emitInstruction(SICInst, STI); 83 } 84 85 static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD, 86 const MCSubtargetInfo &STI) { 87 MCInst LEAInst; 88 LEAInst.setOpcode(VE::LEAzzi); 89 LEAInst.addOperand(RD); 90 LEAInst.addOperand(Imm); 91 OutStreamer.emitInstruction(LEAInst, STI); 92 } 93 94 static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD, 95 const MCSubtargetInfo &STI) { 96 MCInst LEASLInst; 97 LEASLInst.setOpcode(VE::LEASLzzi); 98 LEASLInst.addOperand(RD); 99 LEASLInst.addOperand(Imm); 100 OutStreamer.emitInstruction(LEASLInst, STI); 101 } 102 103 static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, 104 MCOperand &RD, const MCSubtargetInfo &STI) { 105 MCInst LEAInst; 106 LEAInst.setOpcode(VE::LEAzii); 107 LEAInst.addOperand(RD); 108 LEAInst.addOperand(RS1); 109 LEAInst.addOperand(Imm); 110 OutStreamer.emitInstruction(LEAInst, STI); 111 } 112 113 static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1, 114 MCOperand &RS2, MCOperand &Imm, MCOperand &RD, 115 const MCSubtargetInfo &STI) { 116 MCInst LEASLInst; 117 LEASLInst.setOpcode(VE::LEASLrri); 118 LEASLInst.addOperand(RS1); 119 LEASLInst.addOperand(RS2); 120 LEASLInst.addOperand(RD); 121 LEASLInst.addOperand(Imm); 122 OutStreamer.emitInstruction(LEASLInst, STI); 123 } 124 125 static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1, 126 MCOperand &Src2, MCOperand &RD, 127 const MCSubtargetInfo &STI) { 128 MCInst Inst; 129 Inst.setOpcode(Opcode); 130 Inst.addOperand(RD); 131 Inst.addOperand(RS1); 132 Inst.addOperand(Src2); 133 OutStreamer.emitInstruction(Inst, STI); 134 } 135 136 static void emitANDrm0(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, 137 MCOperand &RD, const MCSubtargetInfo &STI) { 138 emitBinary(OutStreamer, VE::ANDrm0, RS1, Imm, RD, STI); 139 } 140 141 static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym, 142 VEMCExpr::VariantKind HiKind, VEMCExpr::VariantKind LoKind, 143 MCOperand &RD, MCContext &OutContext, 144 const MCSubtargetInfo &STI) { 145 146 MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext); 147 MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext); 148 MCOperand ci32 = MCOperand::createImm(32); 149 emitLEAzzi(OutStreamer, lo, RD, STI); 150 emitANDrm0(OutStreamer, RD, ci32, RD, STI); 151 emitLEASLzzi(OutStreamer, hi, RD, STI); 152 } 153 154 void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI, 155 const MCSubtargetInfo &STI) { 156 MCSymbol *GOTLabel = 157 OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_")); 158 159 const MachineOperand &MO = MI->getOperand(0); 160 MCOperand MCRegOP = MCOperand::createReg(MO.getReg()); 161 162 if (!isPositionIndependent()) { 163 // Just load the address of GOT to MCRegOP. 164 switch (TM.getCodeModel()) { 165 default: 166 llvm_unreachable("Unsupported absolute code model"); 167 case CodeModel::Small: 168 case CodeModel::Medium: 169 case CodeModel::Large: 170 emitHiLo(*OutStreamer, GOTLabel, VEMCExpr::VK_VE_HI32, 171 VEMCExpr::VK_VE_LO32, MCRegOP, OutContext, STI); 172 break; 173 } 174 return; 175 } 176 177 MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT 178 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT 179 180 // lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24) 181 // and %got, %got, (32)0 182 // sic %plt 183 // lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%got, %plt) 184 MCOperand cim24 = MCOperand::createImm(-24); 185 MCOperand loImm = 186 createGOTRelExprOp(VEMCExpr::VK_VE_PC_LO32, GOTLabel, OutContext); 187 emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI); 188 MCOperand ci32 = MCOperand::createImm(32); 189 emitANDrm0(*OutStreamer, MCRegOP, ci32, MCRegOP, STI); 190 emitSIC(*OutStreamer, RegPLT, STI); 191 MCOperand hiImm = 192 createGOTRelExprOp(VEMCExpr::VK_VE_PC_HI32, GOTLabel, OutContext); 193 emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI); 194 } 195 196 void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI, 197 const MCSubtargetInfo &STI) { 198 const MachineOperand &MO = MI->getOperand(0); 199 MCOperand MCRegOP = MCOperand::createReg(MO.getReg()); 200 const MachineOperand &Addr = MI->getOperand(1); 201 MCSymbol *AddrSym = nullptr; 202 203 switch (Addr.getType()) { 204 default: 205 llvm_unreachable("<unknown operand type>"); 206 return; 207 case MachineOperand::MO_MachineBasicBlock: 208 report_fatal_error("MBB is not supported yet"); 209 return; 210 case MachineOperand::MO_ConstantPoolIndex: 211 report_fatal_error("ConstantPool is not supported yet"); 212 return; 213 case MachineOperand::MO_ExternalSymbol: 214 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName()); 215 break; 216 case MachineOperand::MO_GlobalAddress: 217 AddrSym = getSymbol(Addr.getGlobal()); 218 break; 219 } 220 221 if (!isPositionIndependent()) { 222 llvm_unreachable("Unsupported uses of %plt in not PIC code"); 223 return; 224 } 225 226 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT 227 228 // lea %dst, %plt_lo(func)(-24) 229 // and %dst, %dst, (32)0 230 // sic %plt ; FIXME: is it safe to use %plt here? 231 // lea.sl %dst, %plt_hi(func)(%dst, %plt) 232 MCOperand cim24 = MCOperand::createImm(-24); 233 MCOperand loImm = 234 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, AddrSym, OutContext); 235 emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI); 236 MCOperand ci32 = MCOperand::createImm(32); 237 emitANDrm0(*OutStreamer, MCRegOP, ci32, MCRegOP, STI); 238 emitSIC(*OutStreamer, RegPLT, STI); 239 MCOperand hiImm = 240 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, AddrSym, OutContext); 241 emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI); 242 } 243 244 void VEAsmPrinter::emitInstruction(const MachineInstr *MI) { 245 246 switch (MI->getOpcode()) { 247 default: 248 break; 249 case TargetOpcode::DBG_VALUE: 250 // FIXME: Debug Value. 251 return; 252 case VE::GETGOT: 253 lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo()); 254 return; 255 case VE::GETFUNPLT: 256 lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo()); 257 return; 258 } 259 260 MachineBasicBlock::const_instr_iterator I = MI->getIterator(); 261 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); 262 do { 263 MCInst TmpInst; 264 LowerVEMachineInstrToMCInst(&*I, TmpInst, *this); 265 EmitToStreamer(*OutStreamer, TmpInst); 266 } while ((++I != E) && I->isInsideBundle()); // Delay slot check. 267 } 268 269 // Force static initialization. 270 extern "C" void LLVMInitializeVEAsmPrinter() { 271 RegisterAsmPrinter<VEAsmPrinter> X(getTheVETarget()); 272 } 273