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->memoperands_empty())
92     return;
93 
94   Align Alignment = Align(16);
95   for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(),
96          EE = MI->memoperands_end(); MMOI != EE; ++MMOI)
97     if ((*MMOI)->getAlign() < Alignment)
98       Alignment = (*MMOI)->getAlign();
99 
100   unsigned AlignmentHint = 0;
101   if (Alignment >= Align(16))
102     AlignmentHint = 4;
103   else if (Alignment >= Align(8))
104     AlignmentHint = 3;
105   if (AlignmentHint == 0)
106     return;
107 
108   LoweredMI.setOpcode(Opcode);
109   LoweredMI.addOperand(MCOperand::createImm(AlignmentHint));
110 }
111 
112 // MI loads the high part of a vector from memory.  Return an instruction
113 // that uses replicating vector load Opcode to do the same thing.
114 static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
115   return MCInstBuilder(Opcode)
116     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
117     .addReg(MI->getOperand(1).getReg())
118     .addImm(MI->getOperand(2).getImm())
119     .addReg(MI->getOperand(3).getReg());
120 }
121 
122 // MI stores the high part of a vector to memory.  Return an instruction
123 // that uses elemental vector store Opcode to do the same thing.
124 static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
125   return MCInstBuilder(Opcode)
126     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
127     .addReg(MI->getOperand(1).getReg())
128     .addImm(MI->getOperand(2).getImm())
129     .addReg(MI->getOperand(3).getReg())
130     .addImm(0);
131 }
132 
133 // The XPLINK ABI requires that a no-op encoding the call type is emitted after
134 // each call to a subroutine. This information can be used by the called
135 // function to determine its entry point, e.g. for generating a backtrace. The
136 // call type is encoded as a register number in the bcr instruction. See
137 // enumeration CallType for the possible values.
138 void SystemZAsmPrinter::emitCallInformation(CallType CT) {
139   EmitToStreamer(*OutStreamer,
140                  MCInstBuilder(SystemZ::BCRAsm)
141                      .addImm(0)
142                      .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
143 }
144 
145 void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
146   SystemZMCInstLower Lower(MF->getContext(), *this);
147   MCInst LoweredMI;
148   switch (MI->getOpcode()) {
149   case SystemZ::Return:
150     LoweredMI = MCInstBuilder(SystemZ::BR)
151       .addReg(SystemZ::R14D);
152     break;
153 
154   case SystemZ::Return_XPLINK:
155     LoweredMI = MCInstBuilder(SystemZ::B)
156       .addReg(SystemZ::R7D)
157       .addImm(2)
158       .addReg(0);
159     break;
160 
161   case SystemZ::CondReturn:
162     LoweredMI = MCInstBuilder(SystemZ::BCR)
163       .addImm(MI->getOperand(0).getImm())
164       .addImm(MI->getOperand(1).getImm())
165       .addReg(SystemZ::R14D);
166     break;
167 
168   case SystemZ::CondReturn_XPLINK:
169     LoweredMI = MCInstBuilder(SystemZ::BC)
170       .addImm(MI->getOperand(0).getImm())
171       .addImm(MI->getOperand(1).getImm())
172       .addReg(SystemZ::R7D)
173       .addImm(2)
174       .addReg(0);
175     break;
176 
177   case SystemZ::CRBReturn:
178     LoweredMI = MCInstBuilder(SystemZ::CRB)
179       .addReg(MI->getOperand(0).getReg())
180       .addReg(MI->getOperand(1).getReg())
181       .addImm(MI->getOperand(2).getImm())
182       .addReg(SystemZ::R14D)
183       .addImm(0);
184     break;
185 
186   case SystemZ::CGRBReturn:
187     LoweredMI = MCInstBuilder(SystemZ::CGRB)
188       .addReg(MI->getOperand(0).getReg())
189       .addReg(MI->getOperand(1).getReg())
190       .addImm(MI->getOperand(2).getImm())
191       .addReg(SystemZ::R14D)
192       .addImm(0);
193     break;
194 
195   case SystemZ::CIBReturn:
196     LoweredMI = MCInstBuilder(SystemZ::CIB)
197       .addReg(MI->getOperand(0).getReg())
198       .addImm(MI->getOperand(1).getImm())
199       .addImm(MI->getOperand(2).getImm())
200       .addReg(SystemZ::R14D)
201       .addImm(0);
202     break;
203 
204   case SystemZ::CGIBReturn:
205     LoweredMI = MCInstBuilder(SystemZ::CGIB)
206       .addReg(MI->getOperand(0).getReg())
207       .addImm(MI->getOperand(1).getImm())
208       .addImm(MI->getOperand(2).getImm())
209       .addReg(SystemZ::R14D)
210       .addImm(0);
211     break;
212 
213   case SystemZ::CLRBReturn:
214     LoweredMI = MCInstBuilder(SystemZ::CLRB)
215       .addReg(MI->getOperand(0).getReg())
216       .addReg(MI->getOperand(1).getReg())
217       .addImm(MI->getOperand(2).getImm())
218       .addReg(SystemZ::R14D)
219       .addImm(0);
220     break;
221 
222   case SystemZ::CLGRBReturn:
223     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
224       .addReg(MI->getOperand(0).getReg())
225       .addReg(MI->getOperand(1).getReg())
226       .addImm(MI->getOperand(2).getImm())
227       .addReg(SystemZ::R14D)
228       .addImm(0);
229     break;
230 
231   case SystemZ::CLIBReturn:
232     LoweredMI = MCInstBuilder(SystemZ::CLIB)
233       .addReg(MI->getOperand(0).getReg())
234       .addImm(MI->getOperand(1).getImm())
235       .addImm(MI->getOperand(2).getImm())
236       .addReg(SystemZ::R14D)
237       .addImm(0);
238     break;
239 
240   case SystemZ::CLGIBReturn:
241     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
242       .addReg(MI->getOperand(0).getReg())
243       .addImm(MI->getOperand(1).getImm())
244       .addImm(MI->getOperand(2).getImm())
245       .addReg(SystemZ::R14D)
246       .addImm(0);
247     break;
248 
249   case SystemZ::CallBRASL_XPLINK64:
250     EmitToStreamer(*OutStreamer,
251                    MCInstBuilder(SystemZ::BRASL)
252                        .addReg(SystemZ::R7D)
253                        .addExpr(Lower.getExpr(MI->getOperand(0),
254                                               MCSymbolRefExpr::VK_PLT)));
255     emitCallInformation(CallType::BRASL7);
256     return;
257 
258   case SystemZ::CallBASR_XPLINK64:
259     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
260                                      .addReg(SystemZ::R7D)
261                                      .addReg(MI->getOperand(0).getReg()));
262     emitCallInformation(CallType::BASR76);
263     return;
264 
265   case SystemZ::CallBRASL:
266     LoweredMI = MCInstBuilder(SystemZ::BRASL)
267       .addReg(SystemZ::R14D)
268       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
269     break;
270 
271   case SystemZ::CallBASR:
272     LoweredMI = MCInstBuilder(SystemZ::BASR)
273       .addReg(SystemZ::R14D)
274       .addReg(MI->getOperand(0).getReg());
275     break;
276 
277   case SystemZ::CallJG:
278     LoweredMI = MCInstBuilder(SystemZ::JG)
279       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
280     break;
281 
282   case SystemZ::CallBRCL:
283     LoweredMI = MCInstBuilder(SystemZ::BRCL)
284       .addImm(MI->getOperand(0).getImm())
285       .addImm(MI->getOperand(1).getImm())
286       .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT));
287     break;
288 
289   case SystemZ::CallBR:
290     LoweredMI = MCInstBuilder(SystemZ::BR)
291       .addReg(MI->getOperand(0).getReg());
292     break;
293 
294   case SystemZ::CallBCR:
295     LoweredMI = MCInstBuilder(SystemZ::BCR)
296       .addImm(MI->getOperand(0).getImm())
297       .addImm(MI->getOperand(1).getImm())
298       .addReg(MI->getOperand(2).getReg());
299     break;
300 
301   case SystemZ::CRBCall:
302     LoweredMI = MCInstBuilder(SystemZ::CRB)
303       .addReg(MI->getOperand(0).getReg())
304       .addReg(MI->getOperand(1).getReg())
305       .addImm(MI->getOperand(2).getImm())
306       .addReg(MI->getOperand(3).getReg())
307       .addImm(0);
308     break;
309 
310   case SystemZ::CGRBCall:
311     LoweredMI = MCInstBuilder(SystemZ::CGRB)
312       .addReg(MI->getOperand(0).getReg())
313       .addReg(MI->getOperand(1).getReg())
314       .addImm(MI->getOperand(2).getImm())
315       .addReg(MI->getOperand(3).getReg())
316       .addImm(0);
317     break;
318 
319   case SystemZ::CIBCall:
320     LoweredMI = MCInstBuilder(SystemZ::CIB)
321       .addReg(MI->getOperand(0).getReg())
322       .addImm(MI->getOperand(1).getImm())
323       .addImm(MI->getOperand(2).getImm())
324       .addReg(MI->getOperand(3).getReg())
325       .addImm(0);
326     break;
327 
328   case SystemZ::CGIBCall:
329     LoweredMI = MCInstBuilder(SystemZ::CGIB)
330       .addReg(MI->getOperand(0).getReg())
331       .addImm(MI->getOperand(1).getImm())
332       .addImm(MI->getOperand(2).getImm())
333       .addReg(MI->getOperand(3).getReg())
334       .addImm(0);
335     break;
336 
337   case SystemZ::CLRBCall:
338     LoweredMI = MCInstBuilder(SystemZ::CLRB)
339       .addReg(MI->getOperand(0).getReg())
340       .addReg(MI->getOperand(1).getReg())
341       .addImm(MI->getOperand(2).getImm())
342       .addReg(MI->getOperand(3).getReg())
343       .addImm(0);
344     break;
345 
346   case SystemZ::CLGRBCall:
347     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
348       .addReg(MI->getOperand(0).getReg())
349       .addReg(MI->getOperand(1).getReg())
350       .addImm(MI->getOperand(2).getImm())
351       .addReg(MI->getOperand(3).getReg())
352       .addImm(0);
353     break;
354 
355   case SystemZ::CLIBCall:
356     LoweredMI = MCInstBuilder(SystemZ::CLIB)
357       .addReg(MI->getOperand(0).getReg())
358       .addImm(MI->getOperand(1).getImm())
359       .addImm(MI->getOperand(2).getImm())
360       .addReg(MI->getOperand(3).getReg())
361       .addImm(0);
362     break;
363 
364   case SystemZ::CLGIBCall:
365     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
366       .addReg(MI->getOperand(0).getReg())
367       .addImm(MI->getOperand(1).getImm())
368       .addImm(MI->getOperand(2).getImm())
369       .addReg(MI->getOperand(3).getReg())
370       .addImm(0);
371     break;
372 
373   case SystemZ::TLS_GDCALL:
374     LoweredMI = MCInstBuilder(SystemZ::BRASL)
375       .addReg(SystemZ::R14D)
376       .addExpr(getTLSGetOffset(MF->getContext()))
377       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
378     break;
379 
380   case SystemZ::TLS_LDCALL:
381     LoweredMI = MCInstBuilder(SystemZ::BRASL)
382       .addReg(SystemZ::R14D)
383       .addExpr(getTLSGetOffset(MF->getContext()))
384       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
385     break;
386 
387   case SystemZ::GOT:
388     LoweredMI = MCInstBuilder(SystemZ::LARL)
389       .addReg(MI->getOperand(0).getReg())
390       .addExpr(getGlobalOffsetTable(MF->getContext()));
391     break;
392 
393   case SystemZ::IILF64:
394     LoweredMI = MCInstBuilder(SystemZ::IILF)
395       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
396       .addImm(MI->getOperand(2).getImm());
397     break;
398 
399   case SystemZ::IIHF64:
400     LoweredMI = MCInstBuilder(SystemZ::IIHF)
401       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
402       .addImm(MI->getOperand(2).getImm());
403     break;
404 
405   case SystemZ::RISBHH:
406   case SystemZ::RISBHL:
407     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
408     break;
409 
410   case SystemZ::RISBLH:
411   case SystemZ::RISBLL:
412     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
413     break;
414 
415   case SystemZ::VLVGP32:
416     LoweredMI = MCInstBuilder(SystemZ::VLVGP)
417       .addReg(MI->getOperand(0).getReg())
418       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))
419       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));
420     break;
421 
422   case SystemZ::VLR32:
423   case SystemZ::VLR64:
424     LoweredMI = MCInstBuilder(SystemZ::VLR)
425       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
426       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));
427     break;
428 
429   case SystemZ::VL:
430     Lower.lower(MI, LoweredMI);
431     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);
432     break;
433 
434   case SystemZ::VST:
435     Lower.lower(MI, LoweredMI);
436     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);
437     break;
438 
439   case SystemZ::VLM:
440     Lower.lower(MI, LoweredMI);
441     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);
442     break;
443 
444   case SystemZ::VSTM:
445     Lower.lower(MI, LoweredMI);
446     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign);
447     break;
448 
449   case SystemZ::VL32:
450     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);
451     break;
452 
453   case SystemZ::VL64:
454     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);
455     break;
456 
457   case SystemZ::VST32:
458     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);
459     break;
460 
461   case SystemZ::VST64:
462     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);
463     break;
464 
465   case SystemZ::LFER:
466     LoweredMI = MCInstBuilder(SystemZ::VLGVF)
467       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))
468       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))
469       .addReg(0).addImm(0);
470     break;
471 
472   case SystemZ::LEFR:
473     LoweredMI = MCInstBuilder(SystemZ::VLVGF)
474       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
475       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
476       .addReg(MI->getOperand(1).getReg())
477       .addReg(0).addImm(0);
478     break;
479 
480 #define LOWER_LOW(NAME)                                                 \
481   case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
482 
483   LOWER_LOW(IILL);
484   LOWER_LOW(IILH);
485   LOWER_LOW(TMLL);
486   LOWER_LOW(TMLH);
487   LOWER_LOW(NILL);
488   LOWER_LOW(NILH);
489   LOWER_LOW(NILF);
490   LOWER_LOW(OILL);
491   LOWER_LOW(OILH);
492   LOWER_LOW(OILF);
493   LOWER_LOW(XILF);
494 
495 #undef LOWER_LOW
496 
497 #define LOWER_HIGH(NAME) \
498   case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
499 
500   LOWER_HIGH(IIHL);
501   LOWER_HIGH(IIHH);
502   LOWER_HIGH(TMHL);
503   LOWER_HIGH(TMHH);
504   LOWER_HIGH(NIHL);
505   LOWER_HIGH(NIHH);
506   LOWER_HIGH(NIHF);
507   LOWER_HIGH(OIHL);
508   LOWER_HIGH(OIHH);
509   LOWER_HIGH(OIHF);
510   LOWER_HIGH(XIHF);
511 
512 #undef LOWER_HIGH
513 
514   case SystemZ::Serialize:
515     if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
516       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
517         .addImm(14).addReg(SystemZ::R0D);
518     else
519       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
520         .addImm(15).addReg(SystemZ::R0D);
521     break;
522 
523   // Emit nothing here but a comment if we can.
524   case SystemZ::MemBarrier:
525     OutStreamer->emitRawComment("MEMBARRIER");
526     return;
527 
528   // We want to emit "j .+2" for traps, jumping to the relative immediate field
529   // of the jump instruction, which is an illegal instruction. We cannot emit a
530   // "." symbol, so create and emit a temp label before the instruction and use
531   // that instead.
532   case SystemZ::Trap: {
533     MCSymbol *DotSym = OutContext.createTempSymbol();
534     OutStreamer->emitLabel(DotSym);
535 
536     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
537     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
538     LoweredMI = MCInstBuilder(SystemZ::J)
539       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
540     }
541     break;
542 
543   // Conditional traps will create a branch on condition instruction that jumps
544   // to the relative immediate field of the jump instruction. (eg. "jo .+2")
545   case SystemZ::CondTrap: {
546     MCSymbol *DotSym = OutContext.createTempSymbol();
547     OutStreamer->emitLabel(DotSym);
548 
549     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
550     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
551     LoweredMI = MCInstBuilder(SystemZ::BRC)
552       .addImm(MI->getOperand(0).getImm())
553       .addImm(MI->getOperand(1).getImm())
554       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
555     }
556     break;
557 
558   case TargetOpcode::FENTRY_CALL:
559     LowerFENTRY_CALL(*MI, Lower);
560     return;
561 
562   case TargetOpcode::STACKMAP:
563     LowerSTACKMAP(*MI);
564     return;
565 
566   case TargetOpcode::PATCHPOINT:
567     LowerPATCHPOINT(*MI, Lower);
568     return;
569 
570   case SystemZ::EXRL_Pseudo: {
571     unsigned TargetInsOpc = MI->getOperand(0).getImm();
572     Register LenMinus1Reg = MI->getOperand(1).getReg();
573     Register DestReg = MI->getOperand(2).getReg();
574     int64_t DestDisp = MI->getOperand(3).getImm();
575     Register SrcReg = MI->getOperand(4).getReg();
576     int64_t SrcDisp = MI->getOperand(5).getImm();
577 
578     SystemZTargetStreamer *TS = getTargetStreamer();
579     MCSymbol *DotSym = nullptr;
580     MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
581       .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
582     SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
583     SystemZTargetStreamer::EXRLT2SymMap::iterator I =
584         TS->EXRLTargets2Sym.find(ET_STI);
585     if (I != TS->EXRLTargets2Sym.end())
586       DotSym = I->second;
587     else
588       TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
589     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
590     EmitToStreamer(
591         *OutStreamer,
592         MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
593     return;
594   }
595 
596   default:
597     Lower.lower(MI, LoweredMI);
598     break;
599   }
600   EmitToStreamer(*OutStreamer, LoweredMI);
601 }
602 
603 // Emit the largest nop instruction smaller than or equal to NumBytes
604 // bytes.  Return the size of nop emitted.
605 static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
606                         unsigned NumBytes, const MCSubtargetInfo &STI) {
607   if (NumBytes < 2) {
608     llvm_unreachable("Zero nops?");
609     return 0;
610   }
611   else if (NumBytes < 4) {
612     OutStreamer.emitInstruction(
613         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
614     return 2;
615   }
616   else if (NumBytes < 6) {
617     OutStreamer.emitInstruction(
618         MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
619         STI);
620     return 4;
621   }
622   else {
623     MCSymbol *DotSym = OutContext.createTempSymbol();
624     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
625     OutStreamer.emitLabel(DotSym);
626     OutStreamer.emitInstruction(
627         MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
628     return 6;
629   }
630 }
631 
632 void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
633                                          SystemZMCInstLower &Lower) {
634   MCContext &Ctx = MF->getContext();
635   if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
636     MCSymbol *DotSym = OutContext.createTempSymbol();
637     OutStreamer->PushSection();
638     OutStreamer->SwitchSection(
639         Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
640     OutStreamer->emitSymbolValue(DotSym, 8);
641     OutStreamer->PopSection();
642     OutStreamer->emitLabel(DotSym);
643   }
644 
645   if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
646     EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
647     return;
648   }
649 
650   MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
651   const MCSymbolRefExpr *Op =
652       MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
653   OutStreamer->emitInstruction(
654       MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
655       getSubtargetInfo());
656 }
657 
658 void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
659   const SystemZInstrInfo *TII =
660     static_cast<const SystemZInstrInfo *>(MF->getSubtarget().getInstrInfo());
661 
662   unsigned NumNOPBytes = MI.getOperand(1).getImm();
663 
664   auto &Ctx = OutStreamer->getContext();
665   MCSymbol *MILabel = Ctx.createTempSymbol();
666   OutStreamer->emitLabel(MILabel);
667 
668   SM.recordStackMap(*MILabel, MI);
669   assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
670 
671   // Scan ahead to trim the shadow.
672   unsigned ShadowBytes = 0;
673   const MachineBasicBlock &MBB = *MI.getParent();
674   MachineBasicBlock::const_iterator MII(MI);
675   ++MII;
676   while (ShadowBytes < NumNOPBytes) {
677     if (MII == MBB.end() ||
678         MII->getOpcode() == TargetOpcode::PATCHPOINT ||
679         MII->getOpcode() == TargetOpcode::STACKMAP)
680       break;
681     ShadowBytes += TII->getInstSizeInBytes(*MII);
682     if (MII->isCall())
683       break;
684     ++MII;
685   }
686 
687   // Emit nops.
688   while (ShadowBytes < NumNOPBytes)
689     ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
690                            getSubtargetInfo());
691 }
692 
693 // Lower a patchpoint of the form:
694 // [<def>], <id>, <numBytes>, <target>, <numArgs>
695 void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
696                                         SystemZMCInstLower &Lower) {
697   auto &Ctx = OutStreamer->getContext();
698   MCSymbol *MILabel = Ctx.createTempSymbol();
699   OutStreamer->emitLabel(MILabel);
700 
701   SM.recordPatchPoint(*MILabel, MI);
702   PatchPointOpers Opers(&MI);
703 
704   unsigned EncodedBytes = 0;
705   const MachineOperand &CalleeMO = Opers.getCallTarget();
706 
707   if (CalleeMO.isImm()) {
708     uint64_t CallTarget = CalleeMO.getImm();
709     if (CallTarget) {
710       unsigned ScratchIdx = -1;
711       unsigned ScratchReg = 0;
712       do {
713         ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
714         ScratchReg = MI.getOperand(ScratchIdx).getReg();
715       } while (ScratchReg == SystemZ::R0D);
716 
717       // Materialize the call target address
718       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
719                                       .addReg(ScratchReg)
720                                       .addImm(CallTarget & 0xFFFFFFFF));
721       EncodedBytes += 6;
722       if (CallTarget >> 32) {
723         EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
724                                         .addReg(ScratchReg)
725                                         .addImm(CallTarget >> 32));
726         EncodedBytes += 6;
727       }
728 
729       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
730                                      .addReg(SystemZ::R14D)
731                                      .addReg(ScratchReg));
732       EncodedBytes += 2;
733     }
734   } else if (CalleeMO.isGlobal()) {
735     const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT);
736     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
737                                    .addReg(SystemZ::R14D)
738                                    .addExpr(Expr));
739     EncodedBytes += 6;
740   }
741 
742   // Emit padding.
743   unsigned NumBytes = Opers.getNumPatchBytes();
744   assert(NumBytes >= EncodedBytes &&
745          "Patchpoint can't request size less than the length of a call.");
746   assert((NumBytes - EncodedBytes) % 2 == 0 &&
747          "Invalid number of NOP bytes requested!");
748   while (EncodedBytes < NumBytes)
749     EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
750                             getSubtargetInfo());
751 }
752 
753 // Convert a SystemZ-specific constant pool modifier into the associated
754 // MCSymbolRefExpr variant kind.
755 static MCSymbolRefExpr::VariantKind
756 getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
757   switch (Modifier) {
758   case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
759   case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
760   case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
761   case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
762   }
763   llvm_unreachable("Invalid SystemCPModifier!");
764 }
765 
766 void SystemZAsmPrinter::emitMachineConstantPoolValue(
767     MachineConstantPoolValue *MCPV) {
768   auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
769 
770   const MCExpr *Expr =
771     MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
772                             getModifierVariantKind(ZCPV->getModifier()),
773                             OutContext);
774   uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
775 
776   OutStreamer->emitValue(Expr, Size);
777 }
778 
779 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
780                                         const char *ExtraCode,
781                                         raw_ostream &OS) {
782   const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
783   const MachineOperand &MO = MI->getOperand(OpNo);
784   MCOperand MCOp;
785   if (ExtraCode) {
786     if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
787         SystemZ::GR128BitRegClass.contains(MO.getReg()))
788       MCOp =
789           MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
790     else
791       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
792   } else {
793     SystemZMCInstLower Lower(MF->getContext(), *this);
794     MCOp = Lower.lowerOperand(MO);
795   }
796   SystemZInstPrinter::printOperand(MCOp, MAI, OS);
797   return false;
798 }
799 
800 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
801                                               unsigned OpNo,
802                                               const char *ExtraCode,
803                                               raw_ostream &OS) {
804   SystemZInstPrinter::
805     printAddress(MAI, MI->getOperand(OpNo).getReg(),
806                  MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),
807                  MI->getOperand(OpNo + 2).getReg(), OS);
808   return false;
809 }
810 
811 void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
812   emitStackMaps(SM);
813 }
814 
815 void SystemZAsmPrinter::emitFunctionEntryLabel() {
816   const SystemZSubtarget &Subtarget =
817       static_cast<const SystemZSubtarget &>(MF->getSubtarget());
818 
819   if (Subtarget.getTargetTriple().isOSzOS()) {
820     MCContext &OutContext = OutStreamer->getContext();
821     MCSymbol *EPMarkerSym = OutContext.createTempSymbol("CM_", true);
822 
823     // EntryPoint Marker
824     const MachineFrameInfo &MFFrame = MF->getFrameInfo();
825     bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
826 
827     // Set Flags
828     uint8_t Flags = 0;
829     if (IsUsingAlloca)
830       Flags |= 0x04;
831 
832     uint32_t DSASize = MFFrame.getStackSize();
833 
834     // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
835     uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
836     DSAAndFlags |= Flags;
837 
838     // Emit entry point marker section.
839     OutStreamer->AddComment("XPLINK Routine Layout Entry");
840     OutStreamer->emitLabel(EPMarkerSym);
841     OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
842     OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
843     OutStreamer->AddComment("Mark Type C'1'");
844     OutStreamer->emitInt8(0xF1); // Mark Type.
845     if (OutStreamer->isVerboseAsm()) {
846       OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
847       OutStreamer->AddComment("Entry Flags");
848       if (Flags & 0x04)
849         OutStreamer->AddComment("  Bit 2: 1 = Uses alloca");
850       else
851         OutStreamer->AddComment("  Bit 2: 0 = Does not use alloca");
852     }
853     OutStreamer->emitInt32(DSAAndFlags);
854   }
855 
856   AsmPrinter::emitFunctionEntryLabel();
857 }
858 
859 // Force static initialization.
860 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
861   RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
862 }
863