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