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/MC/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.
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.
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.
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 
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 
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.
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.
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.
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 
127 void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
128   SystemZMCInstLower Lower(MF->getContext(), *this);
129   MCInst LoweredMI;
130   switch (MI->getOpcode()) {
131   case SystemZ::Return:
132     LoweredMI = MCInstBuilder(SystemZ::BR)
133       .addReg(SystemZ::R14D);
134     break;
135 
136   case SystemZ::Return_XPLINK:
137     LoweredMI = MCInstBuilder(SystemZ::B)
138       .addReg(SystemZ::R7D)
139       .addImm(2)
140       .addReg(0);
141     break;
142 
143   case SystemZ::CondReturn:
144     LoweredMI = MCInstBuilder(SystemZ::BCR)
145       .addImm(MI->getOperand(0).getImm())
146       .addImm(MI->getOperand(1).getImm())
147       .addReg(SystemZ::R14D);
148     break;
149 
150   case SystemZ::CondReturn_XPLINK:
151     LoweredMI = MCInstBuilder(SystemZ::BC)
152       .addImm(MI->getOperand(0).getImm())
153       .addImm(MI->getOperand(1).getImm())
154       .addReg(SystemZ::R7D)
155       .addImm(2)
156       .addReg(0);
157     break;
158 
159   case SystemZ::CRBReturn:
160     LoweredMI = MCInstBuilder(SystemZ::CRB)
161       .addReg(MI->getOperand(0).getReg())
162       .addReg(MI->getOperand(1).getReg())
163       .addImm(MI->getOperand(2).getImm())
164       .addReg(SystemZ::R14D)
165       .addImm(0);
166     break;
167 
168   case SystemZ::CGRBReturn:
169     LoweredMI = MCInstBuilder(SystemZ::CGRB)
170       .addReg(MI->getOperand(0).getReg())
171       .addReg(MI->getOperand(1).getReg())
172       .addImm(MI->getOperand(2).getImm())
173       .addReg(SystemZ::R14D)
174       .addImm(0);
175     break;
176 
177   case SystemZ::CIBReturn:
178     LoweredMI = MCInstBuilder(SystemZ::CIB)
179       .addReg(MI->getOperand(0).getReg())
180       .addImm(MI->getOperand(1).getImm())
181       .addImm(MI->getOperand(2).getImm())
182       .addReg(SystemZ::R14D)
183       .addImm(0);
184     break;
185 
186   case SystemZ::CGIBReturn:
187     LoweredMI = MCInstBuilder(SystemZ::CGIB)
188       .addReg(MI->getOperand(0).getReg())
189       .addImm(MI->getOperand(1).getImm())
190       .addImm(MI->getOperand(2).getImm())
191       .addReg(SystemZ::R14D)
192       .addImm(0);
193     break;
194 
195   case SystemZ::CLRBReturn:
196     LoweredMI = MCInstBuilder(SystemZ::CLRB)
197       .addReg(MI->getOperand(0).getReg())
198       .addReg(MI->getOperand(1).getReg())
199       .addImm(MI->getOperand(2).getImm())
200       .addReg(SystemZ::R14D)
201       .addImm(0);
202     break;
203 
204   case SystemZ::CLGRBReturn:
205     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
206       .addReg(MI->getOperand(0).getReg())
207       .addReg(MI->getOperand(1).getReg())
208       .addImm(MI->getOperand(2).getImm())
209       .addReg(SystemZ::R14D)
210       .addImm(0);
211     break;
212 
213   case SystemZ::CLIBReturn:
214     LoweredMI = MCInstBuilder(SystemZ::CLIB)
215       .addReg(MI->getOperand(0).getReg())
216       .addImm(MI->getOperand(1).getImm())
217       .addImm(MI->getOperand(2).getImm())
218       .addReg(SystemZ::R14D)
219       .addImm(0);
220     break;
221 
222   case SystemZ::CLGIBReturn:
223     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
224       .addReg(MI->getOperand(0).getReg())
225       .addImm(MI->getOperand(1).getImm())
226       .addImm(MI->getOperand(2).getImm())
227       .addReg(SystemZ::R14D)
228       .addImm(0);
229     break;
230 
231   case SystemZ::CallBRASL_XPLINK64:
232     EmitToStreamer(*OutStreamer,
233                    MCInstBuilder(SystemZ::BRASL)
234                        .addReg(SystemZ::R7D)
235                        .addExpr(Lower.getExpr(MI->getOperand(0),
236                                               MCSymbolRefExpr::VK_PLT)));
237     EmitToStreamer(
238         *OutStreamer,
239         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R3D));
240     return;
241 
242   case SystemZ::CallBASR_XPLINK64:
243     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
244                                      .addReg(SystemZ::R7D)
245                                      .addReg(MI->getOperand(0).getReg()));
246     EmitToStreamer(
247         *OutStreamer,
248         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D));
249     return;
250 
251   case SystemZ::CallBRASL:
252     LoweredMI = MCInstBuilder(SystemZ::BRASL)
253       .addReg(SystemZ::R14D)
254       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
255     break;
256 
257   case SystemZ::CallBASR:
258     LoweredMI = MCInstBuilder(SystemZ::BASR)
259       .addReg(SystemZ::R14D)
260       .addReg(MI->getOperand(0).getReg());
261     break;
262 
263   case SystemZ::CallJG:
264     LoweredMI = MCInstBuilder(SystemZ::JG)
265       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
266     break;
267 
268   case SystemZ::CallBRCL:
269     LoweredMI = MCInstBuilder(SystemZ::BRCL)
270       .addImm(MI->getOperand(0).getImm())
271       .addImm(MI->getOperand(1).getImm())
272       .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT));
273     break;
274 
275   case SystemZ::CallBR:
276     LoweredMI = MCInstBuilder(SystemZ::BR)
277       .addReg(MI->getOperand(0).getReg());
278     break;
279 
280   case SystemZ::CallBCR:
281     LoweredMI = MCInstBuilder(SystemZ::BCR)
282       .addImm(MI->getOperand(0).getImm())
283       .addImm(MI->getOperand(1).getImm())
284       .addReg(MI->getOperand(2).getReg());
285     break;
286 
287   case SystemZ::CRBCall:
288     LoweredMI = MCInstBuilder(SystemZ::CRB)
289       .addReg(MI->getOperand(0).getReg())
290       .addReg(MI->getOperand(1).getReg())
291       .addImm(MI->getOperand(2).getImm())
292       .addReg(MI->getOperand(3).getReg())
293       .addImm(0);
294     break;
295 
296   case SystemZ::CGRBCall:
297     LoweredMI = MCInstBuilder(SystemZ::CGRB)
298       .addReg(MI->getOperand(0).getReg())
299       .addReg(MI->getOperand(1).getReg())
300       .addImm(MI->getOperand(2).getImm())
301       .addReg(MI->getOperand(3).getReg())
302       .addImm(0);
303     break;
304 
305   case SystemZ::CIBCall:
306     LoweredMI = MCInstBuilder(SystemZ::CIB)
307       .addReg(MI->getOperand(0).getReg())
308       .addImm(MI->getOperand(1).getImm())
309       .addImm(MI->getOperand(2).getImm())
310       .addReg(MI->getOperand(3).getReg())
311       .addImm(0);
312     break;
313 
314   case SystemZ::CGIBCall:
315     LoweredMI = MCInstBuilder(SystemZ::CGIB)
316       .addReg(MI->getOperand(0).getReg())
317       .addImm(MI->getOperand(1).getImm())
318       .addImm(MI->getOperand(2).getImm())
319       .addReg(MI->getOperand(3).getReg())
320       .addImm(0);
321     break;
322 
323   case SystemZ::CLRBCall:
324     LoweredMI = MCInstBuilder(SystemZ::CLRB)
325       .addReg(MI->getOperand(0).getReg())
326       .addReg(MI->getOperand(1).getReg())
327       .addImm(MI->getOperand(2).getImm())
328       .addReg(MI->getOperand(3).getReg())
329       .addImm(0);
330     break;
331 
332   case SystemZ::CLGRBCall:
333     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
334       .addReg(MI->getOperand(0).getReg())
335       .addReg(MI->getOperand(1).getReg())
336       .addImm(MI->getOperand(2).getImm())
337       .addReg(MI->getOperand(3).getReg())
338       .addImm(0);
339     break;
340 
341   case SystemZ::CLIBCall:
342     LoweredMI = MCInstBuilder(SystemZ::CLIB)
343       .addReg(MI->getOperand(0).getReg())
344       .addImm(MI->getOperand(1).getImm())
345       .addImm(MI->getOperand(2).getImm())
346       .addReg(MI->getOperand(3).getReg())
347       .addImm(0);
348     break;
349 
350   case SystemZ::CLGIBCall:
351     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
352       .addReg(MI->getOperand(0).getReg())
353       .addImm(MI->getOperand(1).getImm())
354       .addImm(MI->getOperand(2).getImm())
355       .addReg(MI->getOperand(3).getReg())
356       .addImm(0);
357     break;
358 
359   case SystemZ::TLS_GDCALL:
360     LoweredMI = MCInstBuilder(SystemZ::BRASL)
361       .addReg(SystemZ::R14D)
362       .addExpr(getTLSGetOffset(MF->getContext()))
363       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
364     break;
365 
366   case SystemZ::TLS_LDCALL:
367     LoweredMI = MCInstBuilder(SystemZ::BRASL)
368       .addReg(SystemZ::R14D)
369       .addExpr(getTLSGetOffset(MF->getContext()))
370       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
371     break;
372 
373   case SystemZ::GOT:
374     LoweredMI = MCInstBuilder(SystemZ::LARL)
375       .addReg(MI->getOperand(0).getReg())
376       .addExpr(getGlobalOffsetTable(MF->getContext()));
377     break;
378 
379   case SystemZ::IILF64:
380     LoweredMI = MCInstBuilder(SystemZ::IILF)
381       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
382       .addImm(MI->getOperand(2).getImm());
383     break;
384 
385   case SystemZ::IIHF64:
386     LoweredMI = MCInstBuilder(SystemZ::IIHF)
387       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
388       .addImm(MI->getOperand(2).getImm());
389     break;
390 
391   case SystemZ::RISBHH:
392   case SystemZ::RISBHL:
393     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
394     break;
395 
396   case SystemZ::RISBLH:
397   case SystemZ::RISBLL:
398     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
399     break;
400 
401   case SystemZ::VLVGP32:
402     LoweredMI = MCInstBuilder(SystemZ::VLVGP)
403       .addReg(MI->getOperand(0).getReg())
404       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))
405       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));
406     break;
407 
408   case SystemZ::VLR32:
409   case SystemZ::VLR64:
410     LoweredMI = MCInstBuilder(SystemZ::VLR)
411       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
412       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));
413     break;
414 
415   case SystemZ::VL:
416     Lower.lower(MI, LoweredMI);
417     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);
418     break;
419 
420   case SystemZ::VST:
421     Lower.lower(MI, LoweredMI);
422     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);
423     break;
424 
425   case SystemZ::VLM:
426     Lower.lower(MI, LoweredMI);
427     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);
428     break;
429 
430   case SystemZ::VSTM:
431     Lower.lower(MI, LoweredMI);
432     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign);
433     break;
434 
435   case SystemZ::VL32:
436     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);
437     break;
438 
439   case SystemZ::VL64:
440     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);
441     break;
442 
443   case SystemZ::VST32:
444     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);
445     break;
446 
447   case SystemZ::VST64:
448     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);
449     break;
450 
451   case SystemZ::LFER:
452     LoweredMI = MCInstBuilder(SystemZ::VLGVF)
453       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))
454       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))
455       .addReg(0).addImm(0);
456     break;
457 
458   case SystemZ::LEFR:
459     LoweredMI = MCInstBuilder(SystemZ::VLVGF)
460       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
461       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
462       .addReg(MI->getOperand(1).getReg())
463       .addReg(0).addImm(0);
464     break;
465 
466 #define LOWER_LOW(NAME)                                                 \
467   case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
468 
469   LOWER_LOW(IILL);
470   LOWER_LOW(IILH);
471   LOWER_LOW(TMLL);
472   LOWER_LOW(TMLH);
473   LOWER_LOW(NILL);
474   LOWER_LOW(NILH);
475   LOWER_LOW(NILF);
476   LOWER_LOW(OILL);
477   LOWER_LOW(OILH);
478   LOWER_LOW(OILF);
479   LOWER_LOW(XILF);
480 
481 #undef LOWER_LOW
482 
483 #define LOWER_HIGH(NAME) \
484   case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
485 
486   LOWER_HIGH(IIHL);
487   LOWER_HIGH(IIHH);
488   LOWER_HIGH(TMHL);
489   LOWER_HIGH(TMHH);
490   LOWER_HIGH(NIHL);
491   LOWER_HIGH(NIHH);
492   LOWER_HIGH(NIHF);
493   LOWER_HIGH(OIHL);
494   LOWER_HIGH(OIHH);
495   LOWER_HIGH(OIHF);
496   LOWER_HIGH(XIHF);
497 
498 #undef LOWER_HIGH
499 
500   case SystemZ::Serialize:
501     if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
502       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
503         .addImm(14).addReg(SystemZ::R0D);
504     else
505       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
506         .addImm(15).addReg(SystemZ::R0D);
507     break;
508 
509   // Emit nothing here but a comment if we can.
510   case SystemZ::MemBarrier:
511     OutStreamer->emitRawComment("MEMBARRIER");
512     return;
513 
514   // We want to emit "j .+2" for traps, jumping to the relative immediate field
515   // of the jump instruction, which is an illegal instruction. We cannot emit a
516   // "." symbol, so create and emit a temp label before the instruction and use
517   // that instead.
518   case SystemZ::Trap: {
519     MCSymbol *DotSym = OutContext.createTempSymbol();
520     OutStreamer->emitLabel(DotSym);
521 
522     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
523     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
524     LoweredMI = MCInstBuilder(SystemZ::J)
525       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
526     }
527     break;
528 
529   // Conditional traps will create a branch on condition instruction that jumps
530   // to the relative immediate field of the jump instruction. (eg. "jo .+2")
531   case SystemZ::CondTrap: {
532     MCSymbol *DotSym = OutContext.createTempSymbol();
533     OutStreamer->emitLabel(DotSym);
534 
535     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
536     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
537     LoweredMI = MCInstBuilder(SystemZ::BRC)
538       .addImm(MI->getOperand(0).getImm())
539       .addImm(MI->getOperand(1).getImm())
540       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
541     }
542     break;
543 
544   case TargetOpcode::FENTRY_CALL:
545     LowerFENTRY_CALL(*MI, Lower);
546     return;
547 
548   case TargetOpcode::STACKMAP:
549     LowerSTACKMAP(*MI);
550     return;
551 
552   case TargetOpcode::PATCHPOINT:
553     LowerPATCHPOINT(*MI, Lower);
554     return;
555 
556   case SystemZ::EXRL_Pseudo: {
557     unsigned TargetInsOpc = MI->getOperand(0).getImm();
558     Register LenMinus1Reg = MI->getOperand(1).getReg();
559     Register DestReg = MI->getOperand(2).getReg();
560     int64_t DestDisp = MI->getOperand(3).getImm();
561     Register SrcReg = MI->getOperand(4).getReg();
562     int64_t SrcDisp = MI->getOperand(5).getImm();
563 
564     SystemZTargetStreamer *TS = getTargetStreamer();
565     MCSymbol *DotSym = nullptr;
566     MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
567       .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
568     SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
569     SystemZTargetStreamer::EXRLT2SymMap::iterator I =
570         TS->EXRLTargets2Sym.find(ET_STI);
571     if (I != TS->EXRLTargets2Sym.end())
572       DotSym = I->second;
573     else
574       TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
575     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
576     EmitToStreamer(
577         *OutStreamer,
578         MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
579     return;
580   }
581 
582   default:
583     Lower.lower(MI, LoweredMI);
584     break;
585   }
586   EmitToStreamer(*OutStreamer, LoweredMI);
587 }
588 
589 // Emit the largest nop instruction smaller than or equal to NumBytes
590 // bytes.  Return the size of nop emitted.
591 static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
592                         unsigned NumBytes, const MCSubtargetInfo &STI) {
593   if (NumBytes < 2) {
594     llvm_unreachable("Zero nops?");
595     return 0;
596   }
597   else if (NumBytes < 4) {
598     OutStreamer.emitInstruction(
599         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
600     return 2;
601   }
602   else if (NumBytes < 6) {
603     OutStreamer.emitInstruction(
604         MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
605         STI);
606     return 4;
607   }
608   else {
609     MCSymbol *DotSym = OutContext.createTempSymbol();
610     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
611     OutStreamer.emitLabel(DotSym);
612     OutStreamer.emitInstruction(
613         MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
614     return 6;
615   }
616 }
617 
618 void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
619                                          SystemZMCInstLower &Lower) {
620   MCContext &Ctx = MF->getContext();
621   if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
622     MCSymbol *DotSym = OutContext.createTempSymbol();
623     OutStreamer->PushSection();
624     OutStreamer->SwitchSection(
625         Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
626     OutStreamer->emitSymbolValue(DotSym, 8);
627     OutStreamer->PopSection();
628     OutStreamer->emitLabel(DotSym);
629   }
630 
631   if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
632     EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
633     return;
634   }
635 
636   MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
637   const MCSymbolRefExpr *Op =
638       MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
639   OutStreamer->emitInstruction(
640       MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
641       getSubtargetInfo());
642 }
643 
644 void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
645   const SystemZInstrInfo *TII =
646     static_cast<const SystemZInstrInfo *>(MF->getSubtarget().getInstrInfo());
647 
648   unsigned NumNOPBytes = MI.getOperand(1).getImm();
649 
650   auto &Ctx = OutStreamer->getContext();
651   MCSymbol *MILabel = Ctx.createTempSymbol();
652   OutStreamer->emitLabel(MILabel);
653 
654   SM.recordStackMap(*MILabel, MI);
655   assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
656 
657   // Scan ahead to trim the shadow.
658   unsigned ShadowBytes = 0;
659   const MachineBasicBlock &MBB = *MI.getParent();
660   MachineBasicBlock::const_iterator MII(MI);
661   ++MII;
662   while (ShadowBytes < NumNOPBytes) {
663     if (MII == MBB.end() ||
664         MII->getOpcode() == TargetOpcode::PATCHPOINT ||
665         MII->getOpcode() == TargetOpcode::STACKMAP)
666       break;
667     ShadowBytes += TII->getInstSizeInBytes(*MII);
668     if (MII->isCall())
669       break;
670     ++MII;
671   }
672 
673   // Emit nops.
674   while (ShadowBytes < NumNOPBytes)
675     ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
676                            getSubtargetInfo());
677 }
678 
679 // Lower a patchpoint of the form:
680 // [<def>], <id>, <numBytes>, <target>, <numArgs>
681 void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
682                                         SystemZMCInstLower &Lower) {
683   auto &Ctx = OutStreamer->getContext();
684   MCSymbol *MILabel = Ctx.createTempSymbol();
685   OutStreamer->emitLabel(MILabel);
686 
687   SM.recordPatchPoint(*MILabel, MI);
688   PatchPointOpers Opers(&MI);
689 
690   unsigned EncodedBytes = 0;
691   const MachineOperand &CalleeMO = Opers.getCallTarget();
692 
693   if (CalleeMO.isImm()) {
694     uint64_t CallTarget = CalleeMO.getImm();
695     if (CallTarget) {
696       unsigned ScratchIdx = -1;
697       unsigned ScratchReg = 0;
698       do {
699         ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
700         ScratchReg = MI.getOperand(ScratchIdx).getReg();
701       } while (ScratchReg == SystemZ::R0D);
702 
703       // Materialize the call target address
704       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
705                                       .addReg(ScratchReg)
706                                       .addImm(CallTarget & 0xFFFFFFFF));
707       EncodedBytes += 6;
708       if (CallTarget >> 32) {
709         EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
710                                         .addReg(ScratchReg)
711                                         .addImm(CallTarget >> 32));
712         EncodedBytes += 6;
713       }
714 
715       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
716                                      .addReg(SystemZ::R14D)
717                                      .addReg(ScratchReg));
718       EncodedBytes += 2;
719     }
720   } else if (CalleeMO.isGlobal()) {
721     const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT);
722     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
723                                    .addReg(SystemZ::R14D)
724                                    .addExpr(Expr));
725     EncodedBytes += 6;
726   }
727 
728   // Emit padding.
729   unsigned NumBytes = Opers.getNumPatchBytes();
730   assert(NumBytes >= EncodedBytes &&
731          "Patchpoint can't request size less than the length of a call.");
732   assert((NumBytes - EncodedBytes) % 2 == 0 &&
733          "Invalid number of NOP bytes requested!");
734   while (EncodedBytes < NumBytes)
735     EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
736                             getSubtargetInfo());
737 }
738 
739 // Convert a SystemZ-specific constant pool modifier into the associated
740 // MCSymbolRefExpr variant kind.
741 static MCSymbolRefExpr::VariantKind
742 getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
743   switch (Modifier) {
744   case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
745   case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
746   case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
747   case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
748   }
749   llvm_unreachable("Invalid SystemCPModifier!");
750 }
751 
752 void SystemZAsmPrinter::emitMachineConstantPoolValue(
753     MachineConstantPoolValue *MCPV) {
754   auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
755 
756   const MCExpr *Expr =
757     MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
758                             getModifierVariantKind(ZCPV->getModifier()),
759                             OutContext);
760   uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
761 
762   OutStreamer->emitValue(Expr, Size);
763 }
764 
765 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
766                                         const char *ExtraCode,
767                                         raw_ostream &OS) {
768   const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
769   const MachineOperand &MO = MI->getOperand(OpNo);
770   MCOperand MCOp;
771   if (ExtraCode) {
772     if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
773         SystemZ::GR128BitRegClass.contains(MO.getReg()))
774       MCOp =
775           MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
776     else
777       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
778   } else {
779     SystemZMCInstLower Lower(MF->getContext(), *this);
780     MCOp = Lower.lowerOperand(MO);
781   }
782   SystemZInstPrinter::printOperand(MCOp, MAI, OS);
783   return false;
784 }
785 
786 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
787                                               unsigned OpNo,
788                                               const char *ExtraCode,
789                                               raw_ostream &OS) {
790   SystemZInstPrinter::
791     printAddress(MAI, MI->getOperand(OpNo).getReg(),
792                  MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),
793                  MI->getOperand(OpNo + 2).getReg(), OS);
794   return false;
795 }
796 
797 void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
798   emitStackMaps(SM);
799 }
800 
801 void SystemZAsmPrinter::emitFunctionEntryLabel() {
802   const SystemZSubtarget &Subtarget =
803       static_cast<const SystemZSubtarget &>(MF->getSubtarget());
804 
805   if (Subtarget.getTargetTriple().isOSzOS()) {
806     MCContext &OutContext = OutStreamer->getContext();
807     MCSymbol *EPMarkerSym = OutContext.createTempSymbol("CM_", true);
808 
809     // EntryPoint Marker
810     const MachineFrameInfo &MFFrame = MF->getFrameInfo();
811     bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
812 
813     // Set Flags
814     uint8_t Flags = 0;
815     if (IsUsingAlloca)
816       Flags |= 0x04;
817 
818     uint32_t DSASize = MFFrame.getStackSize();
819 
820     // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
821     uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
822     DSAAndFlags |= Flags;
823 
824     // Emit entry point marker section.
825     OutStreamer->AddComment("XPLINK Routine Layout Entry");
826     OutStreamer->emitLabel(EPMarkerSym);
827     OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
828     OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
829     OutStreamer->AddComment("Mark Type C'1'");
830     OutStreamer->emitInt8(0xF1); // Mark Type.
831     if (OutStreamer->isVerboseAsm()) {
832       OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
833       OutStreamer->AddComment("Entry Flags");
834       if (Flags & 0x04)
835         OutStreamer->AddComment("  Bit 2: 1 = Uses alloca");
836       else
837         OutStreamer->AddComment("  Bit 2: 0 = Does not use alloca");
838     }
839     OutStreamer->emitInt32(DSAAndFlags);
840   }
841 
842   AsmPrinter::emitFunctionEntryLabel();
843 }
844 
845 // Force static initialization.
846 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
847   RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
848 }
849