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