LLVM 22.0.0git
VEAsmPrinter.cpp
Go to the documentation of this file.
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
18#include "VE.h"
19#include "VEInstrInfo.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"
33using namespace llvm;
34
35#define DEBUG_TYPE "ve-asmprinter"
36
37namespace {
38class VEAsmPrinter : public AsmPrinter {
39 VETargetStreamer &getTargetStreamer() {
40 return static_cast<VETargetStreamer &>(*OutStreamer->getTargetStreamer());
41 }
42
43public:
44 explicit VEAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
45 : AsmPrinter(TM, std::move(Streamer), ID) {}
46
47 StringRef getPassName() const override { return "VE Assembly Printer"; }
48
49 void lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
50 const MCSubtargetInfo &STI);
51 void lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
52 const MCSubtargetInfo &STI);
53 void lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
54 const MCSubtargetInfo &STI);
55
56 void emitInstruction(const MachineInstr *MI) override;
57
58 static const char *getRegisterName(MCRegister Reg) {
60 }
61 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS);
62 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
63 const char *ExtraCode, raw_ostream &O) override;
64 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
65 const char *ExtraCode, raw_ostream &O) override;
66
67 static char ID;
68};
69} // end of anonymous namespace
70
72 MCContext &OutContext) {
73 const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym, OutContext);
75 MCSpecifierExpr::create(MCSym, Kind, OutContext));
76}
77
79 MCContext &OutContext) {
80 const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);
81 return MCOperand::createExpr(MCSpecifierExpr::create(GOT, Kind, OutContext));
82}
83
84static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD,
85 const MCSubtargetInfo &STI) {
86 MCInst SICInst;
87 SICInst.setOpcode(VE::SIC);
88 SICInst.addOperand(RD);
89 OutStreamer.emitInstruction(SICInst, STI);
90}
91
92static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2,
93 const MCSubtargetInfo &STI) {
94 MCInst BSICInst;
95 BSICInst.setOpcode(VE::BSICrii);
96 BSICInst.addOperand(R1);
97 BSICInst.addOperand(R2);
99 BSICInst.addOperand(czero);
100 BSICInst.addOperand(czero);
101 OutStreamer.emitInstruction(BSICInst, STI);
102}
103
104static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
105 const MCSubtargetInfo &STI) {
106 MCInst LEAInst;
107 LEAInst.setOpcode(VE::LEAzii);
108 LEAInst.addOperand(RD);
110 LEAInst.addOperand(CZero);
111 LEAInst.addOperand(CZero);
112 LEAInst.addOperand(Imm);
113 OutStreamer.emitInstruction(LEAInst, STI);
114}
115
116static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD,
117 const MCSubtargetInfo &STI) {
118 MCInst LEASLInst;
119 LEASLInst.setOpcode(VE::LEASLzii);
120 LEASLInst.addOperand(RD);
122 LEASLInst.addOperand(CZero);
123 LEASLInst.addOperand(CZero);
124 LEASLInst.addOperand(Imm);
125 OutStreamer.emitInstruction(LEASLInst, STI);
126}
127
128static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
129 MCOperand &RD, const MCSubtargetInfo &STI) {
130 MCInst LEAInst;
131 LEAInst.setOpcode(VE::LEAzii);
132 LEAInst.addOperand(RD);
134 LEAInst.addOperand(CZero);
135 LEAInst.addOperand(RS1);
136 LEAInst.addOperand(Imm);
137 OutStreamer.emitInstruction(LEAInst, STI);
138}
139
140static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1,
141 MCOperand &RS2, MCOperand &Imm, MCOperand &RD,
142 const MCSubtargetInfo &STI) {
143 MCInst LEASLInst;
144 LEASLInst.setOpcode(VE::LEASLrri);
145 LEASLInst.addOperand(RD);
146 LEASLInst.addOperand(RS1);
147 LEASLInst.addOperand(RS2);
148 LEASLInst.addOperand(Imm);
149 OutStreamer.emitInstruction(LEASLInst, STI);
150}
151
152static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1,
153 MCOperand &Src2, MCOperand &RD,
154 const MCSubtargetInfo &STI) {
155 MCInst Inst;
156 Inst.setOpcode(Opcode);
157 Inst.addOperand(RD);
158 Inst.addOperand(RS1);
159 Inst.addOperand(Src2);
160 OutStreamer.emitInstruction(Inst, STI);
161}
162
163static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm,
164 MCOperand &RD, const MCSubtargetInfo &STI) {
165 emitBinary(OutStreamer, VE::ANDrm, RS1, Imm, RD, STI);
166}
167
168static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
169 VE::Specifier HiKind, VE::Specifier LoKind, MCOperand &RD,
170 MCContext &OutContext, const MCSubtargetInfo &STI) {
171
172 MCOperand hi = createVEMCOperand(HiKind, GOTSym, OutContext);
173 MCOperand lo = createVEMCOperand(LoKind, GOTSym, OutContext);
174 emitLEAzzi(OutStreamer, lo, RD, STI);
176 emitANDrm(OutStreamer, RD, M032, RD, STI);
177 emitLEASLzzi(OutStreamer, hi, RD, STI);
178}
179
180void VEAsmPrinter::lowerGETGOTAndEmitMCInsts(const MachineInstr *MI,
181 const MCSubtargetInfo &STI) {
182 MCSymbol *GOTLabel =
183 OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
184
185 const MachineOperand &MO = MI->getOperand(0);
186 MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
187
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:
195 case CodeModel::Large:
196 emitHiLo(*OutStreamer, GOTLabel, VE::S_HI32, VE::S_LO32, MCRegOP,
197 OutContext, STI);
198 break;
199 }
200 return;
201 }
202
203 MCOperand RegGOT = MCOperand::createReg(VE::SX15); // GOT
204 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
205
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 = createGOTRelExprOp(VE::S_PC_LO32, GOTLabel, OutContext);
212 emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
214 emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
215 emitSIC(*OutStreamer, RegPLT, STI);
216 MCOperand hiImm = createGOTRelExprOp(VE::S_PC_HI32, GOTLabel, OutContext);
217 emitLEASLrri(*OutStreamer, RegGOT, RegPLT, hiImm, MCRegOP, STI);
218}
219
220void VEAsmPrinter::lowerGETFunPLTAndEmitMCInsts(const MachineInstr *MI,
221 const MCSubtargetInfo &STI) {
222 const MachineOperand &MO = MI->getOperand(0);
223 MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
224 const MachineOperand &Addr = MI->getOperand(1);
225 MCSymbol *AddrSym = nullptr;
226
227 switch (Addr.getType()) {
228 default:
229 llvm_unreachable("<unknown operand type>");
230 return;
232 report_fatal_error("MBB is not supported yet");
233 return;
235 report_fatal_error("ConstantPool is not supported yet");
236 return;
238 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
239 break;
241 AddrSym = getSymbol(Addr.getGlobal());
242 break;
243 }
244
245 if (!isPositionIndependent()) {
246 llvm_unreachable("Unsupported uses of %plt in not PIC code");
247 return;
248 }
249
250 MCOperand RegPLT = MCOperand::createReg(VE::SX16); // PLT
251
252 // lea %dst, func@plt_lo(-24)
253 // and %dst, %dst, (32)0
254 // sic %plt ; FIXME: is it safe to use %plt here?
255 // lea.sl %dst, func@plt_hi(%plt, %dst)
256 MCOperand cim24 = MCOperand::createImm(-24);
257 MCOperand loImm = createGOTRelExprOp(VE::S_PLT_LO32, AddrSym, OutContext);
258 emitLEAzii(*OutStreamer, cim24, loImm, MCRegOP, STI);
260 emitANDrm(*OutStreamer, MCRegOP, M032, MCRegOP, STI);
261 emitSIC(*OutStreamer, RegPLT, STI);
262 MCOperand hiImm = createGOTRelExprOp(VE::S_PLT_HI32, AddrSym, OutContext);
263 emitLEASLrri(*OutStreamer, MCRegOP, RegPLT, hiImm, MCRegOP, STI);
264}
265
266void VEAsmPrinter::lowerGETTLSAddrAndEmitMCInsts(const MachineInstr *MI,
267 const MCSubtargetInfo &STI) {
268 const MachineOperand &Addr = MI->getOperand(0);
269 MCSymbol *AddrSym = nullptr;
270
271 switch (Addr.getType()) {
272 default:
273 llvm_unreachable("<unknown operand type>");
274 return;
276 report_fatal_error("MBB is not supported yet");
277 return;
279 report_fatal_error("ConstantPool is not supported yet");
280 return;
282 AddrSym = GetExternalSymbolSymbol(Addr.getSymbolName());
283 break;
285 AddrSym = getSymbol(Addr.getGlobal());
286 break;
287 }
288
289 MCOperand RegLR = MCOperand::createReg(VE::SX10); // LR
290 MCOperand RegS0 = MCOperand::createReg(VE::SX0); // S0
291 MCOperand RegS12 = MCOperand::createReg(VE::SX12); // S12
292 MCSymbol *GetTLSLabel = OutContext.getOrCreateSymbol(Twine("__tls_get_addr"));
293
294 // lea %s0, sym@tls_gd_lo(-24)
295 // and %s0, %s0, (32)0
296 // sic %lr
297 // lea.sl %s0, sym@tls_gd_hi(%lr, %s0)
298 // lea %s12, __tls_get_addr@plt_lo(8)
299 // and %s12, %s12, (32)0
300 // lea.sl %s12, __tls_get_addr@plt_hi(%s12, %lr)
301 // bsic %lr, (, %s12)
302 MCOperand cim24 = MCOperand::createImm(-24);
303 MCOperand loImm = createGOTRelExprOp(VE::S_TLS_GD_LO32, AddrSym, OutContext);
304 emitLEAzii(*OutStreamer, cim24, loImm, RegS0, STI);
306 emitANDrm(*OutStreamer, RegS0, M032, RegS0, STI);
307 emitSIC(*OutStreamer, RegLR, STI);
308 MCOperand hiImm = createGOTRelExprOp(VE::S_TLS_GD_HI32, AddrSym, OutContext);
309 emitLEASLrri(*OutStreamer, RegS0, RegLR, hiImm, RegS0, STI);
311 MCOperand loImm2 =
312 createGOTRelExprOp(VE::S_PLT_LO32, GetTLSLabel, OutContext);
313 emitLEAzii(*OutStreamer, ci8, loImm2, RegS12, STI);
314 emitANDrm(*OutStreamer, RegS12, M032, RegS12, STI);
315 MCOperand hiImm2 =
316 createGOTRelExprOp(VE::S_PLT_HI32, GetTLSLabel, OutContext);
317 emitLEASLrri(*OutStreamer, RegS12, RegLR, hiImm2, RegS12, STI);
318 emitBSIC(*OutStreamer, RegLR, RegS12, STI);
319}
320
321void VEAsmPrinter::emitInstruction(const MachineInstr *MI) {
322 VE_MC::verifyInstructionPredicates(MI->getOpcode(),
323 getSubtargetInfo().getFeatureBits());
324
325 switch (MI->getOpcode()) {
326 default:
327 break;
328 case TargetOpcode::DBG_VALUE:
329 // FIXME: Debug Value.
330 return;
331 case VE::GETGOT:
332 lowerGETGOTAndEmitMCInsts(MI, getSubtargetInfo());
333 return;
334 case VE::GETFUNPLT:
335 lowerGETFunPLTAndEmitMCInsts(MI, getSubtargetInfo());
336 return;
337 case VE::GETTLSADDR:
338 lowerGETTLSAddrAndEmitMCInsts(MI, getSubtargetInfo());
339 return;
340 }
341
343 MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
344 do {
345 MCInst TmpInst;
346 LowerVEMachineInstrToMCInst(&*I, TmpInst, *this);
347 EmitToStreamer(*OutStreamer, TmpInst);
348 } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
349}
350
351void VEAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
352 raw_ostream &O) {
353 const MachineOperand &MO = MI->getOperand(OpNum);
354
355 switch (MO.getType()) {
357 O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
358 break;
360 O << (int)MO.getImm();
361 break;
362 default:
363 llvm_unreachable("<unknown operand type>");
364 }
365}
366
367// PrintAsmOperand - Print out an operand for an inline asm expression.
368bool VEAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
369 const char *ExtraCode, raw_ostream &O) {
370 if (ExtraCode && ExtraCode[0]) {
371 if (ExtraCode[1] != 0)
372 return true; // Unknown modifier.
373
374 switch (ExtraCode[0]) {
375 default:
376 // See if this is a generic print operand
377 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
378 case 'r':
379 case 'v':
380 break;
381 }
382 }
383
384 printOperand(MI, OpNo, O);
385
386 return false;
387}
388
389bool VEAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
390 const char *ExtraCode,
391 raw_ostream &O) {
392 if (ExtraCode && ExtraCode[0])
393 return true; // Unknown modifier
394
395 if (MI->getOperand(OpNo+1).isImm() &&
396 MI->getOperand(OpNo+1).getImm() == 0) {
397 // don't print "+0"
398 } else {
399 printOperand(MI, OpNo+1, O);
400 }
401 if (MI->getOperand(OpNo).isImm() &&
402 MI->getOperand(OpNo).getImm() == 0) {
403 if (MI->getOperand(OpNo+1).isImm() &&
404 MI->getOperand(OpNo+1).getImm() == 0) {
405 O << "0";
406 } else {
407 // don't print "(0)"
408 }
409 } else {
410 O << "(";
411 printOperand(MI, OpNo, O);
412 O << ")";
413 }
414 return false;
415}
416
417char VEAsmPrinter::ID = 0;
418
419INITIALIZE_PASS(VEAsmPrinter, "ve-asm-printer", "VE Assembly Printer", false,
420 false)
421
422// Force static initialization.
423extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmPrinter() {
425}
#define LLVM_ABI
Definition: Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:132
uint64_t Addr
Symbol * Sym
Definition: ELF_riscv.cpp:479
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
static std::string getRegisterName(const TargetRegisterInfo *TRI, Register Reg)
Definition: MIParser.cpp:1416
#define R2(n)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:56
raw_pwrite_stream & OS
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
static void emitSIC(MCStreamer &OutStreamer, MCOperand &RD, const MCSubtargetInfo &STI)
static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym, VE::Specifier HiKind, VE::Specifier LoKind, MCOperand &RD, MCContext &OutContext, const MCSubtargetInfo &STI)
static void emitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1, MCOperand &Src2, MCOperand &RD, const MCSubtargetInfo &STI)
static void emitLEAzii(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
static void emitLEASLzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
static MCOperand createGOTRelExprOp(VE::Specifier Kind, MCSymbol *GOTLabel, MCContext &OutContext)
static void emitBSIC(MCStreamer &OutStreamer, MCOperand &R1, MCOperand &R2, const MCSubtargetInfo &STI)
static MCOperand createVEMCOperand(VE::Specifier Kind, MCSymbol *Sym, MCContext &OutContext)
static void emitLEAzzi(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
static void emitANDrm(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
static void emitLEASLrri(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &RS2, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:90
virtual void emitInstruction(const MachineInstr *)
Targets should implement this to emit instructions.
Definition: AsmPrinter.h:629
virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
Context object for machine code objects.
Definition: MCContext.h:83
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:188
void addOperand(const MCOperand Op)
Definition: MCInst.h:215
void setOpcode(unsigned Op)
Definition: MCInst.h:201
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:40
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:166
static MCOperand createReg(MCRegister Reg)
Definition: MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:145
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.cpp:743
Streaming machine code generation interface.
Definition: MCStreamer.h:220
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Generic base class for all target subtargets.
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:190
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
Instructions::const_iterator const_instr_iterator
Representation of each machine instruction.
Definition: MachineInstr.h:72
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_GlobalAddress
Address of a global value.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:85
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
LLVM_ABI std::string lower() const
Definition: StringRef.cpp:112
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:83
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:82
static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=VE::NoRegAltName)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ S_TLS_GD_LO32
Definition: VEMCAsmInfo.h:51
@ S_TLS_GD_HI32
Definition: VEMCAsmInfo.h:50
@ S_PLT_LO32
Definition: VEMCAsmInfo.h:49
@ S_PLT_HI32
Definition: VEMCAsmInfo.h:48
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void LowerVEMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, AsmPrinter &AP)
Target & getTheVETarget()
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
unsigned M0(unsigned Val)
Definition: VE.h:376
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...