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