1//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
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// Streams SystemZ assembly language and associated data, in the form of
10// MCInsts and MCExprs respectively.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SystemZAsmPrinter.h"
15#include "MCTargetDesc/SystemZGNUInstPrinter.h"
16#include "MCTargetDesc/SystemZHLASMInstPrinter.h"
17#include "MCTargetDesc/SystemZMCAsmInfo.h"
18#include "MCTargetDesc/SystemZMCTargetDesc.h"
19#include "SystemZELFAsmPrinter.h"
20#include "SystemZMCInstLower.h"
21#include "SystemZSubtarget.h"
22#include "SystemZXPLINKAsmPrinter.h"
23#include "TargetInfo/SystemZTargetInfo.h"
24#include "llvm/CodeGen/MachineInstr.h"
25#include "llvm/MC/MCExpr.h"
26#include "llvm/MC/MCInstBuilder.h"
27#include "llvm/MC/MCStreamer.h"
28#include "llvm/MC/TargetRegistry.h"
29#include "llvm/Support/Compiler.h"
30
31using namespace llvm;
32
33// Return an RI instruction like MI with opcode Opcode, but with the
34// GR64 register operands turned into GR32s.
35static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
36 if (MI->isCompare())
37 return MCInstBuilder(Opcode)
38 .addReg(Reg: SystemZMC::getRegAsGR32(Reg: MI->getOperand(i: 0).getReg()))
39 .addImm(Val: MI->getOperand(i: 1).getImm());
40 else
41 return MCInstBuilder(Opcode)
42 .addReg(Reg: SystemZMC::getRegAsGR32(Reg: MI->getOperand(i: 0).getReg()))
43 .addReg(Reg: SystemZMC::getRegAsGR32(Reg: MI->getOperand(i: 1).getReg()))
44 .addImm(Val: MI->getOperand(i: 2).getImm());
45}
46
47// Return an RI instruction like MI with opcode Opcode, but with the
48// GR64 register operands turned into GRH32s.
49static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
50 if (MI->isCompare())
51 return MCInstBuilder(Opcode)
52 .addReg(Reg: SystemZMC::getRegAsGRH32(Reg: MI->getOperand(i: 0).getReg()))
53 .addImm(Val: MI->getOperand(i: 1).getImm());
54 else
55 return MCInstBuilder(Opcode)
56 .addReg(Reg: SystemZMC::getRegAsGRH32(Reg: MI->getOperand(i: 0).getReg()))
57 .addReg(Reg: SystemZMC::getRegAsGRH32(Reg: MI->getOperand(i: 1).getReg()))
58 .addImm(Val: MI->getOperand(i: 2).getImm());
59}
60
61// Return an RI instruction like MI with opcode Opcode, but with the
62// R2 register turned into a GR64.
63static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
64 return MCInstBuilder(Opcode)
65 .addReg(Reg: MI->getOperand(i: 0).getReg())
66 .addReg(Reg: MI->getOperand(i: 1).getReg())
67 .addReg(Reg: SystemZMC::getRegAsGR64(Reg: MI->getOperand(i: 2).getReg()))
68 .addImm(Val: MI->getOperand(i: 3).getImm())
69 .addImm(Val: MI->getOperand(i: 4).getImm())
70 .addImm(Val: MI->getOperand(i: 5).getImm());
71}
72
73// MI is an instruction that accepts an optional alignment hint,
74// and which was already lowered to LoweredMI. If the alignment
75// of the original memory operand is known, update LoweredMI to
76// an instruction with the corresponding hint set.
77static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI,
78 unsigned Opcode) {
79 if (MI->memoperands_empty())
80 return;
81
82 Align Alignment = Align(16);
83 for (const MachineMemOperand *MMO : MI->memoperands())
84 if (MMO->getAlign() < Alignment)
85 Alignment = MMO->getAlign();
86
87 unsigned AlignmentHint = 0;
88 if (Alignment >= Align(16))
89 AlignmentHint = 4;
90 else if (Alignment >= Align(8))
91 AlignmentHint = 3;
92 if (AlignmentHint == 0)
93 return;
94
95 LoweredMI.setOpcode(Opcode);
96 LoweredMI.addOperand(Op: MCOperand::createImm(Val: AlignmentHint));
97}
98
99// MI loads the high part of a vector from memory. Return an instruction
100// that uses replicating vector load Opcode to do the same thing.
101static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
102 return MCInstBuilder(Opcode)
103 .addReg(Reg: SystemZMC::getRegAsVR128(Reg: MI->getOperand(i: 0).getReg()))
104 .addReg(Reg: MI->getOperand(i: 1).getReg())
105 .addImm(Val: MI->getOperand(i: 2).getImm())
106 .addReg(Reg: MI->getOperand(i: 3).getReg());
107}
108
109// MI stores the high part of a vector to memory. Return an instruction
110// that uses elemental vector store Opcode to do the same thing.
111static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
112 return MCInstBuilder(Opcode)
113 .addReg(Reg: SystemZMC::getRegAsVR128(Reg: MI->getOperand(i: 0).getReg()))
114 .addReg(Reg: MI->getOperand(i: 1).getReg())
115 .addImm(Val: MI->getOperand(i: 2).getImm())
116 .addReg(Reg: MI->getOperand(i: 3).getReg())
117 .addImm(Val: 0);
118}
119
120// MI extracts the first element of the source vector.
121static MCInst lowerVecEltExtraction(const MachineInstr *MI, unsigned Opcode) {
122 return MCInstBuilder(Opcode)
123 .addReg(Reg: SystemZMC::getRegAsGR64(Reg: MI->getOperand(i: 0).getReg()))
124 .addReg(Reg: SystemZMC::getRegAsVR128(Reg: MI->getOperand(i: 1).getReg()))
125 .addReg(Reg: 0)
126 .addImm(Val: 0);
127}
128
129// MI inserts value into the first element of the destination vector.
130static MCInst lowerVecEltInsertion(const MachineInstr *MI, unsigned Opcode) {
131 return MCInstBuilder(Opcode)
132 .addReg(Reg: SystemZMC::getRegAsVR128(Reg: MI->getOperand(i: 0).getReg()))
133 .addReg(Reg: SystemZMC::getRegAsVR128(Reg: MI->getOperand(i: 0).getReg()))
134 .addReg(Reg: MI->getOperand(i: 1).getReg())
135 .addReg(Reg: 0)
136 .addImm(Val: 0);
137}
138
139void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
140 SystemZ_MC::verifyInstructionPredicates(Opcode: MI->getOpcode(),
141 Features: getSubtargetInfo().getFeatureBits());
142
143 SystemZMCInstLower Lower(MF->getContext(), *this);
144 MCInst LoweredMI;
145 switch (MI->getOpcode()) {
146 case SystemZ::Return:
147 LoweredMI = MCInstBuilder(SystemZ::BR)
148 .addReg(Reg: SystemZ::R14D);
149 break;
150
151 case SystemZ::CondReturn:
152 LoweredMI = MCInstBuilder(SystemZ::BCR)
153 .addImm(Val: MI->getOperand(i: 0).getImm())
154 .addImm(Val: MI->getOperand(i: 1).getImm())
155 .addReg(Reg: SystemZ::R14D);
156 break;
157
158 case SystemZ::CRBReturn:
159 LoweredMI = MCInstBuilder(SystemZ::CRB)
160 .addReg(Reg: MI->getOperand(i: 0).getReg())
161 .addReg(Reg: MI->getOperand(i: 1).getReg())
162 .addImm(Val: MI->getOperand(i: 2).getImm())
163 .addReg(Reg: SystemZ::R14D)
164 .addImm(Val: 0);
165 break;
166
167 case SystemZ::CGRBReturn:
168 LoweredMI = MCInstBuilder(SystemZ::CGRB)
169 .addReg(Reg: MI->getOperand(i: 0).getReg())
170 .addReg(Reg: MI->getOperand(i: 1).getReg())
171 .addImm(Val: MI->getOperand(i: 2).getImm())
172 .addReg(Reg: SystemZ::R14D)
173 .addImm(Val: 0);
174 break;
175
176 case SystemZ::CIBReturn:
177 LoweredMI = MCInstBuilder(SystemZ::CIB)
178 .addReg(Reg: MI->getOperand(i: 0).getReg())
179 .addImm(Val: MI->getOperand(i: 1).getImm())
180 .addImm(Val: MI->getOperand(i: 2).getImm())
181 .addReg(Reg: SystemZ::R14D)
182 .addImm(Val: 0);
183 break;
184
185 case SystemZ::CGIBReturn:
186 LoweredMI = MCInstBuilder(SystemZ::CGIB)
187 .addReg(Reg: MI->getOperand(i: 0).getReg())
188 .addImm(Val: MI->getOperand(i: 1).getImm())
189 .addImm(Val: MI->getOperand(i: 2).getImm())
190 .addReg(Reg: SystemZ::R14D)
191 .addImm(Val: 0);
192 break;
193
194 case SystemZ::CLRBReturn:
195 LoweredMI = MCInstBuilder(SystemZ::CLRB)
196 .addReg(Reg: MI->getOperand(i: 0).getReg())
197 .addReg(Reg: MI->getOperand(i: 1).getReg())
198 .addImm(Val: MI->getOperand(i: 2).getImm())
199 .addReg(Reg: SystemZ::R14D)
200 .addImm(Val: 0);
201 break;
202
203 case SystemZ::CLGRBReturn:
204 LoweredMI = MCInstBuilder(SystemZ::CLGRB)
205 .addReg(Reg: MI->getOperand(i: 0).getReg())
206 .addReg(Reg: MI->getOperand(i: 1).getReg())
207 .addImm(Val: MI->getOperand(i: 2).getImm())
208 .addReg(Reg: SystemZ::R14D)
209 .addImm(Val: 0);
210 break;
211
212 case SystemZ::CLIBReturn:
213 LoweredMI = MCInstBuilder(SystemZ::CLIB)
214 .addReg(Reg: MI->getOperand(i: 0).getReg())
215 .addImm(Val: MI->getOperand(i: 1).getImm())
216 .addImm(Val: MI->getOperand(i: 2).getImm())
217 .addReg(Reg: SystemZ::R14D)
218 .addImm(Val: 0);
219 break;
220
221 case SystemZ::CLGIBReturn:
222 LoweredMI = MCInstBuilder(SystemZ::CLGIB)
223 .addReg(Reg: MI->getOperand(i: 0).getReg())
224 .addImm(Val: MI->getOperand(i: 1).getImm())
225 .addImm(Val: MI->getOperand(i: 2).getImm())
226 .addReg(Reg: SystemZ::R14D)
227 .addImm(Val: 0);
228 break;
229
230 case SystemZ::CallBR:
231 LoweredMI = MCInstBuilder(SystemZ::BR)
232 .addReg(Reg: MI->getOperand(i: 0).getReg());
233 break;
234
235 case SystemZ::CallBCR:
236 LoweredMI = MCInstBuilder(SystemZ::BCR)
237 .addImm(Val: MI->getOperand(i: 0).getImm())
238 .addImm(Val: MI->getOperand(i: 1).getImm())
239 .addReg(Reg: MI->getOperand(i: 2).getReg());
240 break;
241
242 case SystemZ::CRBCall:
243 LoweredMI = MCInstBuilder(SystemZ::CRB)
244 .addReg(Reg: MI->getOperand(i: 0).getReg())
245 .addReg(Reg: MI->getOperand(i: 1).getReg())
246 .addImm(Val: MI->getOperand(i: 2).getImm())
247 .addReg(Reg: MI->getOperand(i: 3).getReg())
248 .addImm(Val: 0);
249 break;
250
251 case SystemZ::CGRBCall:
252 LoweredMI = MCInstBuilder(SystemZ::CGRB)
253 .addReg(Reg: MI->getOperand(i: 0).getReg())
254 .addReg(Reg: MI->getOperand(i: 1).getReg())
255 .addImm(Val: MI->getOperand(i: 2).getImm())
256 .addReg(Reg: MI->getOperand(i: 3).getReg())
257 .addImm(Val: 0);
258 break;
259
260 case SystemZ::CIBCall:
261 LoweredMI = MCInstBuilder(SystemZ::CIB)
262 .addReg(Reg: MI->getOperand(i: 0).getReg())
263 .addImm(Val: MI->getOperand(i: 1).getImm())
264 .addImm(Val: MI->getOperand(i: 2).getImm())
265 .addReg(Reg: MI->getOperand(i: 3).getReg())
266 .addImm(Val: 0);
267 break;
268
269 case SystemZ::CGIBCall:
270 LoweredMI = MCInstBuilder(SystemZ::CGIB)
271 .addReg(Reg: MI->getOperand(i: 0).getReg())
272 .addImm(Val: MI->getOperand(i: 1).getImm())
273 .addImm(Val: MI->getOperand(i: 2).getImm())
274 .addReg(Reg: MI->getOperand(i: 3).getReg())
275 .addImm(Val: 0);
276 break;
277
278 case SystemZ::CLRBCall:
279 LoweredMI = MCInstBuilder(SystemZ::CLRB)
280 .addReg(Reg: MI->getOperand(i: 0).getReg())
281 .addReg(Reg: MI->getOperand(i: 1).getReg())
282 .addImm(Val: MI->getOperand(i: 2).getImm())
283 .addReg(Reg: MI->getOperand(i: 3).getReg())
284 .addImm(Val: 0);
285 break;
286
287 case SystemZ::CLGRBCall:
288 LoweredMI = MCInstBuilder(SystemZ::CLGRB)
289 .addReg(Reg: MI->getOperand(i: 0).getReg())
290 .addReg(Reg: MI->getOperand(i: 1).getReg())
291 .addImm(Val: MI->getOperand(i: 2).getImm())
292 .addReg(Reg: MI->getOperand(i: 3).getReg())
293 .addImm(Val: 0);
294 break;
295
296 case SystemZ::CLIBCall:
297 LoweredMI = MCInstBuilder(SystemZ::CLIB)
298 .addReg(Reg: MI->getOperand(i: 0).getReg())
299 .addImm(Val: MI->getOperand(i: 1).getImm())
300 .addImm(Val: MI->getOperand(i: 2).getImm())
301 .addReg(Reg: MI->getOperand(i: 3).getReg())
302 .addImm(Val: 0);
303 break;
304
305 case SystemZ::CLGIBCall:
306 LoweredMI = MCInstBuilder(SystemZ::CLGIB)
307 .addReg(Reg: MI->getOperand(i: 0).getReg())
308 .addImm(Val: MI->getOperand(i: 1).getImm())
309 .addImm(Val: MI->getOperand(i: 2).getImm())
310 .addReg(Reg: MI->getOperand(i: 3).getReg())
311 .addImm(Val: 0);
312 break;
313
314 case SystemZ::IILF64:
315 LoweredMI = MCInstBuilder(SystemZ::IILF)
316 .addReg(Reg: SystemZMC::getRegAsGR32(Reg: MI->getOperand(i: 0).getReg()))
317 .addImm(Val: MI->getOperand(i: 2).getImm());
318 break;
319
320 case SystemZ::IIHF64:
321 LoweredMI = MCInstBuilder(SystemZ::IIHF)
322 .addReg(Reg: SystemZMC::getRegAsGRH32(Reg: MI->getOperand(i: 0).getReg()))
323 .addImm(Val: MI->getOperand(i: 2).getImm());
324 break;
325
326 case SystemZ::RISBHH:
327 case SystemZ::RISBHL:
328 LoweredMI = lowerRIEfLow(MI, Opcode: SystemZ::RISBHG);
329 break;
330
331 case SystemZ::RISBLH:
332 case SystemZ::RISBLL:
333 LoweredMI = lowerRIEfLow(MI, Opcode: SystemZ::RISBLG);
334 break;
335
336 case SystemZ::VLVGP32:
337 LoweredMI = MCInstBuilder(SystemZ::VLVGP)
338 .addReg(Reg: MI->getOperand(i: 0).getReg())
339 .addReg(Reg: SystemZMC::getRegAsGR64(Reg: MI->getOperand(i: 1).getReg()))
340 .addReg(Reg: SystemZMC::getRegAsGR64(Reg: MI->getOperand(i: 2).getReg()));
341 break;
342
343 case SystemZ::VLR16:
344 case SystemZ::VLR32:
345 case SystemZ::VLR64:
346 LoweredMI = MCInstBuilder(SystemZ::VLR)
347 .addReg(Reg: SystemZMC::getRegAsVR128(Reg: MI->getOperand(i: 0).getReg()))
348 .addReg(Reg: SystemZMC::getRegAsVR128(Reg: MI->getOperand(i: 1).getReg()));
349 break;
350
351 case SystemZ::VL:
352 Lower.lower(MI, OutMI&: LoweredMI);
353 lowerAlignmentHint(MI, LoweredMI, Opcode: SystemZ::VLAlign);
354 break;
355
356 case SystemZ::VST:
357 Lower.lower(MI, OutMI&: LoweredMI);
358 lowerAlignmentHint(MI, LoweredMI, Opcode: SystemZ::VSTAlign);
359 break;
360
361 case SystemZ::VLM:
362 Lower.lower(MI, OutMI&: LoweredMI);
363 lowerAlignmentHint(MI, LoweredMI, Opcode: SystemZ::VLMAlign);
364 break;
365
366 case SystemZ::VSTM:
367 Lower.lower(MI, OutMI&: LoweredMI);
368 lowerAlignmentHint(MI, LoweredMI, Opcode: SystemZ::VSTMAlign);
369 break;
370
371 case SystemZ::VL16:
372 LoweredMI = lowerSubvectorLoad(MI, Opcode: SystemZ::VLREPH);
373 break;
374
375 case SystemZ::VL32:
376 LoweredMI = lowerSubvectorLoad(MI, Opcode: SystemZ::VLREPF);
377 break;
378
379 case SystemZ::VL64:
380 LoweredMI = lowerSubvectorLoad(MI, Opcode: SystemZ::VLREPG);
381 break;
382
383 case SystemZ::VST16:
384 LoweredMI = lowerSubvectorStore(MI, Opcode: SystemZ::VSTEH);
385 break;
386
387 case SystemZ::VST32:
388 LoweredMI = lowerSubvectorStore(MI, Opcode: SystemZ::VSTEF);
389 break;
390
391 case SystemZ::VST64:
392 LoweredMI = lowerSubvectorStore(MI, Opcode: SystemZ::VSTEG);
393 break;
394
395 case SystemZ::LFER:
396 LoweredMI = lowerVecEltExtraction(MI, Opcode: SystemZ::VLGVF);
397 break;
398
399 case SystemZ::LFER_16:
400 LoweredMI = lowerVecEltExtraction(MI, Opcode: SystemZ::VLGVH);
401 break;
402
403 case SystemZ::LEFR:
404 LoweredMI = lowerVecEltInsertion(MI, Opcode: SystemZ::VLVGF);
405 break;
406
407 case SystemZ::LEFR_16:
408 LoweredMI = lowerVecEltInsertion(MI, Opcode: SystemZ::VLVGH);
409 break;
410
411#define LOWER_LOW(NAME) \
412 case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
413
414 LOWER_LOW(IILL);
415 LOWER_LOW(IILH);
416 LOWER_LOW(TMLL);
417 LOWER_LOW(TMLH);
418 LOWER_LOW(NILL);
419 LOWER_LOW(NILH);
420 LOWER_LOW(NILF);
421 LOWER_LOW(OILL);
422 LOWER_LOW(OILH);
423 LOWER_LOW(OILF);
424 LOWER_LOW(XILF);
425
426#undef LOWER_LOW
427
428#define LOWER_HIGH(NAME) \
429 case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
430
431 LOWER_HIGH(IIHL);
432 LOWER_HIGH(IIHH);
433 LOWER_HIGH(TMHL);
434 LOWER_HIGH(TMHH);
435 LOWER_HIGH(NIHL);
436 LOWER_HIGH(NIHH);
437 LOWER_HIGH(NIHF);
438 LOWER_HIGH(OIHL);
439 LOWER_HIGH(OIHH);
440 LOWER_HIGH(OIHF);
441 LOWER_HIGH(XIHF);
442
443#undef LOWER_HIGH
444
445 case SystemZ::Serialize:
446 if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
447 LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
448 .addImm(Val: 14).addReg(Reg: SystemZ::R0D);
449 else
450 LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
451 .addImm(Val: 15).addReg(Reg: SystemZ::R0D);
452 break;
453
454 // We want to emit "j .+2" for traps, jumping to the relative immediate field
455 // of the jump instruction, which is an illegal instruction. We cannot emit a
456 // "." symbol, so create and emit a temp label before the instruction and use
457 // that instead.
458 case SystemZ::Trap: {
459 MCSymbol *DotSym = OutContext.createTempSymbol();
460 OutStreamer->emitLabel(Symbol: DotSym);
461
462 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(Symbol: DotSym, Ctx&: OutContext);
463 const MCConstantExpr *ConstExpr = MCConstantExpr::create(Value: 2, Ctx&: OutContext);
464 LoweredMI = MCInstBuilder(SystemZ::J)
465 .addExpr(Val: MCBinaryExpr::createAdd(LHS: Expr, RHS: ConstExpr, Ctx&: OutContext));
466 }
467 break;
468
469 // Conditional traps will create a branch on condition instruction that jumps
470 // to the relative immediate field of the jump instruction. (eg. "jo .+2")
471 case SystemZ::CondTrap: {
472 MCSymbol *DotSym = OutContext.createTempSymbol();
473 OutStreamer->emitLabel(Symbol: DotSym);
474
475 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(Symbol: DotSym, Ctx&: OutContext);
476 const MCConstantExpr *ConstExpr = MCConstantExpr::create(Value: 2, Ctx&: OutContext);
477 LoweredMI = MCInstBuilder(SystemZ::BRC)
478 .addImm(Val: MI->getOperand(i: 0).getImm())
479 .addImm(Val: MI->getOperand(i: 1).getImm())
480 .addExpr(Val: MCBinaryExpr::createAdd(LHS: Expr, RHS: ConstExpr, Ctx&: OutContext));
481 }
482 break;
483
484 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
485 llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted");
486
487 case TargetOpcode::PATCHABLE_TAIL_CALL:
488 // TODO: Define a trampoline `__xray_FunctionTailExit` and differentiate a
489 // normal function exit from a tail exit.
490 llvm_unreachable("Tail call is handled in the normal case. See comments "
491 "around this assert.");
492
493 case SystemZ::EXRL_Pseudo: {
494 unsigned TargetInsOpc = MI->getOperand(i: 0).getImm();
495 Register LenMinus1Reg = MI->getOperand(i: 1).getReg();
496 Register DestReg = MI->getOperand(i: 2).getReg();
497 int64_t DestDisp = MI->getOperand(i: 3).getImm();
498 Register SrcReg = MI->getOperand(i: 4).getReg();
499 int64_t SrcDisp = MI->getOperand(i: 5).getImm();
500
501 SystemZTargetStreamer *TS = getTargetStreamer();
502 MCInst ET = MCInstBuilder(TargetInsOpc)
503 .addReg(Reg: DestReg)
504 .addImm(Val: DestDisp)
505 .addImm(Val: 1)
506 .addReg(Reg: SrcReg)
507 .addImm(Val: SrcDisp);
508 SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
509 auto [It, Inserted] = TS->EXRLTargets2Sym.try_emplace(k: ET_STI);
510 if (Inserted)
511 It->second = OutContext.createTempSymbol();
512 MCSymbol *DotSym = It->second;
513 const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(Symbol: DotSym, Ctx&: OutContext);
514 EmitToStreamer(
515 S&: *OutStreamer,
516 Inst: MCInstBuilder(SystemZ::EXRL).addReg(Reg: LenMinus1Reg).addExpr(Val: Dot));
517 return;
518 }
519
520 case SystemZ::FENCE:
521 OutStreamer->emitRawComment(T: "FENCE");
522 return;
523
524 // EH_SjLj_Setup is a dummy terminator instruction of size 0.
525 // It is used to handle the clobber register for builtin setjmp.
526 case SystemZ::EH_SjLj_Setup:
527 return;
528
529 default:
530 Lower.lower(MI, OutMI&: LoweredMI);
531 break;
532 }
533 EmitToStreamer(S&: *OutStreamer, Inst: LoweredMI);
534}
535
536static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo,
537 raw_ostream &OS) {
538 const char *RegName;
539 if (MAI->getAssemblerDialect() == AD_HLASM) {
540 RegName = SystemZHLASMInstPrinter::getRegisterName(Reg: RegNo);
541 // Skip register prefix so that only register number is left
542 assert(isalpha(RegName[0]) && isdigit(RegName[1]));
543 OS << (RegName + 1);
544 } else {
545 RegName = SystemZGNUInstPrinter::getRegisterName(Reg: RegNo);
546 OS << '%' << RegName;
547 }
548}
549
550static void printReg(unsigned Reg, const MCAsmInfo *MAI, raw_ostream &OS) {
551 if (!Reg)
552 OS << '0';
553 else
554 printFormattedRegName(MAI, RegNo: Reg, OS);
555}
556
557static void printOperand(const MCOperand &MCOp, const MCAsmInfo *MAI,
558 raw_ostream &OS) {
559 if (MCOp.isReg())
560 printReg(Reg: MCOp.getReg(), MAI, OS);
561 else if (MCOp.isImm())
562 OS << MCOp.getImm();
563 else if (MCOp.isExpr())
564 MAI->printExpr(OS, *MCOp.getExpr());
565 else
566 llvm_unreachable("Invalid operand");
567}
568
569static void printAddress(const MCAsmInfo *MAI, unsigned Base,
570 const MCOperand &DispMO, unsigned Index,
571 raw_ostream &OS) {
572 printOperand(MCOp: DispMO, MAI, OS);
573 if (Base || Index) {
574 OS << '(';
575 if (Index) {
576 printFormattedRegName(MAI, RegNo: Index, OS);
577 if (Base)
578 OS << ',';
579 }
580 if (Base)
581 printFormattedRegName(MAI, RegNo: Base, OS);
582 OS << ')';
583 }
584}
585
586bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
587 const char *ExtraCode,
588 raw_ostream &OS) {
589 const MCRegisterInfo &MRI = TM.getMCRegisterInfo();
590 const MachineOperand &MO = MI->getOperand(i: OpNo);
591 MCOperand MCOp;
592 if (ExtraCode) {
593 if ((ExtraCode[0] == 'N' || ExtraCode[0] == 'M') && !ExtraCode[1] &&
594 MO.isReg() && SystemZ::GR128BitRegClass.contains(Reg: MO.getReg()))
595 MCOp =
596 MCOperand::createReg(Reg: MRI.getSubReg(Reg: MO.getReg(), Idx: SystemZ::subreg_l64));
597 else
598 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
599 } else {
600 SystemZMCInstLower Lower(MF->getContext(), *this);
601 MCOp = Lower.lowerOperand(MO);
602 }
603 printOperand(MCOp, MAI: &MAI, OS);
604 return false;
605}
606
607bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
608 unsigned OpNo,
609 const char *ExtraCode,
610 raw_ostream &OS) {
611 if (ExtraCode && ExtraCode[0] && !ExtraCode[1]) {
612 switch (ExtraCode[0]) {
613 case 'A':
614 // Unlike EmitMachineNode(), EmitSpecialNode(INLINEASM) does not call
615 // setMemRefs(), so MI->memoperands() is empty and the alignment
616 // information is not available.
617 return false;
618 case 'O':
619 OS << MI->getOperand(i: OpNo + 1).getImm();
620 return false;
621 case 'R':
622 ::printReg(Reg: MI->getOperand(i: OpNo).getReg(), MAI: &MAI, OS);
623 return false;
624 }
625 }
626 printAddress(MAI: &MAI, Base: MI->getOperand(i: OpNo).getReg(),
627 DispMO: MCOperand::createImm(Val: MI->getOperand(i: OpNo + 1).getImm()),
628 Index: MI->getOperand(i: OpNo + 2).getReg(), OS);
629 return false;
630}
631
632char SystemZAsmPrinter::ID = 0;
633
634INITIALIZE_PASS(SystemZAsmPrinter, "systemz-asm-printer",
635 "SystemZ Assembly Printer", false, false)
636
637static AsmPrinter *
638createSystemZAsmPrinter(TargetMachine &TM,
639 std::unique_ptr<MCStreamer> &&Streamer) {
640 if (TM.getTargetTriple().isOSzOS())
641 return new SystemZXPLINKAsmPrinter(TM, std::move(Streamer));
642 return new SystemZELFAsmPrinter(TM, std::move(Streamer));
643}
644
645// Force static initialization.
646extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
647LLVMInitializeSystemZAsmPrinter() {
648 TargetRegistry::RegisterAsmPrinter(T&: getTheSystemZTarget(),
649 Fn: createSystemZAsmPrinter);
650}
651