AMDGPU: Mark test as XFAIL in expensive_checks builds
[llvm-project.git] / llvm / lib / Target / VE / VEAsmPrinter.cpp
bloba3435b15f50ef5ea2a5b2d4f456eb8b045a693d1
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.
12 //===----------------------------------------------------------------------===//
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 "llvm/CodeGen/AsmPrinter.h"
21 #include "llvm/CodeGen/MachineInstr.h"
22 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
23 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
24 #include "llvm/IR/Mangler.h"
25 #include "llvm/MC/MCAsmInfo.h"
26 #include "llvm/MC/MCContext.h"
27 #include "llvm/MC/MCInst.h"
28 #include "llvm/MC/MCStreamer.h"
29 #include "llvm/MC/MCSymbol.h"
30 #include "llvm/MC/TargetRegistry.h"
31 #include "llvm/Support/raw_ostream.h"
32 using namespace llvm;
34 #define DEBUG_TYPE "ve-asmprinter"
36 namespace {
37 class VEAsmPrinter : public AsmPrinter {
38 VETargetStreamer &getTargetStreamer() {
39 return static_cast<VETargetStreamer &>(*OutStreamer->getTargetStreamer());
42 public:
43 explicit VEAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
44 : AsmPrinter(TM, std::move(Streamer)) {}
46 StringRef getPassName() const override { return "VE Assembly Printer"; }
48 void lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
49 const MCSubtargetInfo &STI);
50 void lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
51 const MCSubtargetInfo &STI);
52 void lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
53 const MCSubtargetInfo &STI);
55 void emitInstruction(const MachineInstr *MI) override;
57 static const char *getRegisterName(MCRegister Reg) {
58 return VEInstPrinter::getRegisterName(Reg);
60 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS);
61 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
62 const char *ExtraCode, raw_ostream &O) override;
63 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
64 const char *ExtraCode, raw_ostream &O) override;
66 } // end of anonymous namespace
68 static MCOperand createVEMCOperand(VEMCExpr::VariantKind Kind, MCSymbol *Sym,
69 MCContext &OutContext) {
70 const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, OutContext);
71 const VEMCExpr *expr = VEMCExpr::create(Kind, MCSym, OutContext);
72 return MCOperand::createExpr(expr);
75 static MCOperand createGOTRelExprOp(VEMCExpr::VariantKind Kind,
76 MCSymbol *GOTLabel, MCContext &OutContext) {
77 const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);
78 const VEMCExpr *expr = VEMCExpr::create(Kind, GOT, OutContext);
79 return MCOperand::createExpr(expr);
82 static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD,
83 const MCSubtargetInfo &STI) {
84 MCInst SICInst;
85 SICInst.setOpcode(VE::SIC);
86 SICInst.addOperand(RD);
87 OutStreamer.emitInstruction(SICInst, STI);
90 static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2,
91 const MCSubtargetInfo &STI) {
92 MCInst BSICInst;
93 BSICInst.setOpcode(VE::BSICrii);
94 BSICInst.addOperand(R1);
95 BSICInst.addOperand(R2);
96 MCOperand czero = MCOperand::createImm(0);
97 BSICInst.addOperand(czero);
98 BSICInst.addOperand(czero);
99 OutStreamer.emitInstruction(BSICInst, STI);
102 static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
103 const MCSubtargetInfo &STI) {
104 MCInst LEAInst;
105 LEAInst.setOpcode(VE::LEAzii);
106 LEAInst.addOperand(RD);
107 MCOperand CZero = MCOperand::createImm(0);
108 LEAInst.addOperand(CZero);
109 LEAInst.addOperand(CZero);
110 LEAInst.addOperand(Imm);
111 OutStreamer.emitInstruction(LEAInst, STI);
114 static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
115 const MCSubtargetInfo &STI) {
116 MCInst LEASLInst;
117 LEASLInst.setOpcode(VE::LEASLzii);
118 LEASLInst.addOperand(RD);
119 MCOperand CZero = MCOperand::createImm(0);
120 LEASLInst.addOperand(CZero);
121 LEASLInst.addOperand(CZero);
122 LEASLInst.addOperand(Imm);
123 OutStreamer.emitInstruction(LEASLInst, STI);
126 static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
127 MCOperand &RD, const MCSubtargetInfo &STI) {
128 MCInst LEAInst;
129 LEAInst.setOpcode(VE::LEAzii);
130 LEAInst.addOperand(RD);
131 MCOperand CZero = MCOperand::createImm(0);
132 LEAInst.addOperand(CZero);
133 LEAInst.addOperand(RS1);
134 LEAInst.addOperand(Imm);
135 OutStreamer.emitInstruction(LEAInst, STI);
138 static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1,
139 MCOperand &RS2, MCOperand &Imm, MCOperand &RD,
140 const MCSubtargetInfo &STI) {
141 MCInst LEASLInst;
142 LEASLInst.setOpcode(VE::LEASLrri);
143 LEASLInst.addOperand(RD);
144 LEASLInst.addOperand(RS1);
145 LEASLInst.addOperand(RS2);
146 LEASLInst.addOperand(Imm);
147 OutStreamer.emitInstruction(LEASLInst, STI);
150 static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1,
151 MCOperand &Src2, MCOperand &RD,
152 const MCSubtargetInfo &STI) {
153 MCInst Inst;
154 Inst.setOpcode(Opcode);
155 Inst.addOperand(RD);
156 Inst.addOperand(RS1);
157 Inst.addOperand(Src2);
158 OutStreamer.emitInstruction(Inst, STI);
161 static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
162 MCOperand &RD, const MCSubtargetInfo &STI) {
163 emitBinary(OutStreamer, VE::ANDrm, RS1, Imm, RD, STI);
166 static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
167 VEMCExpr::VariantKind HiKind, VEMCExpr::VariantKind LoKind,
168 MCOperand &RD, MCContext &OutContext,
169 const MCSubtargetInfo &STI) {
171 MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext);
172 MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext);
173 emitLEAzzi(OutStreamer, lo, RD, STI);
174 MCOperand M032 = MCOperand::createImm(M0(32));
175 emitANDrm(OutStreamer, RD, M032, RD, STI);
176 emitLEASLzzi(OutStreamer, hi, RD, STI);
179 void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
180 const MCSubtargetInfo &STI) {
181 MCSymbol *GOTLabel =
182 OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
184 const MachineOperand &MO = MI->getOperand(0);
185 MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
187 if (!isPositionIndependent()) {
188 // Just load the address of GOT to MCRegOP.
189 switch (TM.getCodeModel()) {
190 default:
191 llvm_unreachable("Unsupported absolute code model");
192 case CodeModel::Small:
193 case CodeModel::Medium:
194 case CodeModel::Large:
195 emitHiLo(*OutStreamer, GOTLabel, VEMCExpr::VK_VE_HI32,
196 VEMCExpr::VK_VE_LO32, MCRegOP, OutContext, STI);
197 break;
199 return;
202 MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT
203 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
205 // lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24)
206 // and %got, %got, (32)0
207 // sic %plt
208 // lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%plt, %got)
209 MCOperand cim24 = MCOperand::createImm(-24);
210 MCOperand loImm =
211 createGOTRelExprOp(VEMCExpr::VK_VE_PC_LO32, GOTLabel, OutContext);
212 emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
213 MCOperand M032 = MCOperand::createImm(M0(32));
214 emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
215 emitSIC(*OutStreamer, RegPLT, STI);
216 MCOperand hiImm =
217 createGOTRelExprOp(VEMCExpr::VK_VE_PC_HI32, GOTLabel, OutContext);
218 emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI);
221 void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
222 const MCSubtargetInfo &STI) {
223 const MachineOperand &MO = MI->getOperand(0);
224 MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
225 const MachineOperand &Addr = MI->getOperand(1);
226 MCSymbol *AddrSym = nullptr;
228 switch (Addr.getType()) {
229 default:
230 llvm_unreachable("<unknown operand type>");
231 return;
232 case MachineOperand::MO_MachineBasicBlock:
233 report_fatal_error("MBB is not supported yet");
234 return;
235 case MachineOperand::MO_ConstantPoolIndex:
236 report_fatal_error("ConstantPool is not supported yet");
237 return;
238 case MachineOperand::MO_ExternalSymbol:
239 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
240 break;
241 case MachineOperand::MO_GlobalAddress:
242 AddrSym = getSymbol(Addr.getGlobal());
243 break;
246 if (!isPositionIndependent()) {
247 llvm_unreachable("Unsupported uses of %plt in not PIC code");
248 return;
251 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
253 // lea %dst, func@plt_lo(-24)
254 // and %dst, %dst, (32)0
255 // sic %plt ; FIXME: is it safe to use %plt here?
256 // lea.sl %dst, func@plt_hi(%plt, %dst)
257 MCOperand cim24 = MCOperand::createImm(-24);
258 MCOperand loImm =
259 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, AddrSym, OutContext);
260 emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
261 MCOperand M032 = MCOperand::createImm(M0(32));
262 emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
263 emitSIC(*OutStreamer, RegPLT, STI);
264 MCOperand hiImm =
265 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, AddrSym, OutContext);
266 emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI);
269 void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
270 const MCSubtargetInfo &STI) {
271 const MachineOperand &Addr = MI->getOperand(0);
272 MCSymbol *AddrSym = nullptr;
274 switch (Addr.getType()) {
275 default:
276 llvm_unreachable("<unknown operand type>");
277 return;
278 case MachineOperand::MO_MachineBasicBlock:
279 report_fatal_error("MBB is not supported yet");
280 return;
281 case MachineOperand::MO_ConstantPoolIndex:
282 report_fatal_error("ConstantPool is not supported yet");
283 return;
284 case MachineOperand::MO_ExternalSymbol:
285 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
286 break;
287 case MachineOperand::MO_GlobalAddress:
288 AddrSym = getSymbol(Addr.getGlobal());
289 break;
292 MCOperand RegLR = MCOperand::createReg(VE::SX10); // LR
293 MCOperand RegS0 = MCOperand::createReg(VE::SX0); // S0
294 MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12
295 MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr"));
297 // lea %s0, sym@tls_gd_lo(-24)
298 // and %s0, %s0, (32)0
299 // sic %lr
300 // lea.sl %s0, sym@tls_gd_hi(%lr, %s0)
301 // lea %s12, __tls_get_addr@plt_lo(8)
302 // and %s12, %s12, (32)0
303 // lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr)
304 // bsic %lr, (, %s12)
305 MCOperand cim24 = MCOperand::createImm(-24);
306 MCOperand loImm =
307 createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_LO32, AddrSym, OutContext);
308 emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI);
309 MCOperand M032 = MCOperand::createImm(M0(32));
310 emitANDrm(*OutStreamer, RegS0, M032, RegS0, STI);
311 emitSIC(*OutStreamer, RegLR, STI);
312 MCOperand hiImm =
313 createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_HI32, AddrSym, OutContext);
314 emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI);
315 MCOperand ci8 = MCOperand::createImm(8);
316 MCOperand loImm2 =
317 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, GetTLSLabel, OutContext);
318 emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI);
319 emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI);
320 MCOperand hiImm2 =
321 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, GetTLSLabel, OutContext);
322 emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI);
323 emitBSIC(*OutStreamer, RegLR, RegS12, STI);
326 void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {
327 VE_MC::verifyInstructionPredicates(MI->getOpcode(),
328 getSubtargetInfo().getFeatureBits());
330 switch (MI->getOpcode()) {
331 default:
332 break;
333 case TargetOpcode::DBG_VALUE:
334 // FIXME: Debug Value.
335 return;
336 case VE::GETGOT:
337 lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo());
338 return;
339 case VE::GETFUNPLT:
340 lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo());
341 return;
342 case VE::GETTLSADDR:
343 lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo());
344 return;
347 MachineBasicBlock::const_instr_iterator I = MI->getIterator();
348 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
349 do {
350 MCInst TmpInst;
351 LowerVEMachineInstrToMCInst(&*I, TmpInst, *this);
352 EmitToStreamer(*OutStreamer, TmpInst);
353 } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
356 void VEAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
357 raw_ostream &O) {
358 const MachineOperand &MO = MI->getOperand(OpNum);
360 switch (MO.getType()) {
361 case MachineOperand::MO_Register:
362 O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
363 break;
364 case MachineOperand::MO_Immediate:
365 O << (int)MO.getImm();
366 break;
367 default:
368 llvm_unreachable("<unknown operand type>");
372 // PrintAsmOperand - Print out an operand for an inline asm expression.
373 bool VEAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
374 const char *ExtraCode, raw_ostream &O) {
375 if (ExtraCode && ExtraCode[0]) {
376 if (ExtraCode[1] != 0)
377 return true; // Unknown modifier.
379 switch (ExtraCode[0]) {
380 default:
381 // See if this is a generic print operand
382 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
383 case 'r':
384 case 'v':
385 break;
389 printOperand(MI, OpNo, O);
391 return false;
394 bool VEAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
395 const char *ExtraCode,
396 raw_ostream &O) {
397 if (ExtraCode && ExtraCode[0])
398 return true; // Unknown modifier
400 if (MI->getOperand(OpNo+1).isImm() &&
401 MI->getOperand(OpNo+1).getImm() == 0) {
402 // don't print "+0"
403 } else {
404 printOperand(MI, OpNo+1, O);
406 if (MI->getOperand(OpNo).isImm() &&
407 MI->getOperand(OpNo).getImm() == 0) {
408 if (MI->getOperand(OpNo+1).isImm() &&
409 MI->getOperand(OpNo+1).getImm() == 0) {
410 O << "0";
411 } else {
412 // don't print "(0)"
414 } else {
415 O << "(";
416 printOperand(MI, OpNo, O);
417 O << ")";
419 return false;
422 // Force static initialization.
423 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmPrinter() {
424 RegisterAsmPrinter<VEAsmPrinter> X(getTheVETarget());