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/SystemZInstPrinter.h"
16 #include "SystemZConstantPoolValue.h"
17 #include "SystemZMCInstLower.h"
18 #include "TargetInfo/SystemZTargetInfo.h"
19 #include "llvm/BinaryFormat/ELF.h"
20 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
21 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
22 #include "llvm/IR/Mangler.h"
23 #include "llvm/MC/MCExpr.h"
24 #include "llvm/MC/MCInstBuilder.h"
25 #include "llvm/MC/MCSectionELF.h"
26 #include "llvm/MC/MCStreamer.h"
27 #include "llvm/Support/TargetRegistry.h"
28 
29 using namespace llvm;
30 
31 // Return an RI instruction like MI with opcode Opcode, but with the
32 // GR64 register operands turned into GR32s.
lowerRILow(const MachineInstr * MI,unsigned Opcode)33 static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
34   if (MI->isCompare())
35     return MCInstBuilder(Opcode)
36       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
37       .addImm(MI->getOperand(1).getImm());
38   else
39     return MCInstBuilder(Opcode)
40       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
41       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
42       .addImm(MI->getOperand(2).getImm());
43 }
44 
45 // Return an RI instruction like MI with opcode Opcode, but with the
46 // GR64 register operands turned into GRH32s.
lowerRIHigh(const MachineInstr * MI,unsigned Opcode)47 static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
48   if (MI->isCompare())
49     return MCInstBuilder(Opcode)
50       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
51       .addImm(MI->getOperand(1).getImm());
52   else
53     return MCInstBuilder(Opcode)
54       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
55       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))
56       .addImm(MI->getOperand(2).getImm());
57 }
58 
59 // Return an RI instruction like MI with opcode Opcode, but with the
60 // R2 register turned into a GR64.
lowerRIEfLow(const MachineInstr * MI,unsigned Opcode)61 static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
62   return MCInstBuilder(Opcode)
63     .addReg(MI->getOperand(0).getReg())
64     .addReg(MI->getOperand(1).getReg())
65     .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
66     .addImm(MI->getOperand(3).getImm())
67     .addImm(MI->getOperand(4).getImm())
68     .addImm(MI->getOperand(5).getImm());
69 }
70 
getTLSGetOffset(MCContext & Context)71 static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
72   StringRef Name = "__tls_get_offset";
73   return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
74                                  MCSymbolRefExpr::VK_PLT,
75                                  Context);
76 }
77 
getGlobalOffsetTable(MCContext & Context)78 static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
79   StringRef Name = "_GLOBAL_OFFSET_TABLE_";
80   return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
81                                  MCSymbolRefExpr::VK_None,
82                                  Context);
83 }
84 
85 // MI is an instruction that accepts an optional alignment hint,
86 // and which was already lowered to LoweredMI.  If the alignment
87 // of the original memory operand is known, update LoweredMI to
88 // an instruction with the corresponding hint set.
lowerAlignmentHint(const MachineInstr * MI,MCInst & LoweredMI,unsigned Opcode)89 static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI,
90                                unsigned Opcode) {
91   if (!MI->hasOneMemOperand())
92     return;
93   const MachineMemOperand *MMO = *MI->memoperands_begin();
94   unsigned AlignmentHint = 0;
95   if (MMO->getAlign() >= Align(16))
96     AlignmentHint = 4;
97   else if (MMO->getAlign() >= Align(8))
98     AlignmentHint = 3;
99   if (AlignmentHint == 0)
100     return;
101 
102   LoweredMI.setOpcode(Opcode);
103   LoweredMI.addOperand(MCOperand::createImm(AlignmentHint));
104 }
105 
106 // MI loads the high part of a vector from memory.  Return an instruction
107 // that uses replicating vector load Opcode to do the same thing.
lowerSubvectorLoad(const MachineInstr * MI,unsigned Opcode)108 static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
109   return MCInstBuilder(Opcode)
110     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
111     .addReg(MI->getOperand(1).getReg())
112     .addImm(MI->getOperand(2).getImm())
113     .addReg(MI->getOperand(3).getReg());
114 }
115 
116 // MI stores the high part of a vector to memory.  Return an instruction
117 // that uses elemental vector store Opcode to do the same thing.
lowerSubvectorStore(const MachineInstr * MI,unsigned Opcode)118 static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
119   return MCInstBuilder(Opcode)
120     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
121     .addReg(MI->getOperand(1).getReg())
122     .addImm(MI->getOperand(2).getImm())
123     .addReg(MI->getOperand(3).getReg())
124     .addImm(0);
125 }
126 
emitInstruction(const MachineInstr * MI)127 void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
128   SystemZMCInstLower Lower(MF->getContext(), *this);
129   const SystemZSubtarget *Subtarget = &MF->getSubtarget<SystemZSubtarget>();
130   MCInst LoweredMI;
131   switch (MI->getOpcode()) {
132   case SystemZ::Return:
133     if (Subtarget->isTargetXPLINK64())
134       LoweredMI =
135           MCInstBuilder(SystemZ::B).addReg(SystemZ::R7D).addImm(2).addReg(0);
136     else
137       LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
138     break;
139 
140   case SystemZ::CondReturn:
141     LoweredMI = MCInstBuilder(SystemZ::BCR)
142       .addImm(MI->getOperand(0).getImm())
143       .addImm(MI->getOperand(1).getImm())
144       .addReg(SystemZ::R14D);
145     break;
146 
147   case SystemZ::CRBReturn:
148     LoweredMI = MCInstBuilder(SystemZ::CRB)
149       .addReg(MI->getOperand(0).getReg())
150       .addReg(MI->getOperand(1).getReg())
151       .addImm(MI->getOperand(2).getImm())
152       .addReg(SystemZ::R14D)
153       .addImm(0);
154     break;
155 
156   case SystemZ::CGRBReturn:
157     LoweredMI = MCInstBuilder(SystemZ::CGRB)
158       .addReg(MI->getOperand(0).getReg())
159       .addReg(MI->getOperand(1).getReg())
160       .addImm(MI->getOperand(2).getImm())
161       .addReg(SystemZ::R14D)
162       .addImm(0);
163     break;
164 
165   case SystemZ::CIBReturn:
166     LoweredMI = MCInstBuilder(SystemZ::CIB)
167       .addReg(MI->getOperand(0).getReg())
168       .addImm(MI->getOperand(1).getImm())
169       .addImm(MI->getOperand(2).getImm())
170       .addReg(SystemZ::R14D)
171       .addImm(0);
172     break;
173 
174   case SystemZ::CGIBReturn:
175     LoweredMI = MCInstBuilder(SystemZ::CGIB)
176       .addReg(MI->getOperand(0).getReg())
177       .addImm(MI->getOperand(1).getImm())
178       .addImm(MI->getOperand(2).getImm())
179       .addReg(SystemZ::R14D)
180       .addImm(0);
181     break;
182 
183   case SystemZ::CLRBReturn:
184     LoweredMI = MCInstBuilder(SystemZ::CLRB)
185       .addReg(MI->getOperand(0).getReg())
186       .addReg(MI->getOperand(1).getReg())
187       .addImm(MI->getOperand(2).getImm())
188       .addReg(SystemZ::R14D)
189       .addImm(0);
190     break;
191 
192   case SystemZ::CLGRBReturn:
193     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
194       .addReg(MI->getOperand(0).getReg())
195       .addReg(MI->getOperand(1).getReg())
196       .addImm(MI->getOperand(2).getImm())
197       .addReg(SystemZ::R14D)
198       .addImm(0);
199     break;
200 
201   case SystemZ::CLIBReturn:
202     LoweredMI = MCInstBuilder(SystemZ::CLIB)
203       .addReg(MI->getOperand(0).getReg())
204       .addImm(MI->getOperand(1).getImm())
205       .addImm(MI->getOperand(2).getImm())
206       .addReg(SystemZ::R14D)
207       .addImm(0);
208     break;
209 
210   case SystemZ::CLGIBReturn:
211     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
212       .addReg(MI->getOperand(0).getReg())
213       .addImm(MI->getOperand(1).getImm())
214       .addImm(MI->getOperand(2).getImm())
215       .addReg(SystemZ::R14D)
216       .addImm(0);
217     break;
218 
219   case SystemZ::CallBRASL_XPLINK64:
220     EmitToStreamer(*OutStreamer,
221                    MCInstBuilder(SystemZ::BRASL)
222                        .addReg(SystemZ::R7D)
223                        .addExpr(Lower.getExpr(MI->getOperand(0),
224                                               MCSymbolRefExpr::VK_PLT)));
225     EmitToStreamer(
226         *OutStreamer,
227         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R3D));
228     return;
229 
230   case SystemZ::CallBASR_XPLINK64:
231     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
232                                      .addReg(SystemZ::R7D)
233                                      .addReg(MI->getOperand(0).getReg()));
234     EmitToStreamer(
235         *OutStreamer,
236         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D));
237     return;
238 
239   case SystemZ::CallBRASL:
240     LoweredMI = MCInstBuilder(SystemZ::BRASL)
241       .addReg(SystemZ::R14D)
242       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
243     break;
244 
245   case SystemZ::CallBASR:
246     LoweredMI = MCInstBuilder(SystemZ::BASR)
247       .addReg(SystemZ::R14D)
248       .addReg(MI->getOperand(0).getReg());
249     break;
250 
251   case SystemZ::CallJG:
252     LoweredMI = MCInstBuilder(SystemZ::JG)
253       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
254     break;
255 
256   case SystemZ::CallBRCL:
257     LoweredMI = MCInstBuilder(SystemZ::BRCL)
258       .addImm(MI->getOperand(0).getImm())
259       .addImm(MI->getOperand(1).getImm())
260       .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT));
261     break;
262 
263   case SystemZ::CallBR:
264     LoweredMI = MCInstBuilder(SystemZ::BR)
265       .addReg(MI->getOperand(0).getReg());
266     break;
267 
268   case SystemZ::CallBCR:
269     LoweredMI = MCInstBuilder(SystemZ::BCR)
270       .addImm(MI->getOperand(0).getImm())
271       .addImm(MI->getOperand(1).getImm())
272       .addReg(MI->getOperand(2).getReg());
273     break;
274 
275   case SystemZ::CRBCall:
276     LoweredMI = MCInstBuilder(SystemZ::CRB)
277       .addReg(MI->getOperand(0).getReg())
278       .addReg(MI->getOperand(1).getReg())
279       .addImm(MI->getOperand(2).getImm())
280       .addReg(MI->getOperand(3).getReg())
281       .addImm(0);
282     break;
283 
284   case SystemZ::CGRBCall:
285     LoweredMI = MCInstBuilder(SystemZ::CGRB)
286       .addReg(MI->getOperand(0).getReg())
287       .addReg(MI->getOperand(1).getReg())
288       .addImm(MI->getOperand(2).getImm())
289       .addReg(MI->getOperand(3).getReg())
290       .addImm(0);
291     break;
292 
293   case SystemZ::CIBCall:
294     LoweredMI = MCInstBuilder(SystemZ::CIB)
295       .addReg(MI->getOperand(0).getReg())
296       .addImm(MI->getOperand(1).getImm())
297       .addImm(MI->getOperand(2).getImm())
298       .addReg(MI->getOperand(3).getReg())
299       .addImm(0);
300     break;
301 
302   case SystemZ::CGIBCall:
303     LoweredMI = MCInstBuilder(SystemZ::CGIB)
304       .addReg(MI->getOperand(0).getReg())
305       .addImm(MI->getOperand(1).getImm())
306       .addImm(MI->getOperand(2).getImm())
307       .addReg(MI->getOperand(3).getReg())
308       .addImm(0);
309     break;
310 
311   case SystemZ::CLRBCall:
312     LoweredMI = MCInstBuilder(SystemZ::CLRB)
313       .addReg(MI->getOperand(0).getReg())
314       .addReg(MI->getOperand(1).getReg())
315       .addImm(MI->getOperand(2).getImm())
316       .addReg(MI->getOperand(3).getReg())
317       .addImm(0);
318     break;
319 
320   case SystemZ::CLGRBCall:
321     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
322       .addReg(MI->getOperand(0).getReg())
323       .addReg(MI->getOperand(1).getReg())
324       .addImm(MI->getOperand(2).getImm())
325       .addReg(MI->getOperand(3).getReg())
326       .addImm(0);
327     break;
328 
329   case SystemZ::CLIBCall:
330     LoweredMI = MCInstBuilder(SystemZ::CLIB)
331       .addReg(MI->getOperand(0).getReg())
332       .addImm(MI->getOperand(1).getImm())
333       .addImm(MI->getOperand(2).getImm())
334       .addReg(MI->getOperand(3).getReg())
335       .addImm(0);
336     break;
337 
338   case SystemZ::CLGIBCall:
339     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
340       .addReg(MI->getOperand(0).getReg())
341       .addImm(MI->getOperand(1).getImm())
342       .addImm(MI->getOperand(2).getImm())
343       .addReg(MI->getOperand(3).getReg())
344       .addImm(0);
345     break;
346 
347   case SystemZ::TLS_GDCALL:
348     LoweredMI = MCInstBuilder(SystemZ::BRASL)
349       .addReg(SystemZ::R14D)
350       .addExpr(getTLSGetOffset(MF->getContext()))
351       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
352     break;
353 
354   case SystemZ::TLS_LDCALL:
355     LoweredMI = MCInstBuilder(SystemZ::BRASL)
356       .addReg(SystemZ::R14D)
357       .addExpr(getTLSGetOffset(MF->getContext()))
358       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
359     break;
360 
361   case SystemZ::GOT:
362     LoweredMI = MCInstBuilder(SystemZ::LARL)
363       .addReg(MI->getOperand(0).getReg())
364       .addExpr(getGlobalOffsetTable(MF->getContext()));
365     break;
366 
367   case SystemZ::IILF64:
368     LoweredMI = MCInstBuilder(SystemZ::IILF)
369       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
370       .addImm(MI->getOperand(2).getImm());
371     break;
372 
373   case SystemZ::IIHF64:
374     LoweredMI = MCInstBuilder(SystemZ::IIHF)
375       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
376       .addImm(MI->getOperand(2).getImm());
377     break;
378 
379   case SystemZ::RISBHH:
380   case SystemZ::RISBHL:
381     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
382     break;
383 
384   case SystemZ::RISBLH:
385   case SystemZ::RISBLL:
386     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
387     break;
388 
389   case SystemZ::VLVGP32:
390     LoweredMI = MCInstBuilder(SystemZ::VLVGP)
391       .addReg(MI->getOperand(0).getReg())
392       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))
393       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));
394     break;
395 
396   case SystemZ::VLR32:
397   case SystemZ::VLR64:
398     LoweredMI = MCInstBuilder(SystemZ::VLR)
399       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
400       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));
401     break;
402 
403   case SystemZ::VL:
404     Lower.lower(MI, LoweredMI);
405     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);
406     break;
407 
408   case SystemZ::VST:
409     Lower.lower(MI, LoweredMI);
410     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);
411     break;
412 
413   case SystemZ::VLM:
414     Lower.lower(MI, LoweredMI);
415     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);
416     break;
417 
418   case SystemZ::VSTM:
419     Lower.lower(MI, LoweredMI);
420     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign);
421     break;
422 
423   case SystemZ::VL32:
424     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);
425     break;
426 
427   case SystemZ::VL64:
428     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);
429     break;
430 
431   case SystemZ::VST32:
432     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);
433     break;
434 
435   case SystemZ::VST64:
436     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);
437     break;
438 
439   case SystemZ::LFER:
440     LoweredMI = MCInstBuilder(SystemZ::VLGVF)
441       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))
442       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))
443       .addReg(0).addImm(0);
444     break;
445 
446   case SystemZ::LEFR:
447     LoweredMI = MCInstBuilder(SystemZ::VLVGF)
448       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
449       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
450       .addReg(MI->getOperand(1).getReg())
451       .addReg(0).addImm(0);
452     break;
453 
454 #define LOWER_LOW(NAME)                                                 \
455   case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
456 
457   LOWER_LOW(IILL);
458   LOWER_LOW(IILH);
459   LOWER_LOW(TMLL);
460   LOWER_LOW(TMLH);
461   LOWER_LOW(NILL);
462   LOWER_LOW(NILH);
463   LOWER_LOW(NILF);
464   LOWER_LOW(OILL);
465   LOWER_LOW(OILH);
466   LOWER_LOW(OILF);
467   LOWER_LOW(XILF);
468 
469 #undef LOWER_LOW
470 
471 #define LOWER_HIGH(NAME) \
472   case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
473 
474   LOWER_HIGH(IIHL);
475   LOWER_HIGH(IIHH);
476   LOWER_HIGH(TMHL);
477   LOWER_HIGH(TMHH);
478   LOWER_HIGH(NIHL);
479   LOWER_HIGH(NIHH);
480   LOWER_HIGH(NIHF);
481   LOWER_HIGH(OIHL);
482   LOWER_HIGH(OIHH);
483   LOWER_HIGH(OIHF);
484   LOWER_HIGH(XIHF);
485 
486 #undef LOWER_HIGH
487 
488   case SystemZ::Serialize:
489     if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
490       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
491         .addImm(14).addReg(SystemZ::R0D);
492     else
493       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
494         .addImm(15).addReg(SystemZ::R0D);
495     break;
496 
497   // Emit nothing here but a comment if we can.
498   case SystemZ::MemBarrier:
499     OutStreamer->emitRawComment("MEMBARRIER");
500     return;
501 
502   // We want to emit "j .+2" for traps, jumping to the relative immediate field
503   // of the jump instruction, which is an illegal instruction. We cannot emit a
504   // "." symbol, so create and emit a temp label before the instruction and use
505   // that instead.
506   case SystemZ::Trap: {
507     MCSymbol *DotSym = OutContext.createTempSymbol();
508     OutStreamer->emitLabel(DotSym);
509 
510     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
511     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
512     LoweredMI = MCInstBuilder(SystemZ::J)
513       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
514     }
515     break;
516 
517   // Conditional traps will create a branch on condition instruction that jumps
518   // to the relative immediate field of the jump instruction. (eg. "jo .+2")
519   case SystemZ::CondTrap: {
520     MCSymbol *DotSym = OutContext.createTempSymbol();
521     OutStreamer->emitLabel(DotSym);
522 
523     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
524     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
525     LoweredMI = MCInstBuilder(SystemZ::BRC)
526       .addImm(MI->getOperand(0).getImm())
527       .addImm(MI->getOperand(1).getImm())
528       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
529     }
530     break;
531 
532   case TargetOpcode::FENTRY_CALL:
533     LowerFENTRY_CALL(*MI, Lower);
534     return;
535 
536   case TargetOpcode::STACKMAP:
537     LowerSTACKMAP(*MI);
538     return;
539 
540   case TargetOpcode::PATCHPOINT:
541     LowerPATCHPOINT(*MI, Lower);
542     return;
543 
544   case SystemZ::EXRL_Pseudo: {
545     unsigned TargetInsOpc = MI->getOperand(0).getImm();
546     Register LenMinus1Reg = MI->getOperand(1).getReg();
547     Register DestReg = MI->getOperand(2).getReg();
548     int64_t DestDisp = MI->getOperand(3).getImm();
549     Register SrcReg = MI->getOperand(4).getReg();
550     int64_t SrcDisp = MI->getOperand(5).getImm();
551 
552     MCSymbol *DotSym = nullptr;
553     MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
554       .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
555     MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
556     EXRLT2SymMap::iterator I = EXRLTargets2Sym.find(ET_STI);
557     if (I != EXRLTargets2Sym.end())
558       DotSym = I->second;
559     else
560       EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
561     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
562     EmitToStreamer(
563         *OutStreamer,
564         MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
565     return;
566   }
567 
568   default:
569     Lower.lower(MI, LoweredMI);
570     break;
571   }
572   EmitToStreamer(*OutStreamer, LoweredMI);
573 }
574 
575 // Emit the largest nop instruction smaller than or equal to NumBytes
576 // bytes.  Return the size of nop emitted.
EmitNop(MCContext & OutContext,MCStreamer & OutStreamer,unsigned NumBytes,const MCSubtargetInfo & STI)577 static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
578                         unsigned NumBytes, const MCSubtargetInfo &STI) {
579   if (NumBytes < 2) {
580     llvm_unreachable("Zero nops?");
581     return 0;
582   }
583   else if (NumBytes < 4) {
584     OutStreamer.emitInstruction(
585         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
586     return 2;
587   }
588   else if (NumBytes < 6) {
589     OutStreamer.emitInstruction(
590         MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
591         STI);
592     return 4;
593   }
594   else {
595     MCSymbol *DotSym = OutContext.createTempSymbol();
596     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
597     OutStreamer.emitLabel(DotSym);
598     OutStreamer.emitInstruction(
599         MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
600     return 6;
601   }
602 }
603 
LowerFENTRY_CALL(const MachineInstr & MI,SystemZMCInstLower & Lower)604 void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
605                                          SystemZMCInstLower &Lower) {
606   MCContext &Ctx = MF->getContext();
607   if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
608     MCSymbol *DotSym = OutContext.createTempSymbol();
609     OutStreamer->PushSection();
610     OutStreamer->SwitchSection(
611         Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
612     OutStreamer->emitSymbolValue(DotSym, 8);
613     OutStreamer->PopSection();
614     OutStreamer->emitLabel(DotSym);
615   }
616 
617   if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
618     EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
619     return;
620   }
621 
622   MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
623   const MCSymbolRefExpr *Op =
624       MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
625   OutStreamer->emitInstruction(
626       MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
627       getSubtargetInfo());
628 }
629 
LowerSTACKMAP(const MachineInstr & MI)630 void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
631   const SystemZInstrInfo *TII =
632     static_cast<const SystemZInstrInfo *>(MF->getSubtarget().getInstrInfo());
633 
634   unsigned NumNOPBytes = MI.getOperand(1).getImm();
635 
636   auto &Ctx = OutStreamer->getContext();
637   MCSymbol *MILabel = Ctx.createTempSymbol();
638   OutStreamer->emitLabel(MILabel);
639 
640   SM.recordStackMap(*MILabel, MI);
641   assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
642 
643   // Scan ahead to trim the shadow.
644   unsigned ShadowBytes = 0;
645   const MachineBasicBlock &MBB = *MI.getParent();
646   MachineBasicBlock::const_iterator MII(MI);
647   ++MII;
648   while (ShadowBytes < NumNOPBytes) {
649     if (MII == MBB.end() ||
650         MII->getOpcode() == TargetOpcode::PATCHPOINT ||
651         MII->getOpcode() == TargetOpcode::STACKMAP)
652       break;
653     ShadowBytes += TII->getInstSizeInBytes(*MII);
654     if (MII->isCall())
655       break;
656     ++MII;
657   }
658 
659   // Emit nops.
660   while (ShadowBytes < NumNOPBytes)
661     ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
662                            getSubtargetInfo());
663 }
664 
665 // Lower a patchpoint of the form:
666 // [<def>], <id>, <numBytes>, <target>, <numArgs>
LowerPATCHPOINT(const MachineInstr & MI,SystemZMCInstLower & Lower)667 void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
668                                         SystemZMCInstLower &Lower) {
669   auto &Ctx = OutStreamer->getContext();
670   MCSymbol *MILabel = Ctx.createTempSymbol();
671   OutStreamer->emitLabel(MILabel);
672 
673   SM.recordPatchPoint(*MILabel, MI);
674   PatchPointOpers Opers(&MI);
675 
676   unsigned EncodedBytes = 0;
677   const MachineOperand &CalleeMO = Opers.getCallTarget();
678 
679   if (CalleeMO.isImm()) {
680     uint64_t CallTarget = CalleeMO.getImm();
681     if (CallTarget) {
682       unsigned ScratchIdx = -1;
683       unsigned ScratchReg = 0;
684       do {
685         ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
686         ScratchReg = MI.getOperand(ScratchIdx).getReg();
687       } while (ScratchReg == SystemZ::R0D);
688 
689       // Materialize the call target address
690       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
691                                       .addReg(ScratchReg)
692                                       .addImm(CallTarget & 0xFFFFFFFF));
693       EncodedBytes += 6;
694       if (CallTarget >> 32) {
695         EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
696                                         .addReg(ScratchReg)
697                                         .addImm(CallTarget >> 32));
698         EncodedBytes += 6;
699       }
700 
701       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
702                                      .addReg(SystemZ::R14D)
703                                      .addReg(ScratchReg));
704       EncodedBytes += 2;
705     }
706   } else if (CalleeMO.isGlobal()) {
707     const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT);
708     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
709                                    .addReg(SystemZ::R14D)
710                                    .addExpr(Expr));
711     EncodedBytes += 6;
712   }
713 
714   // Emit padding.
715   unsigned NumBytes = Opers.getNumPatchBytes();
716   assert(NumBytes >= EncodedBytes &&
717          "Patchpoint can't request size less than the length of a call.");
718   assert((NumBytes - EncodedBytes) % 2 == 0 &&
719          "Invalid number of NOP bytes requested!");
720   while (EncodedBytes < NumBytes)
721     EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
722                             getSubtargetInfo());
723 }
724 
emitEXRLTargetInstructions()725 void SystemZAsmPrinter::emitEXRLTargetInstructions() {
726   if (EXRLTargets2Sym.empty())
727     return;
728   // Switch to the .text section.
729   OutStreamer->SwitchSection(getObjFileLowering().getTextSection());
730   for (auto &I : EXRLTargets2Sym) {
731     OutStreamer->emitLabel(I.second);
732     const MCInstSTIPair &MCI_STI = I.first;
733     OutStreamer->emitInstruction(MCI_STI.first, *MCI_STI.second);
734   }
735   EXRLTargets2Sym.clear();
736 }
737 
738 // Convert a SystemZ-specific constant pool modifier into the associated
739 // MCSymbolRefExpr variant kind.
740 static MCSymbolRefExpr::VariantKind
getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier)741 getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
742   switch (Modifier) {
743   case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
744   case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
745   case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
746   case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
747   }
748   llvm_unreachable("Invalid SystemCPModifier!");
749 }
750 
emitMachineConstantPoolValue(MachineConstantPoolValue * MCPV)751 void SystemZAsmPrinter::emitMachineConstantPoolValue(
752     MachineConstantPoolValue *MCPV) {
753   auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
754 
755   const MCExpr *Expr =
756     MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
757                             getModifierVariantKind(ZCPV->getModifier()),
758                             OutContext);
759   uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
760 
761   OutStreamer->emitValue(Expr, Size);
762 }
763 
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & OS)764 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
765                                         const char *ExtraCode,
766                                         raw_ostream &OS) {
767   const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
768   const MachineOperand &MO = MI->getOperand(OpNo);
769   MCOperand MCOp;
770   if (ExtraCode) {
771     if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
772         SystemZ::GR128BitRegClass.contains(MO.getReg()))
773       MCOp =
774           MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
775     else
776       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
777   } else {
778     SystemZMCInstLower Lower(MF->getContext(), *this);
779     MCOp = Lower.lowerOperand(MO);
780   }
781   SystemZInstPrinter::printOperand(MCOp, MAI, OS);
782   return false;
783 }
784 
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & OS)785 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
786                                               unsigned OpNo,
787                                               const char *ExtraCode,
788                                               raw_ostream &OS) {
789   SystemZInstPrinter::printAddress(MAI, MI->getOperand(OpNo).getReg(),
790                                    MI->getOperand(OpNo + 1).getImm(),
791                                    MI->getOperand(OpNo + 2).getReg(), OS);
792   return false;
793 }
794 
emitEndOfAsmFile(Module & M)795 void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
796   emitEXRLTargetInstructions();
797   emitStackMaps(SM);
798 }
799 
800 // Force static initialization.
LLVMInitializeSystemZAsmPrinter()801 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
802   RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
803 }
804