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