1 //===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Streams SystemZ assembly language and associated data, in the form of
10 // MCInsts and MCExprs respectively.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "SystemZAsmPrinter.h"
15 #include "MCTargetDesc/SystemZInstPrinter.h"
16 #include "SystemZConstantPoolValue.h"
17 #include "SystemZMCInstLower.h"
18 #include "TargetInfo/SystemZTargetInfo.h"
19 #include "llvm/BinaryFormat/ELF.h"
20 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
21 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
22 #include "llvm/IR/Mangler.h"
23 #include "llvm/MC/MCExpr.h"
24 #include "llvm/MC/MCInstBuilder.h"
25 #include "llvm/MC/MCSectionELF.h"
26 #include "llvm/MC/MCStreamer.h"
27 #include "llvm/Support/TargetRegistry.h"
28 
29 using namespace llvm;
30 
31 // Return an RI instruction like MI with opcode Opcode, but with the
32 // GR64 register operands turned into GR32s.
33 static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
34   if (MI->isCompare())
35     return MCInstBuilder(Opcode)
36       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
37       .addImm(MI->getOperand(1).getImm());
38   else
39     return MCInstBuilder(Opcode)
40       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
41       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
42       .addImm(MI->getOperand(2).getImm());
43 }
44 
45 // Return an RI instruction like MI with opcode Opcode, but with the
46 // GR64 register operands turned into GRH32s.
47 static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
48   if (MI->isCompare())
49     return MCInstBuilder(Opcode)
50       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
51       .addImm(MI->getOperand(1).getImm());
52   else
53     return MCInstBuilder(Opcode)
54       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
55       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))
56       .addImm(MI->getOperand(2).getImm());
57 }
58 
59 // Return an RI instruction like MI with opcode Opcode, but with the
60 // R2 register turned into a GR64.
61 static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
62   return MCInstBuilder(Opcode)
63     .addReg(MI->getOperand(0).getReg())
64     .addReg(MI->getOperand(1).getReg())
65     .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
66     .addImm(MI->getOperand(3).getImm())
67     .addImm(MI->getOperand(4).getImm())
68     .addImm(MI->getOperand(5).getImm());
69 }
70 
71 static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
72   StringRef Name = "__tls_get_offset";
73   return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
74                                  MCSymbolRefExpr::VK_PLT,
75                                  Context);
76 }
77 
78 static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
79   StringRef Name = "_GLOBAL_OFFSET_TABLE_";
80   return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
81                                  MCSymbolRefExpr::VK_None,
82                                  Context);
83 }
84 
85 // MI is an instruction that accepts an optional alignment hint,
86 // and which was already lowered to LoweredMI.  If the alignment
87 // of the original memory operand is known, update LoweredMI to
88 // an instruction with the corresponding hint set.
89 static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI,
90                                unsigned Opcode) {
91   if (!MI->hasOneMemOperand())
92     return;
93   const MachineMemOperand *MMO = *MI->memoperands_begin();
94   unsigned AlignmentHint = 0;
95   if (MMO->getAlign() >= Align(16))
96     AlignmentHint = 4;
97   else if (MMO->getAlign() >= Align(8))
98     AlignmentHint = 3;
99   if (AlignmentHint == 0)
100     return;
101 
102   LoweredMI.setOpcode(Opcode);
103   LoweredMI.addOperand(MCOperand::createImm(AlignmentHint));
104 }
105 
106 // MI loads the high part of a vector from memory.  Return an instruction
107 // that uses replicating vector load Opcode to do the same thing.
108 static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
109   return MCInstBuilder(Opcode)
110     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
111     .addReg(MI->getOperand(1).getReg())
112     .addImm(MI->getOperand(2).getImm())
113     .addReg(MI->getOperand(3).getReg());
114 }
115 
116 // MI stores the high part of a vector to memory.  Return an instruction
117 // that uses elemental vector store Opcode to do the same thing.
118 static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
119   return MCInstBuilder(Opcode)
120     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
121     .addReg(MI->getOperand(1).getReg())
122     .addImm(MI->getOperand(2).getImm())
123     .addReg(MI->getOperand(3).getReg())
124     .addImm(0);
125 }
126 
127 void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
128   SystemZMCInstLower Lower(MF->getContext(), *this);
129   MCInst LoweredMI;
130   switch (MI->getOpcode()) {
131   case SystemZ::Return:
132     LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
133     break;
134 
135   case SystemZ::CondReturn:
136     LoweredMI = MCInstBuilder(SystemZ::BCR)
137       .addImm(MI->getOperand(0).getImm())
138       .addImm(MI->getOperand(1).getImm())
139       .addReg(SystemZ::R14D);
140     break;
141 
142   case SystemZ::CRBReturn:
143     LoweredMI = MCInstBuilder(SystemZ::CRB)
144       .addReg(MI->getOperand(0).getReg())
145       .addReg(MI->getOperand(1).getReg())
146       .addImm(MI->getOperand(2).getImm())
147       .addReg(SystemZ::R14D)
148       .addImm(0);
149     break;
150 
151   case SystemZ::CGRBReturn:
152     LoweredMI = MCInstBuilder(SystemZ::CGRB)
153       .addReg(MI->getOperand(0).getReg())
154       .addReg(MI->getOperand(1).getReg())
155       .addImm(MI->getOperand(2).getImm())
156       .addReg(SystemZ::R14D)
157       .addImm(0);
158     break;
159 
160   case SystemZ::CIBReturn:
161     LoweredMI = MCInstBuilder(SystemZ::CIB)
162       .addReg(MI->getOperand(0).getReg())
163       .addImm(MI->getOperand(1).getImm())
164       .addImm(MI->getOperand(2).getImm())
165       .addReg(SystemZ::R14D)
166       .addImm(0);
167     break;
168 
169   case SystemZ::CGIBReturn:
170     LoweredMI = MCInstBuilder(SystemZ::CGIB)
171       .addReg(MI->getOperand(0).getReg())
172       .addImm(MI->getOperand(1).getImm())
173       .addImm(MI->getOperand(2).getImm())
174       .addReg(SystemZ::R14D)
175       .addImm(0);
176     break;
177 
178   case SystemZ::CLRBReturn:
179     LoweredMI = MCInstBuilder(SystemZ::CLRB)
180       .addReg(MI->getOperand(0).getReg())
181       .addReg(MI->getOperand(1).getReg())
182       .addImm(MI->getOperand(2).getImm())
183       .addReg(SystemZ::R14D)
184       .addImm(0);
185     break;
186 
187   case SystemZ::CLGRBReturn:
188     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
189       .addReg(MI->getOperand(0).getReg())
190       .addReg(MI->getOperand(1).getReg())
191       .addImm(MI->getOperand(2).getImm())
192       .addReg(SystemZ::R14D)
193       .addImm(0);
194     break;
195 
196   case SystemZ::CLIBReturn:
197     LoweredMI = MCInstBuilder(SystemZ::CLIB)
198       .addReg(MI->getOperand(0).getReg())
199       .addImm(MI->getOperand(1).getImm())
200       .addImm(MI->getOperand(2).getImm())
201       .addReg(SystemZ::R14D)
202       .addImm(0);
203     break;
204 
205   case SystemZ::CLGIBReturn:
206     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
207       .addReg(MI->getOperand(0).getReg())
208       .addImm(MI->getOperand(1).getImm())
209       .addImm(MI->getOperand(2).getImm())
210       .addReg(SystemZ::R14D)
211       .addImm(0);
212     break;
213 
214   case SystemZ::CallBRASL:
215     LoweredMI = MCInstBuilder(SystemZ::BRASL)
216       .addReg(SystemZ::R14D)
217       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
218     break;
219 
220   case SystemZ::CallBASR:
221     LoweredMI = MCInstBuilder(SystemZ::BASR)
222       .addReg(SystemZ::R14D)
223       .addReg(MI->getOperand(0).getReg());
224     break;
225 
226   case SystemZ::CallJG:
227     LoweredMI = MCInstBuilder(SystemZ::JG)
228       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
229     break;
230 
231   case SystemZ::CallBRCL:
232     LoweredMI = MCInstBuilder(SystemZ::BRCL)
233       .addImm(MI->getOperand(0).getImm())
234       .addImm(MI->getOperand(1).getImm())
235       .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT));
236     break;
237 
238   case SystemZ::CallBR:
239     LoweredMI = MCInstBuilder(SystemZ::BR)
240       .addReg(MI->getOperand(0).getReg());
241     break;
242 
243   case SystemZ::CallBCR:
244     LoweredMI = MCInstBuilder(SystemZ::BCR)
245       .addImm(MI->getOperand(0).getImm())
246       .addImm(MI->getOperand(1).getImm())
247       .addReg(MI->getOperand(2).getReg());
248     break;
249 
250   case SystemZ::CRBCall:
251     LoweredMI = MCInstBuilder(SystemZ::CRB)
252       .addReg(MI->getOperand(0).getReg())
253       .addReg(MI->getOperand(1).getReg())
254       .addImm(MI->getOperand(2).getImm())
255       .addReg(MI->getOperand(3).getReg())
256       .addImm(0);
257     break;
258 
259   case SystemZ::CGRBCall:
260     LoweredMI = MCInstBuilder(SystemZ::CGRB)
261       .addReg(MI->getOperand(0).getReg())
262       .addReg(MI->getOperand(1).getReg())
263       .addImm(MI->getOperand(2).getImm())
264       .addReg(MI->getOperand(3).getReg())
265       .addImm(0);
266     break;
267 
268   case SystemZ::CIBCall:
269     LoweredMI = MCInstBuilder(SystemZ::CIB)
270       .addReg(MI->getOperand(0).getReg())
271       .addImm(MI->getOperand(1).getImm())
272       .addImm(MI->getOperand(2).getImm())
273       .addReg(MI->getOperand(3).getReg())
274       .addImm(0);
275     break;
276 
277   case SystemZ::CGIBCall:
278     LoweredMI = MCInstBuilder(SystemZ::CGIB)
279       .addReg(MI->getOperand(0).getReg())
280       .addImm(MI->getOperand(1).getImm())
281       .addImm(MI->getOperand(2).getImm())
282       .addReg(MI->getOperand(3).getReg())
283       .addImm(0);
284     break;
285 
286   case SystemZ::CLRBCall:
287     LoweredMI = MCInstBuilder(SystemZ::CLRB)
288       .addReg(MI->getOperand(0).getReg())
289       .addReg(MI->getOperand(1).getReg())
290       .addImm(MI->getOperand(2).getImm())
291       .addReg(MI->getOperand(3).getReg())
292       .addImm(0);
293     break;
294 
295   case SystemZ::CLGRBCall:
296     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
297       .addReg(MI->getOperand(0).getReg())
298       .addReg(MI->getOperand(1).getReg())
299       .addImm(MI->getOperand(2).getImm())
300       .addReg(MI->getOperand(3).getReg())
301       .addImm(0);
302     break;
303 
304   case SystemZ::CLIBCall:
305     LoweredMI = MCInstBuilder(SystemZ::CLIB)
306       .addReg(MI->getOperand(0).getReg())
307       .addImm(MI->getOperand(1).getImm())
308       .addImm(MI->getOperand(2).getImm())
309       .addReg(MI->getOperand(3).getReg())
310       .addImm(0);
311     break;
312 
313   case SystemZ::CLGIBCall:
314     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
315       .addReg(MI->getOperand(0).getReg())
316       .addImm(MI->getOperand(1).getImm())
317       .addImm(MI->getOperand(2).getImm())
318       .addReg(MI->getOperand(3).getReg())
319       .addImm(0);
320     break;
321 
322   case SystemZ::TLS_GDCALL:
323     LoweredMI = MCInstBuilder(SystemZ::BRASL)
324       .addReg(SystemZ::R14D)
325       .addExpr(getTLSGetOffset(MF->getContext()))
326       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
327     break;
328 
329   case SystemZ::TLS_LDCALL:
330     LoweredMI = MCInstBuilder(SystemZ::BRASL)
331       .addReg(SystemZ::R14D)
332       .addExpr(getTLSGetOffset(MF->getContext()))
333       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
334     break;
335 
336   case SystemZ::GOT:
337     LoweredMI = MCInstBuilder(SystemZ::LARL)
338       .addReg(MI->getOperand(0).getReg())
339       .addExpr(getGlobalOffsetTable(MF->getContext()));
340     break;
341 
342   case SystemZ::IILF64:
343     LoweredMI = MCInstBuilder(SystemZ::IILF)
344       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
345       .addImm(MI->getOperand(2).getImm());
346     break;
347 
348   case SystemZ::IIHF64:
349     LoweredMI = MCInstBuilder(SystemZ::IIHF)
350       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
351       .addImm(MI->getOperand(2).getImm());
352     break;
353 
354   case SystemZ::RISBHH:
355   case SystemZ::RISBHL:
356     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
357     break;
358 
359   case SystemZ::RISBLH:
360   case SystemZ::RISBLL:
361     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
362     break;
363 
364   case SystemZ::VLVGP32:
365     LoweredMI = MCInstBuilder(SystemZ::VLVGP)
366       .addReg(MI->getOperand(0).getReg())
367       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))
368       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));
369     break;
370 
371   case SystemZ::VLR32:
372   case SystemZ::VLR64:
373     LoweredMI = MCInstBuilder(SystemZ::VLR)
374       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
375       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));
376     break;
377 
378   case SystemZ::VL:
379     Lower.lower(MI, LoweredMI);
380     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);
381     break;
382 
383   case SystemZ::VST:
384     Lower.lower(MI, LoweredMI);
385     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);
386     break;
387 
388   case SystemZ::VLM:
389     Lower.lower(MI, LoweredMI);
390     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);
391     break;
392 
393   case SystemZ::VSTM:
394     Lower.lower(MI, LoweredMI);
395     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign);
396     break;
397 
398   case SystemZ::VL32:
399     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);
400     break;
401 
402   case SystemZ::VL64:
403     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);
404     break;
405 
406   case SystemZ::VST32:
407     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);
408     break;
409 
410   case SystemZ::VST64:
411     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);
412     break;
413 
414   case SystemZ::LFER:
415     LoweredMI = MCInstBuilder(SystemZ::VLGVF)
416       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))
417       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))
418       .addReg(0).addImm(0);
419     break;
420 
421   case SystemZ::LEFR:
422     LoweredMI = MCInstBuilder(SystemZ::VLVGF)
423       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
424       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
425       .addReg(MI->getOperand(1).getReg())
426       .addReg(0).addImm(0);
427     break;
428 
429 #define LOWER_LOW(NAME)                                                 \
430   case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
431 
432   LOWER_LOW(IILL);
433   LOWER_LOW(IILH);
434   LOWER_LOW(TMLL);
435   LOWER_LOW(TMLH);
436   LOWER_LOW(NILL);
437   LOWER_LOW(NILH);
438   LOWER_LOW(NILF);
439   LOWER_LOW(OILL);
440   LOWER_LOW(OILH);
441   LOWER_LOW(OILF);
442   LOWER_LOW(XILF);
443 
444 #undef LOWER_LOW
445 
446 #define LOWER_HIGH(NAME) \
447   case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
448 
449   LOWER_HIGH(IIHL);
450   LOWER_HIGH(IIHH);
451   LOWER_HIGH(TMHL);
452   LOWER_HIGH(TMHH);
453   LOWER_HIGH(NIHL);
454   LOWER_HIGH(NIHH);
455   LOWER_HIGH(NIHF);
456   LOWER_HIGH(OIHL);
457   LOWER_HIGH(OIHH);
458   LOWER_HIGH(OIHF);
459   LOWER_HIGH(XIHF);
460 
461 #undef LOWER_HIGH
462 
463   case SystemZ::Serialize:
464     if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
465       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
466         .addImm(14).addReg(SystemZ::R0D);
467     else
468       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
469         .addImm(15).addReg(SystemZ::R0D);
470     break;
471 
472   // Emit nothing here but a comment if we can.
473   case SystemZ::MemBarrier:
474     OutStreamer->emitRawComment("MEMBARRIER");
475     return;
476 
477   // We want to emit "j .+2" for traps, jumping to the relative immediate field
478   // of the jump instruction, which is an illegal instruction. We cannot emit a
479   // "." symbol, so create and emit a temp label before the instruction and use
480   // that instead.
481   case SystemZ::Trap: {
482     MCSymbol *DotSym = OutContext.createTempSymbol();
483     OutStreamer->emitLabel(DotSym);
484 
485     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
486     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
487     LoweredMI = MCInstBuilder(SystemZ::J)
488       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
489     }
490     break;
491 
492   // Conditional traps will create a branch on condition instruction that jumps
493   // to the relative immediate field of the jump instruction. (eg. "jo .+2")
494   case SystemZ::CondTrap: {
495     MCSymbol *DotSym = OutContext.createTempSymbol();
496     OutStreamer->emitLabel(DotSym);
497 
498     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
499     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
500     LoweredMI = MCInstBuilder(SystemZ::BRC)
501       .addImm(MI->getOperand(0).getImm())
502       .addImm(MI->getOperand(1).getImm())
503       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
504     }
505     break;
506 
507   case TargetOpcode::FENTRY_CALL:
508     LowerFENTRY_CALL(*MI, Lower);
509     return;
510 
511   case TargetOpcode::STACKMAP:
512     LowerSTACKMAP(*MI);
513     return;
514 
515   case TargetOpcode::PATCHPOINT:
516     LowerPATCHPOINT(*MI, Lower);
517     return;
518 
519   default:
520     Lower.lower(MI, LoweredMI);
521     break;
522   }
523   EmitToStreamer(*OutStreamer, LoweredMI);
524 }
525 
526 // Emit the largest nop instruction smaller than or equal to NumBytes
527 // bytes.  Return the size of nop emitted.
528 static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
529                         unsigned NumBytes, const MCSubtargetInfo &STI) {
530   if (NumBytes < 2) {
531     llvm_unreachable("Zero nops?");
532     return 0;
533   }
534   else if (NumBytes < 4) {
535     OutStreamer.emitInstruction(
536         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
537     return 2;
538   }
539   else if (NumBytes < 6) {
540     OutStreamer.emitInstruction(
541         MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
542         STI);
543     return 4;
544   }
545   else {
546     MCSymbol *DotSym = OutContext.createTempSymbol();
547     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
548     OutStreamer.emitLabel(DotSym);
549     OutStreamer.emitInstruction(
550         MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
551     return 6;
552   }
553 }
554 
555 void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
556                                          SystemZMCInstLower &Lower) {
557   MCContext &Ctx = MF->getContext();
558   if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
559     MCSymbol *DotSym = OutContext.createTempSymbol();
560     OutStreamer->PushSection();
561     OutStreamer->SwitchSection(
562         Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
563     OutStreamer->emitSymbolValue(DotSym, 8);
564     OutStreamer->PopSection();
565     OutStreamer->emitLabel(DotSym);
566   }
567 
568   if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
569     EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
570     return;
571   }
572 
573   MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
574   const MCSymbolRefExpr *Op =
575       MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
576   OutStreamer->emitInstruction(
577       MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
578       getSubtargetInfo());
579 }
580 
581 void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
582   const SystemZInstrInfo *TII =
583     static_cast<const SystemZInstrInfo *>(MF->getSubtarget().getInstrInfo());
584 
585   unsigned NumNOPBytes = MI.getOperand(1).getImm();
586 
587   auto &Ctx = OutStreamer->getContext();
588   MCSymbol *MILabel = Ctx.createTempSymbol();
589   OutStreamer->emitLabel(MILabel);
590 
591   SM.recordStackMap(*MILabel, MI);
592   assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
593 
594   // Scan ahead to trim the shadow.
595   unsigned ShadowBytes = 0;
596   const MachineBasicBlock &MBB = *MI.getParent();
597   MachineBasicBlock::const_iterator MII(MI);
598   ++MII;
599   while (ShadowBytes < NumNOPBytes) {
600     if (MII == MBB.end() ||
601         MII->getOpcode() == TargetOpcode::PATCHPOINT ||
602         MII->getOpcode() == TargetOpcode::STACKMAP)
603       break;
604     ShadowBytes += TII->getInstSizeInBytes(*MII);
605     if (MII->isCall())
606       break;
607     ++MII;
608   }
609 
610   // Emit nops.
611   while (ShadowBytes < NumNOPBytes)
612     ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
613                            getSubtargetInfo());
614 }
615 
616 // Lower a patchpoint of the form:
617 // [<def>], <id>, <numBytes>, <target>, <numArgs>
618 void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
619                                         SystemZMCInstLower &Lower) {
620   auto &Ctx = OutStreamer->getContext();
621   MCSymbol *MILabel = Ctx.createTempSymbol();
622   OutStreamer->emitLabel(MILabel);
623 
624   SM.recordPatchPoint(*MILabel, MI);
625   PatchPointOpers Opers(&MI);
626 
627   unsigned EncodedBytes = 0;
628   const MachineOperand &CalleeMO = Opers.getCallTarget();
629 
630   if (CalleeMO.isImm()) {
631     uint64_t CallTarget = CalleeMO.getImm();
632     if (CallTarget) {
633       unsigned ScratchIdx = -1;
634       unsigned ScratchReg = 0;
635       do {
636         ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
637         ScratchReg = MI.getOperand(ScratchIdx).getReg();
638       } while (ScratchReg == SystemZ::R0D);
639 
640       // Materialize the call target address
641       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
642                                       .addReg(ScratchReg)
643                                       .addImm(CallTarget & 0xFFFFFFFF));
644       EncodedBytes += 6;
645       if (CallTarget >> 32) {
646         EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
647                                         .addReg(ScratchReg)
648                                         .addImm(CallTarget >> 32));
649         EncodedBytes += 6;
650       }
651 
652       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
653                                      .addReg(SystemZ::R14D)
654                                      .addReg(ScratchReg));
655       EncodedBytes += 2;
656     }
657   } else if (CalleeMO.isGlobal()) {
658     const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT);
659     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
660                                    .addReg(SystemZ::R14D)
661                                    .addExpr(Expr));
662     EncodedBytes += 6;
663   }
664 
665   // Emit padding.
666   unsigned NumBytes = Opers.getNumPatchBytes();
667   assert(NumBytes >= EncodedBytes &&
668          "Patchpoint can't request size less than the length of a call.");
669   assert((NumBytes - EncodedBytes) % 2 == 0 &&
670          "Invalid number of NOP bytes requested!");
671   while (EncodedBytes < NumBytes)
672     EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
673                             getSubtargetInfo());
674 }
675 
676 // Convert a SystemZ-specific constant pool modifier into the associated
677 // MCSymbolRefExpr variant kind.
678 static MCSymbolRefExpr::VariantKind
679 getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
680   switch (Modifier) {
681   case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
682   case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
683   case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
684   case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
685   }
686   llvm_unreachable("Invalid SystemCPModifier!");
687 }
688 
689 void SystemZAsmPrinter::emitMachineConstantPoolValue(
690     MachineConstantPoolValue *MCPV) {
691   auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
692 
693   const MCExpr *Expr =
694     MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
695                             getModifierVariantKind(ZCPV->getModifier()),
696                             OutContext);
697   uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
698 
699   OutStreamer->emitValue(Expr, Size);
700 }
701 
702 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
703                                         const char *ExtraCode,
704                                         raw_ostream &OS) {
705   if (ExtraCode)
706     return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
707   SystemZMCInstLower Lower(MF->getContext(), *this);
708   MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo)));
709   SystemZInstPrinter::printOperand(MO, MAI, OS);
710   return false;
711 }
712 
713 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
714                                               unsigned OpNo,
715                                               const char *ExtraCode,
716                                               raw_ostream &OS) {
717   SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(),
718                                    MI->getOperand(OpNo + 1).getImm(),
719                                    MI->getOperand(OpNo + 2).getReg(), OS);
720   return false;
721 }
722 
723 void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
724   emitStackMaps(SM);
725 }
726 
727 // Force static initialization.
728 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
729   RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
730 }
731