1 //===-- VEAsmPrinter.cpp - VE LLVM assembly writer ------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to GAS-format VE assembly language.
12 //===----------------------------------------------------------------------===//
14 #include "MCTargetDesc/VEInstPrinter.h"
15 #include "MCTargetDesc/VEMCExpr.h"
16 #include "MCTargetDesc/VETargetStreamer.h"
17 #include "TargetInfo/VETargetInfo.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"
37 #define DEBUG_TYPE "ve-asmprinter"
40 class VEAsmPrinter : public AsmPrinter {
41 VETargetStreamer &getTargetStreamer() {
42 return static_cast<VETargetStreamer &>(*OutStreamer->getTargetStreamer());
46 explicit VEAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
47 : AsmPrinter(TM, std::move(Streamer)) {}
49 StringRef getPassName() const override { return "VE Assembly Printer"; }
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);
58 void emitInstruction(const MachineInstr *MI) override;
60 static const char *getRegisterName(unsigned RegNo) {
61 return VEInstPrinter::getRegisterName(RegNo);
64 } // end of anonymous namespace
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);
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);
80 static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD,
81 const MCSubtargetInfo &STI) {
83 SICInst.setOpcode(VE::SIC);
84 SICInst.addOperand(RD);
85 OutStreamer.emitInstruction(SICInst, STI);
88 static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2,
89 const MCSubtargetInfo &STI) {
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);
100 static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
101 const MCSubtargetInfo &STI) {
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);
112 static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
113 const MCSubtargetInfo &STI) {
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);
124 static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
125 MCOperand &RD, const MCSubtargetInfo &STI) {
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);
136 static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1,
137 MCOperand &RS2, MCOperand &Imm, MCOperand &RD,
138 const MCSubtargetInfo &STI) {
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);
148 static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1,
149 MCOperand &Src2, MCOperand &RD,
150 const MCSubtargetInfo &STI) {
152 Inst.setOpcode(Opcode);
154 Inst.addOperand(RS1);
155 Inst.addOperand(Src2);
156 OutStreamer.emitInstruction(Inst, STI);
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);
164 static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
165 VEMCExpr::VariantKind HiKind, VEMCExpr::VariantKind LoKind,
166 MCOperand &RD, MCContext &OutContext,
167 const MCSubtargetInfo &STI) {
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);
177 void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
178 const MCSubtargetInfo &STI) {
180 OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
182 const MachineOperand &MO = MI->getOperand(0);
183 MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
185 if (!isPositionIndependent()) {
186 // Just load the address of GOT to MCRegOP.
187 switch (TM.getCodeModel()) {
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);
200 MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT
201 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
203 // lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24)
204 // and %got, %got, (32)0
206 // lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%got, %plt)
207 MCOperand cim24 = MCOperand::createImm(-24);
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);
215 createGOTRelExprOp(VEMCExpr::VK_VE_PC_HI32, GOTLabel, OutContext);
216 emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI);
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;
226 switch (Addr.getType()) {
228 llvm_unreachable("<unknown operand type>");
230 case MachineOperand::MO_MachineBasicBlock:
231 report_fatal_error("MBB is not supported yet");
233 case MachineOperand::MO_ConstantPoolIndex:
234 report_fatal_error("ConstantPool is not supported yet");
236 case MachineOperand::MO_ExternalSymbol:
237 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
239 case MachineOperand::MO_GlobalAddress:
240 AddrSym = getSymbol(Addr.getGlobal());
244 if (!isPositionIndependent()) {
245 llvm_unreachable("Unsupported uses of %plt in not PIC code");
249 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
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);
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);
263 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, AddrSym, OutContext);
264 emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI);
267 void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
268 const MCSubtargetInfo &STI) {
269 const MachineOperand &Addr = MI->getOperand(0);
270 MCSymbol *AddrSym = nullptr;
272 switch (Addr.getType()) {
274 llvm_unreachable("<unknown operand type>");
276 case MachineOperand::MO_MachineBasicBlock:
277 report_fatal_error("MBB is not supported yet");
279 case MachineOperand::MO_ConstantPoolIndex:
280 report_fatal_error("ConstantPool is not supported yet");
282 case MachineOperand::MO_ExternalSymbol:
283 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
285 case MachineOperand::MO_GlobalAddress:
286 AddrSym = getSymbol(Addr.getGlobal());
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"));
295 // lea %s0, sym@tls_gd_lo(-24)
296 // and %s0, %s0, (32)0
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);
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);
311 createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_HI32, AddrSym, OutContext);
312 emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI);
313 MCOperand ci8 = MCOperand::createImm(8);
315 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, GetTLSLabel, OutContext);
316 emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI);
317 emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI);
319 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, GetTLSLabel, OutContext);
320 emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI);
321 emitBSIC(*OutStreamer, RegLR, RegS12, STI);
324 void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {
326 switch (MI->getOpcode()) {
329 case TargetOpcode::DBG_VALUE:
330 // FIXME: Debug Value.
333 lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo());
336 lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo());
339 lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo());
343 MachineBasicBlock::const_instr_iterator I = MI->getIterator();
344 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
347 LowerVEMachineInstrToMCInst(&*I, TmpInst, *this);
348 EmitToStreamer(*OutStreamer, TmpInst);
349 } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
352 // Force static initialization.
353 extern "C" void LLVMInitializeVEAsmPrinter() {
354 RegisterAsmPrinter<VEAsmPrinter> X(getTheVETarget());