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