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->memoperands_empty())
92     return;
93 
94   Align Alignment = Align(16);
95   for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(),
96          EE = MI->memoperands_end(); MMOI != EE; ++MMOI)
97     if ((*MMOI)->getAlign() < Alignment)
98       Alignment = (*MMOI)->getAlign();
99 
100   unsigned AlignmentHint = 0;
101   if (Alignment >= Align(16))
102     AlignmentHint = 4;
103   else if (Alignment >= Align(8))
104     AlignmentHint = 3;
105   if (AlignmentHint == 0)
106     return;
107 
108   LoweredMI.setOpcode(Opcode);
109   LoweredMI.addOperand(MCOperand::createImm(AlignmentHint));
110 }
111 
112 // MI loads the high part of a vector from memory.  Return an instruction
113 // that uses replicating vector load Opcode to do the same thing.
114 static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
115   return MCInstBuilder(Opcode)
116     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
117     .addReg(MI->getOperand(1).getReg())
118     .addImm(MI->getOperand(2).getImm())
119     .addReg(MI->getOperand(3).getReg());
120 }
121 
122 // MI stores the high part of a vector to memory.  Return an instruction
123 // that uses elemental vector store Opcode to do the same thing.
124 static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
125   return MCInstBuilder(Opcode)
126     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
127     .addReg(MI->getOperand(1).getReg())
128     .addImm(MI->getOperand(2).getImm())
129     .addReg(MI->getOperand(3).getReg())
130     .addImm(0);
131 }
132 
133 // The XPLINK ABI requires that a no-op encoding the call type is emitted after
134 // each call to a subroutine. This information can be used by the called
135 // function to determine its entry point, e.g. for generating a backtrace. The
136 // call type is encoded as a register number in the bcr instruction. See
137 // enumeration CallType for the possible values.
138 void SystemZAsmPrinter::emitCallInformation(CallType CT) {
139   EmitToStreamer(*OutStreamer,
140                  MCInstBuilder(SystemZ::BCRAsm)
141                      .addImm(0)
142                      .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
143 }
144 
145 void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
146   SystemZMCInstLower Lower(MF->getContext(), *this);
147   MCInst LoweredMI;
148   switch (MI->getOpcode()) {
149   case SystemZ::Return:
150     LoweredMI = MCInstBuilder(SystemZ::BR)
151       .addReg(SystemZ::R14D);
152     break;
153 
154   case SystemZ::Return_XPLINK:
155     LoweredMI = MCInstBuilder(SystemZ::B)
156       .addReg(SystemZ::R7D)
157       .addImm(2)
158       .addReg(0);
159     break;
160 
161   case SystemZ::CondReturn:
162     LoweredMI = MCInstBuilder(SystemZ::BCR)
163       .addImm(MI->getOperand(0).getImm())
164       .addImm(MI->getOperand(1).getImm())
165       .addReg(SystemZ::R14D);
166     break;
167 
168   case SystemZ::CondReturn_XPLINK:
169     LoweredMI = MCInstBuilder(SystemZ::BC)
170       .addImm(MI->getOperand(0).getImm())
171       .addImm(MI->getOperand(1).getImm())
172       .addReg(SystemZ::R7D)
173       .addImm(2)
174       .addReg(0);
175     break;
176 
177   case SystemZ::CRBReturn:
178     LoweredMI = MCInstBuilder(SystemZ::CRB)
179       .addReg(MI->getOperand(0).getReg())
180       .addReg(MI->getOperand(1).getReg())
181       .addImm(MI->getOperand(2).getImm())
182       .addReg(SystemZ::R14D)
183       .addImm(0);
184     break;
185 
186   case SystemZ::CGRBReturn:
187     LoweredMI = MCInstBuilder(SystemZ::CGRB)
188       .addReg(MI->getOperand(0).getReg())
189       .addReg(MI->getOperand(1).getReg())
190       .addImm(MI->getOperand(2).getImm())
191       .addReg(SystemZ::R14D)
192       .addImm(0);
193     break;
194 
195   case SystemZ::CIBReturn:
196     LoweredMI = MCInstBuilder(SystemZ::CIB)
197       .addReg(MI->getOperand(0).getReg())
198       .addImm(MI->getOperand(1).getImm())
199       .addImm(MI->getOperand(2).getImm())
200       .addReg(SystemZ::R14D)
201       .addImm(0);
202     break;
203 
204   case SystemZ::CGIBReturn:
205     LoweredMI = MCInstBuilder(SystemZ::CGIB)
206       .addReg(MI->getOperand(0).getReg())
207       .addImm(MI->getOperand(1).getImm())
208       .addImm(MI->getOperand(2).getImm())
209       .addReg(SystemZ::R14D)
210       .addImm(0);
211     break;
212 
213   case SystemZ::CLRBReturn:
214     LoweredMI = MCInstBuilder(SystemZ::CLRB)
215       .addReg(MI->getOperand(0).getReg())
216       .addReg(MI->getOperand(1).getReg())
217       .addImm(MI->getOperand(2).getImm())
218       .addReg(SystemZ::R14D)
219       .addImm(0);
220     break;
221 
222   case SystemZ::CLGRBReturn:
223     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
224       .addReg(MI->getOperand(0).getReg())
225       .addReg(MI->getOperand(1).getReg())
226       .addImm(MI->getOperand(2).getImm())
227       .addReg(SystemZ::R14D)
228       .addImm(0);
229     break;
230 
231   case SystemZ::CLIBReturn:
232     LoweredMI = MCInstBuilder(SystemZ::CLIB)
233       .addReg(MI->getOperand(0).getReg())
234       .addImm(MI->getOperand(1).getImm())
235       .addImm(MI->getOperand(2).getImm())
236       .addReg(SystemZ::R14D)
237       .addImm(0);
238     break;
239 
240   case SystemZ::CLGIBReturn:
241     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
242       .addReg(MI->getOperand(0).getReg())
243       .addImm(MI->getOperand(1).getImm())
244       .addImm(MI->getOperand(2).getImm())
245       .addReg(SystemZ::R14D)
246       .addImm(0);
247     break;
248 
249   case SystemZ::CallBRASL_XPLINK64:
250     EmitToStreamer(*OutStreamer,
251                    MCInstBuilder(SystemZ::BRASL)
252                        .addReg(SystemZ::R7D)
253                        .addExpr(Lower.getExpr(MI->getOperand(0),
254                                               MCSymbolRefExpr::VK_PLT)));
255     emitCallInformation(CallType::BRASL7);
256     return;
257 
258   case SystemZ::CallBASR_XPLINK64:
259     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
260                                      .addReg(SystemZ::R7D)
261                                      .addReg(MI->getOperand(0).getReg()));
262     emitCallInformation(CallType::BASR76);
263     return;
264 
265   case SystemZ::CallBASR_STACKEXT:
266     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
267                                      .addReg(SystemZ::R3D)
268                                      .addReg(MI->getOperand(0).getReg()));
269     emitCallInformation(CallType::BASR33);
270     return;
271 
272   case SystemZ::CallBRASL:
273     LoweredMI = MCInstBuilder(SystemZ::BRASL)
274       .addReg(SystemZ::R14D)
275       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
276     break;
277 
278   case SystemZ::CallBASR:
279     LoweredMI = MCInstBuilder(SystemZ::BASR)
280       .addReg(SystemZ::R14D)
281       .addReg(MI->getOperand(0).getReg());
282     break;
283 
284   case SystemZ::CallJG:
285     LoweredMI = MCInstBuilder(SystemZ::JG)
286       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
287     break;
288 
289   case SystemZ::CallBRCL:
290     LoweredMI = MCInstBuilder(SystemZ::BRCL)
291       .addImm(MI->getOperand(0).getImm())
292       .addImm(MI->getOperand(1).getImm())
293       .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT));
294     break;
295 
296   case SystemZ::CallBR:
297     LoweredMI = MCInstBuilder(SystemZ::BR)
298       .addReg(MI->getOperand(0).getReg());
299     break;
300 
301   case SystemZ::CallBCR:
302     LoweredMI = MCInstBuilder(SystemZ::BCR)
303       .addImm(MI->getOperand(0).getImm())
304       .addImm(MI->getOperand(1).getImm())
305       .addReg(MI->getOperand(2).getReg());
306     break;
307 
308   case SystemZ::CRBCall:
309     LoweredMI = MCInstBuilder(SystemZ::CRB)
310       .addReg(MI->getOperand(0).getReg())
311       .addReg(MI->getOperand(1).getReg())
312       .addImm(MI->getOperand(2).getImm())
313       .addReg(MI->getOperand(3).getReg())
314       .addImm(0);
315     break;
316 
317   case SystemZ::CGRBCall:
318     LoweredMI = MCInstBuilder(SystemZ::CGRB)
319       .addReg(MI->getOperand(0).getReg())
320       .addReg(MI->getOperand(1).getReg())
321       .addImm(MI->getOperand(2).getImm())
322       .addReg(MI->getOperand(3).getReg())
323       .addImm(0);
324     break;
325 
326   case SystemZ::CIBCall:
327     LoweredMI = MCInstBuilder(SystemZ::CIB)
328       .addReg(MI->getOperand(0).getReg())
329       .addImm(MI->getOperand(1).getImm())
330       .addImm(MI->getOperand(2).getImm())
331       .addReg(MI->getOperand(3).getReg())
332       .addImm(0);
333     break;
334 
335   case SystemZ::CGIBCall:
336     LoweredMI = MCInstBuilder(SystemZ::CGIB)
337       .addReg(MI->getOperand(0).getReg())
338       .addImm(MI->getOperand(1).getImm())
339       .addImm(MI->getOperand(2).getImm())
340       .addReg(MI->getOperand(3).getReg())
341       .addImm(0);
342     break;
343 
344   case SystemZ::CLRBCall:
345     LoweredMI = MCInstBuilder(SystemZ::CLRB)
346       .addReg(MI->getOperand(0).getReg())
347       .addReg(MI->getOperand(1).getReg())
348       .addImm(MI->getOperand(2).getImm())
349       .addReg(MI->getOperand(3).getReg())
350       .addImm(0);
351     break;
352 
353   case SystemZ::CLGRBCall:
354     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
355       .addReg(MI->getOperand(0).getReg())
356       .addReg(MI->getOperand(1).getReg())
357       .addImm(MI->getOperand(2).getImm())
358       .addReg(MI->getOperand(3).getReg())
359       .addImm(0);
360     break;
361 
362   case SystemZ::CLIBCall:
363     LoweredMI = MCInstBuilder(SystemZ::CLIB)
364       .addReg(MI->getOperand(0).getReg())
365       .addImm(MI->getOperand(1).getImm())
366       .addImm(MI->getOperand(2).getImm())
367       .addReg(MI->getOperand(3).getReg())
368       .addImm(0);
369     break;
370 
371   case SystemZ::CLGIBCall:
372     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
373       .addReg(MI->getOperand(0).getReg())
374       .addImm(MI->getOperand(1).getImm())
375       .addImm(MI->getOperand(2).getImm())
376       .addReg(MI->getOperand(3).getReg())
377       .addImm(0);
378     break;
379 
380   case SystemZ::TLS_GDCALL:
381     LoweredMI = MCInstBuilder(SystemZ::BRASL)
382       .addReg(SystemZ::R14D)
383       .addExpr(getTLSGetOffset(MF->getContext()))
384       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
385     break;
386 
387   case SystemZ::TLS_LDCALL:
388     LoweredMI = MCInstBuilder(SystemZ::BRASL)
389       .addReg(SystemZ::R14D)
390       .addExpr(getTLSGetOffset(MF->getContext()))
391       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
392     break;
393 
394   case SystemZ::GOT:
395     LoweredMI = MCInstBuilder(SystemZ::LARL)
396       .addReg(MI->getOperand(0).getReg())
397       .addExpr(getGlobalOffsetTable(MF->getContext()));
398     break;
399 
400   case SystemZ::IILF64:
401     LoweredMI = MCInstBuilder(SystemZ::IILF)
402       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
403       .addImm(MI->getOperand(2).getImm());
404     break;
405 
406   case SystemZ::IIHF64:
407     LoweredMI = MCInstBuilder(SystemZ::IIHF)
408       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
409       .addImm(MI->getOperand(2).getImm());
410     break;
411 
412   case SystemZ::RISBHH:
413   case SystemZ::RISBHL:
414     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
415     break;
416 
417   case SystemZ::RISBLH:
418   case SystemZ::RISBLL:
419     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
420     break;
421 
422   case SystemZ::VLVGP32:
423     LoweredMI = MCInstBuilder(SystemZ::VLVGP)
424       .addReg(MI->getOperand(0).getReg())
425       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))
426       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));
427     break;
428 
429   case SystemZ::VLR32:
430   case SystemZ::VLR64:
431     LoweredMI = MCInstBuilder(SystemZ::VLR)
432       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
433       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));
434     break;
435 
436   case SystemZ::VL:
437     Lower.lower(MI, LoweredMI);
438     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);
439     break;
440 
441   case SystemZ::VST:
442     Lower.lower(MI, LoweredMI);
443     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);
444     break;
445 
446   case SystemZ::VLM:
447     Lower.lower(MI, LoweredMI);
448     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);
449     break;
450 
451   case SystemZ::VSTM:
452     Lower.lower(MI, LoweredMI);
453     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign);
454     break;
455 
456   case SystemZ::VL32:
457     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);
458     break;
459 
460   case SystemZ::VL64:
461     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);
462     break;
463 
464   case SystemZ::VST32:
465     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);
466     break;
467 
468   case SystemZ::VST64:
469     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);
470     break;
471 
472   case SystemZ::LFER:
473     LoweredMI = MCInstBuilder(SystemZ::VLGVF)
474       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))
475       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))
476       .addReg(0).addImm(0);
477     break;
478 
479   case SystemZ::LEFR:
480     LoweredMI = MCInstBuilder(SystemZ::VLVGF)
481       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
482       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
483       .addReg(MI->getOperand(1).getReg())
484       .addReg(0).addImm(0);
485     break;
486 
487 #define LOWER_LOW(NAME)                                                 \
488   case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
489 
490   LOWER_LOW(IILL);
491   LOWER_LOW(IILH);
492   LOWER_LOW(TMLL);
493   LOWER_LOW(TMLH);
494   LOWER_LOW(NILL);
495   LOWER_LOW(NILH);
496   LOWER_LOW(NILF);
497   LOWER_LOW(OILL);
498   LOWER_LOW(OILH);
499   LOWER_LOW(OILF);
500   LOWER_LOW(XILF);
501 
502 #undef LOWER_LOW
503 
504 #define LOWER_HIGH(NAME) \
505   case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
506 
507   LOWER_HIGH(IIHL);
508   LOWER_HIGH(IIHH);
509   LOWER_HIGH(TMHL);
510   LOWER_HIGH(TMHH);
511   LOWER_HIGH(NIHL);
512   LOWER_HIGH(NIHH);
513   LOWER_HIGH(NIHF);
514   LOWER_HIGH(OIHL);
515   LOWER_HIGH(OIHH);
516   LOWER_HIGH(OIHF);
517   LOWER_HIGH(XIHF);
518 
519 #undef LOWER_HIGH
520 
521   case SystemZ::Serialize:
522     if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
523       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
524         .addImm(14).addReg(SystemZ::R0D);
525     else
526       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
527         .addImm(15).addReg(SystemZ::R0D);
528     break;
529 
530   // Emit nothing here but a comment if we can.
531   case SystemZ::MemBarrier:
532     OutStreamer->emitRawComment("MEMBARRIER");
533     return;
534 
535   // We want to emit "j .+2" for traps, jumping to the relative immediate field
536   // of the jump instruction, which is an illegal instruction. We cannot emit a
537   // "." symbol, so create and emit a temp label before the instruction and use
538   // that instead.
539   case SystemZ::Trap: {
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::J)
546       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
547     }
548     break;
549 
550   // Conditional traps will create a branch on condition instruction that jumps
551   // to the relative immediate field of the jump instruction. (eg. "jo .+2")
552   case SystemZ::CondTrap: {
553     MCSymbol *DotSym = OutContext.createTempSymbol();
554     OutStreamer->emitLabel(DotSym);
555 
556     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
557     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
558     LoweredMI = MCInstBuilder(SystemZ::BRC)
559       .addImm(MI->getOperand(0).getImm())
560       .addImm(MI->getOperand(1).getImm())
561       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
562     }
563     break;
564 
565   case TargetOpcode::FENTRY_CALL:
566     LowerFENTRY_CALL(*MI, Lower);
567     return;
568 
569   case TargetOpcode::STACKMAP:
570     LowerSTACKMAP(*MI);
571     return;
572 
573   case TargetOpcode::PATCHPOINT:
574     LowerPATCHPOINT(*MI, Lower);
575     return;
576 
577   case SystemZ::EXRL_Pseudo: {
578     unsigned TargetInsOpc = MI->getOperand(0).getImm();
579     Register LenMinus1Reg = MI->getOperand(1).getReg();
580     Register DestReg = MI->getOperand(2).getReg();
581     int64_t DestDisp = MI->getOperand(3).getImm();
582     Register SrcReg = MI->getOperand(4).getReg();
583     int64_t SrcDisp = MI->getOperand(5).getImm();
584 
585     SystemZTargetStreamer *TS = getTargetStreamer();
586     MCSymbol *DotSym = nullptr;
587     MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
588       .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
589     SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
590     SystemZTargetStreamer::EXRLT2SymMap::iterator I =
591         TS->EXRLTargets2Sym.find(ET_STI);
592     if (I != TS->EXRLTargets2Sym.end())
593       DotSym = I->second;
594     else
595       TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
596     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
597     EmitToStreamer(
598         *OutStreamer,
599         MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
600     return;
601   }
602 
603   default:
604     Lower.lower(MI, LoweredMI);
605     break;
606   }
607   EmitToStreamer(*OutStreamer, LoweredMI);
608 }
609 
610 // Emit the largest nop instruction smaller than or equal to NumBytes
611 // bytes.  Return the size of nop emitted.
612 static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
613                         unsigned NumBytes, const MCSubtargetInfo &STI) {
614   if (NumBytes < 2) {
615     llvm_unreachable("Zero nops?");
616     return 0;
617   }
618   else if (NumBytes < 4) {
619     OutStreamer.emitInstruction(
620         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
621     return 2;
622   }
623   else if (NumBytes < 6) {
624     OutStreamer.emitInstruction(
625         MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
626         STI);
627     return 4;
628   }
629   else {
630     MCSymbol *DotSym = OutContext.createTempSymbol();
631     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
632     OutStreamer.emitLabel(DotSym);
633     OutStreamer.emitInstruction(
634         MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
635     return 6;
636   }
637 }
638 
639 void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
640                                          SystemZMCInstLower &Lower) {
641   MCContext &Ctx = MF->getContext();
642   if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
643     MCSymbol *DotSym = OutContext.createTempSymbol();
644     OutStreamer->pushSection();
645     OutStreamer->switchSection(
646         Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
647     OutStreamer->emitSymbolValue(DotSym, 8);
648     OutStreamer->popSection();
649     OutStreamer->emitLabel(DotSym);
650   }
651 
652   if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
653     EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
654     return;
655   }
656 
657   MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
658   const MCSymbolRefExpr *Op =
659       MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
660   OutStreamer->emitInstruction(
661       MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
662       getSubtargetInfo());
663 }
664 
665 void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
666   auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo();
667 
668   unsigned NumNOPBytes = MI.getOperand(1).getImm();
669 
670   auto &Ctx = OutStreamer->getContext();
671   MCSymbol *MILabel = Ctx.createTempSymbol();
672   OutStreamer->emitLabel(MILabel);
673 
674   SM.recordStackMap(*MILabel, MI);
675   assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
676 
677   // Scan ahead to trim the shadow.
678   unsigned ShadowBytes = 0;
679   const MachineBasicBlock &MBB = *MI.getParent();
680   MachineBasicBlock::const_iterator MII(MI);
681   ++MII;
682   while (ShadowBytes < NumNOPBytes) {
683     if (MII == MBB.end() ||
684         MII->getOpcode() == TargetOpcode::PATCHPOINT ||
685         MII->getOpcode() == TargetOpcode::STACKMAP)
686       break;
687     ShadowBytes += TII->getInstSizeInBytes(*MII);
688     if (MII->isCall())
689       break;
690     ++MII;
691   }
692 
693   // Emit nops.
694   while (ShadowBytes < NumNOPBytes)
695     ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
696                            getSubtargetInfo());
697 }
698 
699 // Lower a patchpoint of the form:
700 // [<def>], <id>, <numBytes>, <target>, <numArgs>
701 void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
702                                         SystemZMCInstLower &Lower) {
703   auto &Ctx = OutStreamer->getContext();
704   MCSymbol *MILabel = Ctx.createTempSymbol();
705   OutStreamer->emitLabel(MILabel);
706 
707   SM.recordPatchPoint(*MILabel, MI);
708   PatchPointOpers Opers(&MI);
709 
710   unsigned EncodedBytes = 0;
711   const MachineOperand &CalleeMO = Opers.getCallTarget();
712 
713   if (CalleeMO.isImm()) {
714     uint64_t CallTarget = CalleeMO.getImm();
715     if (CallTarget) {
716       unsigned ScratchIdx = -1;
717       unsigned ScratchReg = 0;
718       do {
719         ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
720         ScratchReg = MI.getOperand(ScratchIdx).getReg();
721       } while (ScratchReg == SystemZ::R0D);
722 
723       // Materialize the call target address
724       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
725                                       .addReg(ScratchReg)
726                                       .addImm(CallTarget & 0xFFFFFFFF));
727       EncodedBytes += 6;
728       if (CallTarget >> 32) {
729         EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
730                                         .addReg(ScratchReg)
731                                         .addImm(CallTarget >> 32));
732         EncodedBytes += 6;
733       }
734 
735       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
736                                      .addReg(SystemZ::R14D)
737                                      .addReg(ScratchReg));
738       EncodedBytes += 2;
739     }
740   } else if (CalleeMO.isGlobal()) {
741     const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT);
742     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
743                                    .addReg(SystemZ::R14D)
744                                    .addExpr(Expr));
745     EncodedBytes += 6;
746   }
747 
748   // Emit padding.
749   unsigned NumBytes = Opers.getNumPatchBytes();
750   assert(NumBytes >= EncodedBytes &&
751          "Patchpoint can't request size less than the length of a call.");
752   assert((NumBytes - EncodedBytes) % 2 == 0 &&
753          "Invalid number of NOP bytes requested!");
754   while (EncodedBytes < NumBytes)
755     EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
756                             getSubtargetInfo());
757 }
758 
759 // Convert a SystemZ-specific constant pool modifier into the associated
760 // MCSymbolRefExpr variant kind.
761 static MCSymbolRefExpr::VariantKind
762 getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
763   switch (Modifier) {
764   case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
765   case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
766   case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
767   case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
768   }
769   llvm_unreachable("Invalid SystemCPModifier!");
770 }
771 
772 void SystemZAsmPrinter::emitMachineConstantPoolValue(
773     MachineConstantPoolValue *MCPV) {
774   auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
775 
776   const MCExpr *Expr =
777     MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
778                             getModifierVariantKind(ZCPV->getModifier()),
779                             OutContext);
780   uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
781 
782   OutStreamer->emitValue(Expr, Size);
783 }
784 
785 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
786                                         const char *ExtraCode,
787                                         raw_ostream &OS) {
788   const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
789   const MachineOperand &MO = MI->getOperand(OpNo);
790   MCOperand MCOp;
791   if (ExtraCode) {
792     if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
793         SystemZ::GR128BitRegClass.contains(MO.getReg()))
794       MCOp =
795           MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
796     else
797       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
798   } else {
799     SystemZMCInstLower Lower(MF->getContext(), *this);
800     MCOp = Lower.lowerOperand(MO);
801   }
802   SystemZInstPrinter::printOperand(MCOp, MAI, OS);
803   return false;
804 }
805 
806 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
807                                               unsigned OpNo,
808                                               const char *ExtraCode,
809                                               raw_ostream &OS) {
810   SystemZInstPrinter::
811     printAddress(MAI, MI->getOperand(OpNo).getReg(),
812                  MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),
813                  MI->getOperand(OpNo + 2).getReg(), OS);
814   return false;
815 }
816 
817 void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
818   emitStackMaps(SM);
819 }
820 
821 void SystemZAsmPrinter::emitFunctionBodyEnd() {
822   if (TM.getTargetTriple().isOSzOS()) {
823     // Emit symbol for the end of function if the z/OS target streamer
824     // is used. This is needed to calculate the size of the function.
825     MCSymbol *FnEndSym = createTempSymbol("func_end");
826     OutStreamer->emitLabel(FnEndSym);
827 
828     OutStreamer->pushSection();
829     OutStreamer->switchSection(getObjFileLowering().getPPA1Section());
830     emitPPA1(FnEndSym);
831     OutStreamer->popSection();
832 
833     CurrentFnPPA1Sym = nullptr;
834     CurrentFnEPMarkerSym = nullptr;
835   }
836 }
837 
838 static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
839                           bool StackProtector, bool FPRMask, bool VRMask) {
840   enum class PPA1Flag1 : uint8_t {
841     DSA64Bit = (0x80 >> 0),
842     VarArg = (0x80 >> 7),
843     LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit)
844   };
845   enum class PPA1Flag2 : uint8_t {
846     ExternalProcedure = (0x80 >> 0),
847     STACKPROTECTOR = (0x80 >> 3),
848     LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure)
849   };
850   enum class PPA1Flag3 : uint8_t {
851     FPRMask = (0x80 >> 2),
852     LLVM_MARK_AS_BITMASK_ENUM(FPRMask)
853   };
854   enum class PPA1Flag4 : uint8_t {
855     EPMOffsetPresent = (0x80 >> 0),
856     VRMask = (0x80 >> 2),
857     ProcedureNamePresent = (0x80 >> 7),
858     LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent)
859   };
860 
861   // Declare optional section flags that can be modified.
862   auto Flags1 = PPA1Flag1(0);
863   auto Flags2 = PPA1Flag2::ExternalProcedure;
864   auto Flags3 = PPA1Flag3(0);
865   auto Flags4 = PPA1Flag4::EPMOffsetPresent | PPA1Flag4::ProcedureNamePresent;
866 
867   Flags1 |= PPA1Flag1::DSA64Bit;
868 
869   if (VarArg)
870     Flags1 |= PPA1Flag1::VarArg;
871 
872   if (StackProtector)
873     Flags2 |= PPA1Flag2::STACKPROTECTOR;
874 
875   // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in.
876   if (FPRMask)
877     Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag.
878 
879   if (VRMask)
880     Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag.
881 
882   OutStreamer->AddComment("PPA1 Flags 1");
883   if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit)
884     OutStreamer->AddComment("  Bit 0: 1 = 64-bit DSA");
885   else
886     OutStreamer->AddComment("  Bit 0: 0 = 32-bit DSA");
887   if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg)
888     OutStreamer->AddComment("  Bit 7: 1 = Vararg function");
889   OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1.
890 
891   OutStreamer->AddComment("PPA1 Flags 2");
892   if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure)
893     OutStreamer->AddComment("  Bit 0: 1 = External procedure");
894   if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR)
895     OutStreamer->AddComment("  Bit 3: 1 = STACKPROTECT is enabled");
896   else
897     OutStreamer->AddComment("  Bit 3: 0 = STACKPROTECT is not enabled");
898   OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2.
899 
900   OutStreamer->AddComment("PPA1 Flags 3");
901   if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask)
902     OutStreamer->AddComment("  Bit 2: 1 = FP Reg Mask is in optional area");
903   OutStreamer->emitInt8(
904       static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections).
905 
906   OutStreamer->AddComment("PPA1 Flags 4");
907   if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask)
908     OutStreamer->AddComment("  Bit 2: 1 = Vector Reg Mask is in optional area");
909   OutStreamer->emitInt8(static_cast<uint8_t>(
910       Flags4)); // Flags 4 (optional sections, always emit these).
911 }
912 
913 void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
914   const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
915   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
916   const auto TargetHasVector = Subtarget.hasVector();
917 
918   const SystemZMachineFunctionInfo *ZFI =
919       MF->getInfo<SystemZMachineFunctionInfo>();
920   const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>(
921       Subtarget.getFrameLowering());
922   const MachineFrameInfo &MFFrame = MF->getFrameInfo();
923 
924   // Get saved GPR/FPR/VPR masks.
925   const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
926   uint16_t SavedGPRMask = 0;
927   uint16_t SavedFPRMask = 0;
928   uint8_t SavedVRMask = 0;
929   int64_t OffsetFPR = 0;
930   int64_t OffsetVR = 0;
931   const int64_t TopOfStack =
932       MFFrame.getOffsetAdjustment() + MFFrame.getStackSize();
933 
934   // Loop over the spilled registers. The CalleeSavedInfo can't be used because
935   // it does not contain all spilled registers.
936   for (unsigned I = ZFI->getSpillGPRRegs().LowGPR,
937                 E = ZFI->getSpillGPRRegs().HighGPR;
938        I && E && I <= E; ++I) {
939     unsigned V = TRI->getEncodingValue((Register)I);
940     assert(V < 16 && "GPR index out of range");
941     SavedGPRMask |= 1 << (15 - V);
942   }
943 
944   for (auto &CS : CSI) {
945     unsigned Reg = CS.getReg();
946     unsigned I = TRI->getEncodingValue(Reg);
947 
948     if (SystemZ::FP64BitRegClass.contains(Reg)) {
949       assert(I < 16 && "FPR index out of range");
950       SavedFPRMask |= 1 << (15 - I);
951       int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
952       if (Temp < OffsetFPR)
953         OffsetFPR = Temp;
954     } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
955       assert(I >= 16 && I <= 23 && "VPR index out of range");
956       unsigned BitNum = I - 16;
957       SavedVRMask |= 1 << (7 - BitNum);
958       int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
959       if (Temp < OffsetVR)
960         OffsetVR = Temp;
961     }
962   }
963 
964   // Adjust the offset.
965   OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0;
966   OffsetVR += (OffsetVR < 0) ? TopOfStack : 0;
967 
968   // Get alloca register.
969   uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF));
970   uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0;
971   assert(AllocaReg < 16 && "Can't have alloca register larger than 15");
972   (void)AllocaReg;
973 
974   // Build FPR save area offset.
975   uint32_t FrameAndFPROffset = 0;
976   if (SavedFPRMask) {
977     uint64_t FPRSaveAreaOffset = OffsetFPR;
978     assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range");
979 
980     FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
981     FrameAndFPROffset |= FrameReg << 28;                // Put into top 4 bits.
982   }
983 
984   // Build VR save area offset.
985   uint32_t FrameAndVROffset = 0;
986   if (TargetHasVector && SavedVRMask) {
987     uint64_t VRSaveAreaOffset = OffsetVR;
988     assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range");
989 
990     FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
991     FrameAndVROffset |= FrameReg << 28;               // Put into top 4 bits.
992   }
993 
994   // Emit PPA1 section.
995   OutStreamer->AddComment("PPA1");
996   OutStreamer->emitLabel(CurrentFnPPA1Sym);
997   OutStreamer->AddComment("Version");
998   OutStreamer->emitInt8(0x02); // Version.
999   OutStreamer->AddComment("LE Signature X'CE'");
1000   OutStreamer->emitInt8(0xCE); // CEL signature.
1001   OutStreamer->AddComment("Saved GPR Mask");
1002   OutStreamer->emitInt16(SavedGPRMask);
1003 
1004   emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),
1005                 MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
1006                 TargetHasVector && SavedVRMask != 0);
1007 
1008   OutStreamer->AddComment("Length/4 of Parms");
1009   OutStreamer->emitInt16(
1010       static_cast<uint16_t>(MFFrame.getMaxCallFrameSize() / 4)); // Parms/4.
1011   OutStreamer->AddComment("Length of Code");
1012   OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4);
1013 
1014   // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
1015   if (SavedFPRMask) {
1016     OutStreamer->AddComment("FPR mask");
1017     OutStreamer->emitInt16(SavedFPRMask);
1018     OutStreamer->AddComment("AR mask");
1019     OutStreamer->emitInt16(0); // AR Mask, unused currently.
1020     OutStreamer->AddComment("FPR Save Area Locator");
1021     OutStreamer->AddComment(Twine("  Bit 0-3: Register R")
1022                                 .concat(utostr(FrameAndFPROffset >> 28))
1023                                 .str());
1024     OutStreamer->AddComment(Twine("  Bit 4-31: Offset ")
1025                                 .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF))
1026                                 .str());
1027     OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with
1028                                                // register to add value to
1029                                                // (alloca reg).
1030   }
1031 
1032   // Emit saved VR mask to VR save area.
1033   if (TargetHasVector && SavedVRMask) {
1034     OutStreamer->AddComment("VR mask");
1035     OutStreamer->emitInt8(SavedVRMask);
1036     OutStreamer->emitInt8(0);  // Reserved.
1037     OutStreamer->emitInt16(0); // Also reserved.
1038     OutStreamer->AddComment("VR Save Area Locator");
1039     OutStreamer->AddComment(Twine("  Bit 0-3: Register R")
1040                                 .concat(utostr(FrameAndVROffset >> 28))
1041                                 .str());
1042     OutStreamer->AddComment(Twine("  Bit 4-31: Offset ")
1043                                 .concat(utostr(FrameAndVROffset & 0x0FFFFFFF))
1044                                 .str());
1045     OutStreamer->emitInt32(FrameAndVROffset);
1046   }
1047 
1048   // Emit offset to entry point optional section (0x80 of flags 4).
1049   OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym,
1050                                       4);
1051 }
1052 
1053 void SystemZAsmPrinter::emitFunctionEntryLabel() {
1054   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
1055 
1056   if (Subtarget.getTargetTriple().isOSzOS()) {
1057     MCContext &OutContext = OutStreamer->getContext();
1058 
1059     // Save information for later use.
1060     std::string N(MF->getFunction().hasName()
1061                       ? Twine(MF->getFunction().getName()).concat("_").str()
1062                       : "");
1063 
1064     CurrentFnEPMarkerSym =
1065         OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true);
1066     CurrentFnPPA1Sym =
1067         OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true);
1068 
1069     // EntryPoint Marker
1070     const MachineFrameInfo &MFFrame = MF->getFrameInfo();
1071     bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
1072 
1073     // Set Flags
1074     uint8_t Flags = 0;
1075     if (IsUsingAlloca)
1076       Flags |= 0x04;
1077 
1078     uint32_t DSASize = MFFrame.getStackSize();
1079 
1080     // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
1081     uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
1082     DSAAndFlags |= Flags;
1083 
1084     // Emit entry point marker section.
1085     OutStreamer->AddComment("XPLINK Routine Layout Entry");
1086     OutStreamer->emitLabel(CurrentFnEPMarkerSym);
1087     OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
1088     OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
1089     OutStreamer->AddComment("Mark Type C'1'");
1090     OutStreamer->emitInt8(0xF1); // Mark Type.
1091     OutStreamer->AddComment("Offset to PPA1");
1092     OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym,
1093                                         4);
1094     if (OutStreamer->isVerboseAsm()) {
1095       OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
1096       OutStreamer->AddComment("Entry Flags");
1097       if (Flags & 0x04)
1098         OutStreamer->AddComment("  Bit 2: 1 = Uses alloca");
1099       else
1100         OutStreamer->AddComment("  Bit 2: 0 = Does not use alloca");
1101     }
1102     OutStreamer->emitInt32(DSAAndFlags);
1103   }
1104 
1105   AsmPrinter::emitFunctionEntryLabel();
1106 }
1107 
1108 // Force static initialization.
1109 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
1110   RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
1111 }
1112