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