[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / VE / VEAsmPrinter.cpp
blob08a75b6b8c550e9ae5f72884c798e2b8eb25b5c1
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 "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;
37 #define DEBUG_TYPE "ve-asmprinter"
39 namespace {
40 class VEAsmPrinter : public AsmPrinter {
41 VETargetStreamer &getTargetStreamer() {
42 return static_cast<VETargetStreamer &>(*OutStreamer->getTargetStreamer());
45 public:
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);
63 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS);
64 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
65 const char *ExtraCode, raw_ostream &O) override;
67 } // end of anonymous namespace
69 static MCOperand createVEMCOperand(VEMCExpr::VariantKind Kind, MCSymbol *Sym,
70 MCContext &OutContext) {
71 const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, OutContext);
72 const VEMCExpr *expr = VEMCExpr::create(Kind, MCSym, OutContext);
73 return MCOperand::createExpr(expr);
76 static MCOperand createGOTRelExprOp(VEMCExpr::VariantKind Kind,
77 MCSymbol *GOTLabel, MCContext &OutContext) {
78 const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);
79 const VEMCExpr *expr = VEMCExpr::create(Kind, GOT, OutContext);
80 return MCOperand::createExpr(expr);
83 static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD,
84 const MCSubtargetInfo &STI) {
85 MCInst SICInst;
86 SICInst.setOpcode(VE::SIC);
87 SICInst.addOperand(RD);
88 OutStreamer.emitInstruction(SICInst, STI);
91 static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2,
92 const MCSubtargetInfo &STI) {
93 MCInst BSICInst;
94 BSICInst.setOpcode(VE::BSICrii);
95 BSICInst.addOperand(R1);
96 BSICInst.addOperand(R2);
97 MCOperand czero = MCOperand::createImm(0);
98 BSICInst.addOperand(czero);
99 BSICInst.addOperand(czero);
100 OutStreamer.emitInstruction(BSICInst, STI);
103 static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
104 const MCSubtargetInfo &STI) {
105 MCInst LEAInst;
106 LEAInst.setOpcode(VE::LEAzii);
107 LEAInst.addOperand(RD);
108 MCOperand CZero = MCOperand::createImm(0);
109 LEAInst.addOperand(CZero);
110 LEAInst.addOperand(CZero);
111 LEAInst.addOperand(Imm);
112 OutStreamer.emitInstruction(LEAInst, STI);
115 static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
116 const MCSubtargetInfo &STI) {
117 MCInst LEASLInst;
118 LEASLInst.setOpcode(VE::LEASLzii);
119 LEASLInst.addOperand(RD);
120 MCOperand CZero = MCOperand::createImm(0);
121 LEASLInst.addOperand(CZero);
122 LEASLInst.addOperand(CZero);
123 LEASLInst.addOperand(Imm);
124 OutStreamer.emitInstruction(LEASLInst, STI);
127 static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
128 MCOperand &RD, const MCSubtargetInfo &STI) {
129 MCInst LEAInst;
130 LEAInst.setOpcode(VE::LEAzii);
131 LEAInst.addOperand(RD);
132 MCOperand CZero = MCOperand::createImm(0);
133 LEAInst.addOperand(CZero);
134 LEAInst.addOperand(RS1);
135 LEAInst.addOperand(Imm);
136 OutStreamer.emitInstruction(LEAInst, STI);
139 static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1,
140 MCOperand &RS2, MCOperand &Imm, MCOperand &RD,
141 const MCSubtargetInfo &STI) {
142 MCInst LEASLInst;
143 LEASLInst.setOpcode(VE::LEASLrri);
144 LEASLInst.addOperand(RD);
145 LEASLInst.addOperand(RS1);
146 LEASLInst.addOperand(RS2);
147 LEASLInst.addOperand(Imm);
148 OutStreamer.emitInstruction(LEASLInst, STI);
151 static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1,
152 MCOperand &Src2, MCOperand &RD,
153 const MCSubtargetInfo &STI) {
154 MCInst Inst;
155 Inst.setOpcode(Opcode);
156 Inst.addOperand(RD);
157 Inst.addOperand(RS1);
158 Inst.addOperand(Src2);
159 OutStreamer.emitInstruction(Inst, STI);
162 static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
163 MCOperand &RD, const MCSubtargetInfo &STI) {
164 emitBinary(OutStreamer, VE::ANDrm, RS1, Imm, RD, STI);
167 static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
168 VEMCExpr::VariantKind HiKind, VEMCExpr::VariantKind LoKind,
169 MCOperand &RD, MCContext &OutContext,
170 const MCSubtargetInfo &STI) {
172 MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext);
173 MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext);
174 emitLEAzzi(OutStreamer, lo, RD, STI);
175 MCOperand M032 = MCOperand::createImm(M0(32));
176 emitANDrm(OutStreamer, RD, M032, RD, STI);
177 emitLEASLzzi(OutStreamer, hi, RD, STI);
180 void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
181 const MCSubtargetInfo &STI) {
182 MCSymbol *GOTLabel =
183 OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
185 const MachineOperand &MO = MI->getOperand(0);
186 MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
188 if (!isPositionIndependent()) {
189 // Just load the address of GOT to MCRegOP.
190 switch (TM.getCodeModel()) {
191 default:
192 llvm_unreachable("Unsupported absolute code model");
193 case CodeModel::Small:
194 case CodeModel::Medium:
195 case CodeModel::Large:
196 emitHiLo(*OutStreamer, GOTLabel, VEMCExpr::VK_VE_HI32,
197 VEMCExpr::VK_VE_LO32, MCRegOP, OutContext, STI);
198 break;
200 return;
203 MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT
204 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
206 // lea %got, _GLOBAL_OFFSET_TABLE_@PC_LO(-24)
207 // and %got, %got, (32)0
208 // sic %plt
209 // lea.sl %got, _GLOBAL_OFFSET_TABLE_@PC_HI(%plt, %got)
210 MCOperand cim24 = MCOperand::createImm(-24);
211 MCOperand loImm =
212 createGOTRelExprOp(VEMCExpr::VK_VE_PC_LO32, GOTLabel, OutContext);
213 emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
214 MCOperand M032 = MCOperand::createImm(M0(32));
215 emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
216 emitSIC(*OutStreamer, RegPLT, STI);
217 MCOperand hiImm =
218 createGOTRelExprOp(VEMCExpr::VK_VE_PC_HI32, GOTLabel, OutContext);
219 emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI);
222 void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
223 const MCSubtargetInfo &STI) {
224 const MachineOperand &MO = MI->getOperand(0);
225 MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
226 const MachineOperand &Addr = MI->getOperand(1);
227 MCSymbol *AddrSym = nullptr;
229 switch (Addr.getType()) {
230 default:
231 llvm_unreachable("<unknown operand type>");
232 return;
233 case MachineOperand::MO_MachineBasicBlock:
234 report_fatal_error("MBB is not supported yet");
235 return;
236 case MachineOperand::MO_ConstantPoolIndex:
237 report_fatal_error("ConstantPool is not supported yet");
238 return;
239 case MachineOperand::MO_ExternalSymbol:
240 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
241 break;
242 case MachineOperand::MO_GlobalAddress:
243 AddrSym = getSymbol(Addr.getGlobal());
244 break;
247 if (!isPositionIndependent()) {
248 llvm_unreachable("Unsupported uses of %plt in not PIC code");
249 return;
252 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
254 // lea %dst, func@plt_lo(-24)
255 // and %dst, %dst, (32)0
256 // sic %plt ; FIXME: is it safe to use %plt here?
257 // lea.sl %dst, func@plt_hi(%plt, %dst)
258 MCOperand cim24 = MCOperand::createImm(-24);
259 MCOperand loImm =
260 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, AddrSym, OutContext);
261 emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
262 MCOperand M032 = MCOperand::createImm(M0(32));
263 emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
264 emitSIC(*OutStreamer, RegPLT, STI);
265 MCOperand hiImm =
266 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, AddrSym, OutContext);
267 emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI);
270 void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
271 const MCSubtargetInfo &STI) {
272 const MachineOperand &Addr = MI->getOperand(0);
273 MCSymbol *AddrSym = nullptr;
275 switch (Addr.getType()) {
276 default:
277 llvm_unreachable("<unknown operand type>");
278 return;
279 case MachineOperand::MO_MachineBasicBlock:
280 report_fatal_error("MBB is not supported yet");
281 return;
282 case MachineOperand::MO_ConstantPoolIndex:
283 report_fatal_error("ConstantPool is not supported yet");
284 return;
285 case MachineOperand::MO_ExternalSymbol:
286 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
287 break;
288 case MachineOperand::MO_GlobalAddress:
289 AddrSym = getSymbol(Addr.getGlobal());
290 break;
293 MCOperand RegLR = MCOperand::createReg(VE::SX10); // LR
294 MCOperand RegS0 = MCOperand::createReg(VE::SX0); // S0
295 MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12
296 MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr"));
298 // lea %s0, sym@tls_gd_lo(-24)
299 // and %s0, %s0, (32)0
300 // sic %lr
301 // lea.sl %s0, sym@tls_gd_hi(%lr, %s0)
302 // lea %s12, __tls_get_addr@plt_lo(8)
303 // and %s12, %s12, (32)0
304 // lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr)
305 // bsic %lr, (, %s12)
306 MCOperand cim24 = MCOperand::createImm(-24);
307 MCOperand loImm =
308 createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_LO32, AddrSym, OutContext);
309 emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI);
310 MCOperand M032 = MCOperand::createImm(M0(32));
311 emitANDrm(*OutStreamer, RegS0, M032, RegS0, STI);
312 emitSIC(*OutStreamer, RegLR, STI);
313 MCOperand hiImm =
314 createGOTRelExprOp(VEMCExpr::VK_VE_TLS_GD_HI32, AddrSym, OutContext);
315 emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI);
316 MCOperand ci8 = MCOperand::createImm(8);
317 MCOperand loImm2 =
318 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_LO32, GetTLSLabel, OutContext);
319 emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI);
320 emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI);
321 MCOperand hiImm2 =
322 createGOTRelExprOp(VEMCExpr::VK_VE_PLT_HI32, GetTLSLabel, OutContext);
323 emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI);
324 emitBSIC(*OutStreamer, RegLR, RegS12, STI);
327 void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {
329 switch (MI->getOpcode()) {
330 default:
331 break;
332 case TargetOpcode::DBG_VALUE:
333 // FIXME: Debug Value.
334 return;
335 case VE::GETGOT:
336 lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo());
337 return;
338 case VE::GETFUNPLT:
339 lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo());
340 return;
341 case VE::GETTLSADDR:
342 lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo());
343 return;
346 MachineBasicBlock::const_instr_iterator I = MI->getIterator();
347 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
348 do {
349 MCInst TmpInst;
350 LowerVEMachineInstrToMCInst(&*I, TmpInst, *this);
351 EmitToStreamer(*OutStreamer, TmpInst);
352 } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
355 void VEAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
356 raw_ostream &O) {
357 const MachineOperand &MO = MI->getOperand(OpNum);
359 switch (MO.getType()) {
360 case MachineOperand::MO_Register:
361 O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
362 break;
363 default:
364 llvm_unreachable("<unknown operand type>");
368 // PrintAsmOperand - Print out an operand for an inline asm expression.
369 bool VEAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
370 const char *ExtraCode, raw_ostream &O) {
371 if (ExtraCode && ExtraCode[0]) {
372 if (ExtraCode[1] != 0)
373 return true; // Unknown modifier.
375 switch (ExtraCode[0]) {
376 default:
377 // See if this is a generic print operand
378 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
379 case 'r':
380 case 'v':
381 break;
385 printOperand(MI, OpNo, O);
387 return false;
390 // Force static initialization.
391 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmPrinter() {
392 RegisterAsmPrinter<VEAsmPrinter> X(getTheVETarget());