xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp (revision 924226fba12cc9a228c73b956e1b7fa24c60b055)
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/MC/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   case SystemZ::EXRL_Pseudo: {
545     unsigned TargetInsOpc = MI->getOperand(0).getImm();
546     Register LenMinus1Reg = MI->getOperand(1).getReg();
547     Register DestReg = MI->getOperand(2).getReg();
548     int64_t DestDisp = MI->getOperand(3).getImm();
549     Register SrcReg = MI->getOperand(4).getReg();
550     int64_t SrcDisp = MI->getOperand(5).getImm();
551 
552     SystemZTargetStreamer *TS = getTargetStreamer();
553     MCSymbol *DotSym = nullptr;
554     MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
555       .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
556     SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
557     SystemZTargetStreamer::EXRLT2SymMap::iterator I =
558         TS->EXRLTargets2Sym.find(ET_STI);
559     if (I != TS->EXRLTargets2Sym.end())
560       DotSym = I->second;
561     else
562       TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
563     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
564     EmitToStreamer(
565         *OutStreamer,
566         MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
567     return;
568   }
569 
570   default:
571     Lower.lower(MI, LoweredMI);
572     break;
573   }
574   EmitToStreamer(*OutStreamer, LoweredMI);
575 }
576 
577 // Emit the largest nop instruction smaller than or equal to NumBytes
578 // bytes.  Return the size of nop emitted.
579 static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
580                         unsigned NumBytes, const MCSubtargetInfo &STI) {
581   if (NumBytes < 2) {
582     llvm_unreachable("Zero nops?");
583     return 0;
584   }
585   else if (NumBytes < 4) {
586     OutStreamer.emitInstruction(
587         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
588     return 2;
589   }
590   else if (NumBytes < 6) {
591     OutStreamer.emitInstruction(
592         MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
593         STI);
594     return 4;
595   }
596   else {
597     MCSymbol *DotSym = OutContext.createTempSymbol();
598     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
599     OutStreamer.emitLabel(DotSym);
600     OutStreamer.emitInstruction(
601         MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
602     return 6;
603   }
604 }
605 
606 void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
607                                          SystemZMCInstLower &Lower) {
608   MCContext &Ctx = MF->getContext();
609   if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
610     MCSymbol *DotSym = OutContext.createTempSymbol();
611     OutStreamer->PushSection();
612     OutStreamer->SwitchSection(
613         Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
614     OutStreamer->emitSymbolValue(DotSym, 8);
615     OutStreamer->PopSection();
616     OutStreamer->emitLabel(DotSym);
617   }
618 
619   if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
620     EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
621     return;
622   }
623 
624   MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
625   const MCSymbolRefExpr *Op =
626       MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
627   OutStreamer->emitInstruction(
628       MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
629       getSubtargetInfo());
630 }
631 
632 void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
633   const SystemZInstrInfo *TII =
634     static_cast<const SystemZInstrInfo *>(MF->getSubtarget().getInstrInfo());
635 
636   unsigned NumNOPBytes = MI.getOperand(1).getImm();
637 
638   auto &Ctx = OutStreamer->getContext();
639   MCSymbol *MILabel = Ctx.createTempSymbol();
640   OutStreamer->emitLabel(MILabel);
641 
642   SM.recordStackMap(*MILabel, MI);
643   assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
644 
645   // Scan ahead to trim the shadow.
646   unsigned ShadowBytes = 0;
647   const MachineBasicBlock &MBB = *MI.getParent();
648   MachineBasicBlock::const_iterator MII(MI);
649   ++MII;
650   while (ShadowBytes < NumNOPBytes) {
651     if (MII == MBB.end() ||
652         MII->getOpcode() == TargetOpcode::PATCHPOINT ||
653         MII->getOpcode() == TargetOpcode::STACKMAP)
654       break;
655     ShadowBytes += TII->getInstSizeInBytes(*MII);
656     if (MII->isCall())
657       break;
658     ++MII;
659   }
660 
661   // Emit nops.
662   while (ShadowBytes < NumNOPBytes)
663     ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
664                            getSubtargetInfo());
665 }
666 
667 // Lower a patchpoint of the form:
668 // [<def>], <id>, <numBytes>, <target>, <numArgs>
669 void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
670                                         SystemZMCInstLower &Lower) {
671   auto &Ctx = OutStreamer->getContext();
672   MCSymbol *MILabel = Ctx.createTempSymbol();
673   OutStreamer->emitLabel(MILabel);
674 
675   SM.recordPatchPoint(*MILabel, MI);
676   PatchPointOpers Opers(&MI);
677 
678   unsigned EncodedBytes = 0;
679   const MachineOperand &CalleeMO = Opers.getCallTarget();
680 
681   if (CalleeMO.isImm()) {
682     uint64_t CallTarget = CalleeMO.getImm();
683     if (CallTarget) {
684       unsigned ScratchIdx = -1;
685       unsigned ScratchReg = 0;
686       do {
687         ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
688         ScratchReg = MI.getOperand(ScratchIdx).getReg();
689       } while (ScratchReg == SystemZ::R0D);
690 
691       // Materialize the call target address
692       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
693                                       .addReg(ScratchReg)
694                                       .addImm(CallTarget & 0xFFFFFFFF));
695       EncodedBytes += 6;
696       if (CallTarget >> 32) {
697         EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
698                                         .addReg(ScratchReg)
699                                         .addImm(CallTarget >> 32));
700         EncodedBytes += 6;
701       }
702 
703       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
704                                      .addReg(SystemZ::R14D)
705                                      .addReg(ScratchReg));
706       EncodedBytes += 2;
707     }
708   } else if (CalleeMO.isGlobal()) {
709     const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT);
710     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
711                                    .addReg(SystemZ::R14D)
712                                    .addExpr(Expr));
713     EncodedBytes += 6;
714   }
715 
716   // Emit padding.
717   unsigned NumBytes = Opers.getNumPatchBytes();
718   assert(NumBytes >= EncodedBytes &&
719          "Patchpoint can't request size less than the length of a call.");
720   assert((NumBytes - EncodedBytes) % 2 == 0 &&
721          "Invalid number of NOP bytes requested!");
722   while (EncodedBytes < NumBytes)
723     EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
724                             getSubtargetInfo());
725 }
726 
727 // Convert a SystemZ-specific constant pool modifier into the associated
728 // MCSymbolRefExpr variant kind.
729 static MCSymbolRefExpr::VariantKind
730 getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
731   switch (Modifier) {
732   case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
733   case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
734   case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
735   case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
736   }
737   llvm_unreachable("Invalid SystemCPModifier!");
738 }
739 
740 void SystemZAsmPrinter::emitMachineConstantPoolValue(
741     MachineConstantPoolValue *MCPV) {
742   auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
743 
744   const MCExpr *Expr =
745     MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
746                             getModifierVariantKind(ZCPV->getModifier()),
747                             OutContext);
748   uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
749 
750   OutStreamer->emitValue(Expr, Size);
751 }
752 
753 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
754                                         const char *ExtraCode,
755                                         raw_ostream &OS) {
756   const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
757   const MachineOperand &MO = MI->getOperand(OpNo);
758   MCOperand MCOp;
759   if (ExtraCode) {
760     if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
761         SystemZ::GR128BitRegClass.contains(MO.getReg()))
762       MCOp =
763           MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
764     else
765       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
766   } else {
767     SystemZMCInstLower Lower(MF->getContext(), *this);
768     MCOp = Lower.lowerOperand(MO);
769   }
770   SystemZInstPrinter::printOperand(MCOp, MAI, OS);
771   return false;
772 }
773 
774 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
775                                               unsigned OpNo,
776                                               const char *ExtraCode,
777                                               raw_ostream &OS) {
778   SystemZInstPrinter::
779     printAddress(MAI, MI->getOperand(OpNo).getReg(),
780                  MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),
781                  MI->getOperand(OpNo + 2).getReg(), OS);
782   return false;
783 }
784 
785 void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
786   emitStackMaps(SM);
787 }
788 
789 void SystemZAsmPrinter::emitFunctionEntryLabel() {
790   const SystemZSubtarget &Subtarget =
791       static_cast<const SystemZSubtarget &>(MF->getSubtarget());
792 
793   if (Subtarget.getTargetTriple().isOSzOS()) {
794     MCContext &OutContext = OutStreamer->getContext();
795     MCSymbol *EPMarkerSym = OutContext.createTempSymbol("CM_", true);
796 
797     // EntryPoint Marker
798     const MachineFrameInfo &MFFrame = MF->getFrameInfo();
799     bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
800 
801     // Set Flags
802     uint8_t Flags = 0;
803     if (IsUsingAlloca)
804       Flags |= 0x04;
805 
806     uint32_t DSASize = MFFrame.getStackSize();
807 
808     // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
809     uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
810     DSAAndFlags |= Flags;
811 
812     // Emit entry point marker section.
813     OutStreamer->AddComment("XPLINK Routine Layout Entry");
814     OutStreamer->emitLabel(EPMarkerSym);
815     OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
816     OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
817     OutStreamer->AddComment("Mark Type C'1'");
818     OutStreamer->emitInt8(0xF1); // Mark Type.
819     if (OutStreamer->isVerboseAsm()) {
820       OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
821       OutStreamer->AddComment("Entry Flags");
822       if (Flags & 0x04)
823         OutStreamer->AddComment("  Bit 2: 1 = Uses alloca");
824       else
825         OutStreamer->AddComment("  Bit 2: 0 = Does not use alloca");
826     }
827     OutStreamer->emitInt32(DSAAndFlags);
828   }
829 
830   AsmPrinter::emitFunctionEntryLabel();
831 }
832 
833 // Force static initialization.
834 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
835   RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
836 }
837