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