1251607Sdim//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
2251607Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6251607Sdim//
7251607Sdim//===----------------------------------------------------------------------===//
8251607Sdim//
9251607Sdim// Streams SystemZ assembly language and associated data, in the form of
10251607Sdim// MCInsts and MCExprs respectively.
11251607Sdim//
12251607Sdim//===----------------------------------------------------------------------===//
13251607Sdim
14251607Sdim#include "SystemZAsmPrinter.h"
15353358Sdim#include "MCTargetDesc/SystemZInstPrinter.h"
16251607Sdim#include "SystemZConstantPoolValue.h"
17251607Sdim#include "SystemZMCInstLower.h"
18353358Sdim#include "TargetInfo/SystemZTargetInfo.h"
19360784Sdim#include "llvm/BinaryFormat/ELF.h"
20251607Sdim#include "llvm/CodeGen/MachineModuleInfoImpls.h"
21251607Sdim#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
22276479Sdim#include "llvm/IR/Mangler.h"
23251607Sdim#include "llvm/MC/MCExpr.h"
24261991Sdim#include "llvm/MC/MCInstBuilder.h"
25360784Sdim#include "llvm/MC/MCSectionELF.h"
26251607Sdim#include "llvm/MC/MCStreamer.h"
27251607Sdim#include "llvm/Support/TargetRegistry.h"
28251607Sdim
29251607Sdimusing namespace llvm;
30251607Sdim
31261991Sdim// Return an RI instruction like MI with opcode Opcode, but with the
32261991Sdim// GR64 register operands turned into GR32s.
33261991Sdimstatic MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
34261991Sdim  if (MI->isCompare())
35261991Sdim    return MCInstBuilder(Opcode)
36261991Sdim      .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
37261991Sdim      .addImm(MI->getOperand(1).getImm());
38261991Sdim  else
39261991Sdim    return MCInstBuilder(Opcode)
40261991Sdim      .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
41261991Sdim      .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
42261991Sdim      .addImm(MI->getOperand(2).getImm());
43261991Sdim}
44261991Sdim
45261991Sdim// Return an RI instruction like MI with opcode Opcode, but with the
46261991Sdim// GR64 register operands turned into GRH32s.
47261991Sdimstatic MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
48261991Sdim  if (MI->isCompare())
49261991Sdim    return MCInstBuilder(Opcode)
50261991Sdim      .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
51261991Sdim      .addImm(MI->getOperand(1).getImm());
52261991Sdim  else
53261991Sdim    return MCInstBuilder(Opcode)
54261991Sdim      .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
55261991Sdim      .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))
56261991Sdim      .addImm(MI->getOperand(2).getImm());
57261991Sdim}
58261991Sdim
59261991Sdim// Return an RI instruction like MI with opcode Opcode, but with the
60261991Sdim// R2 register turned into a GR64.
61261991Sdimstatic MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
62261991Sdim  return MCInstBuilder(Opcode)
63261991Sdim    .addReg(MI->getOperand(0).getReg())
64261991Sdim    .addReg(MI->getOperand(1).getReg())
65261991Sdim    .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
66261991Sdim    .addImm(MI->getOperand(3).getImm())
67261991Sdim    .addImm(MI->getOperand(4).getImm())
68261991Sdim    .addImm(MI->getOperand(5).getImm());
69261991Sdim}
70261991Sdim
71288943Sdimstatic const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
72288943Sdim  StringRef Name = "__tls_get_offset";
73288943Sdim  return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
74288943Sdim                                 MCSymbolRefExpr::VK_PLT,
75288943Sdim                                 Context);
76288943Sdim}
77288943Sdim
78288943Sdimstatic const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
79288943Sdim  StringRef Name = "_GLOBAL_OFFSET_TABLE_";
80288943Sdim  return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
81288943Sdim                                 MCSymbolRefExpr::VK_None,
82288943Sdim                                 Context);
83288943Sdim}
84288943Sdim
85353358Sdim// MI is an instruction that accepts an optional alignment hint,
86353358Sdim// and which was already lowered to LoweredMI.  If the alignment
87353358Sdim// of the original memory operand is known, update LoweredMI to
88353358Sdim// an instruction with the corresponding hint set.
89353358Sdimstatic void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI,
90353358Sdim                               unsigned Opcode) {
91353358Sdim  if (!MI->hasOneMemOperand())
92353358Sdim    return;
93353358Sdim  const MachineMemOperand *MMO = *MI->memoperands_begin();
94353358Sdim  unsigned AlignmentHint = 0;
95353358Sdim  if (MMO->getAlignment() >= 16)
96353358Sdim    AlignmentHint = 4;
97353358Sdim  else if (MMO->getAlignment() >= 8)
98353358Sdim    AlignmentHint = 3;
99353358Sdim  if (AlignmentHint == 0)
100353358Sdim    return;
101353358Sdim
102353358Sdim  LoweredMI.setOpcode(Opcode);
103353358Sdim  LoweredMI.addOperand(MCOperand::createImm(AlignmentHint));
104353358Sdim}
105353358Sdim
106288943Sdim// MI loads the high part of a vector from memory.  Return an instruction
107288943Sdim// that uses replicating vector load Opcode to do the same thing.
108288943Sdimstatic MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
109288943Sdim  return MCInstBuilder(Opcode)
110288943Sdim    .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
111288943Sdim    .addReg(MI->getOperand(1).getReg())
112288943Sdim    .addImm(MI->getOperand(2).getImm())
113288943Sdim    .addReg(MI->getOperand(3).getReg());
114288943Sdim}
115288943Sdim
116288943Sdim// MI stores the high part of a vector to memory.  Return an instruction
117288943Sdim// that uses elemental vector store Opcode to do the same thing.
118288943Sdimstatic MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
119288943Sdim  return MCInstBuilder(Opcode)
120288943Sdim    .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
121288943Sdim    .addReg(MI->getOperand(1).getReg())
122288943Sdim    .addImm(MI->getOperand(2).getImm())
123288943Sdim    .addReg(MI->getOperand(3).getReg())
124288943Sdim    .addImm(0);
125288943Sdim}
126288943Sdim
127251607Sdimvoid SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
128261991Sdim  SystemZMCInstLower Lower(MF->getContext(), *this);
129251607Sdim  MCInst LoweredMI;
130261991Sdim  switch (MI->getOpcode()) {
131261991Sdim  case SystemZ::Return:
132261991Sdim    LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
133261991Sdim    break;
134261991Sdim
135309124Sdim  case SystemZ::CondReturn:
136309124Sdim    LoweredMI = MCInstBuilder(SystemZ::BCR)
137309124Sdim      .addImm(MI->getOperand(0).getImm())
138309124Sdim      .addImm(MI->getOperand(1).getImm())
139309124Sdim      .addReg(SystemZ::R14D);
140309124Sdim    break;
141309124Sdim
142309124Sdim  case SystemZ::CRBReturn:
143309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CRB)
144309124Sdim      .addReg(MI->getOperand(0).getReg())
145309124Sdim      .addReg(MI->getOperand(1).getReg())
146309124Sdim      .addImm(MI->getOperand(2).getImm())
147309124Sdim      .addReg(SystemZ::R14D)
148309124Sdim      .addImm(0);
149309124Sdim    break;
150309124Sdim
151309124Sdim  case SystemZ::CGRBReturn:
152309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CGRB)
153309124Sdim      .addReg(MI->getOperand(0).getReg())
154309124Sdim      .addReg(MI->getOperand(1).getReg())
155309124Sdim      .addImm(MI->getOperand(2).getImm())
156309124Sdim      .addReg(SystemZ::R14D)
157309124Sdim      .addImm(0);
158309124Sdim    break;
159309124Sdim
160309124Sdim  case SystemZ::CIBReturn:
161309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CIB)
162309124Sdim      .addReg(MI->getOperand(0).getReg())
163309124Sdim      .addImm(MI->getOperand(1).getImm())
164309124Sdim      .addImm(MI->getOperand(2).getImm())
165309124Sdim      .addReg(SystemZ::R14D)
166309124Sdim      .addImm(0);
167309124Sdim    break;
168309124Sdim
169309124Sdim  case SystemZ::CGIBReturn:
170309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CGIB)
171309124Sdim      .addReg(MI->getOperand(0).getReg())
172309124Sdim      .addImm(MI->getOperand(1).getImm())
173309124Sdim      .addImm(MI->getOperand(2).getImm())
174309124Sdim      .addReg(SystemZ::R14D)
175309124Sdim      .addImm(0);
176309124Sdim    break;
177309124Sdim
178309124Sdim  case SystemZ::CLRBReturn:
179309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CLRB)
180309124Sdim      .addReg(MI->getOperand(0).getReg())
181309124Sdim      .addReg(MI->getOperand(1).getReg())
182309124Sdim      .addImm(MI->getOperand(2).getImm())
183309124Sdim      .addReg(SystemZ::R14D)
184309124Sdim      .addImm(0);
185309124Sdim    break;
186309124Sdim
187309124Sdim  case SystemZ::CLGRBReturn:
188309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CLGRB)
189309124Sdim      .addReg(MI->getOperand(0).getReg())
190309124Sdim      .addReg(MI->getOperand(1).getReg())
191309124Sdim      .addImm(MI->getOperand(2).getImm())
192309124Sdim      .addReg(SystemZ::R14D)
193309124Sdim      .addImm(0);
194309124Sdim    break;
195309124Sdim
196309124Sdim  case SystemZ::CLIBReturn:
197309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CLIB)
198309124Sdim      .addReg(MI->getOperand(0).getReg())
199309124Sdim      .addImm(MI->getOperand(1).getImm())
200309124Sdim      .addImm(MI->getOperand(2).getImm())
201309124Sdim      .addReg(SystemZ::R14D)
202309124Sdim      .addImm(0);
203309124Sdim    break;
204309124Sdim
205309124Sdim  case SystemZ::CLGIBReturn:
206309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CLGIB)
207309124Sdim      .addReg(MI->getOperand(0).getReg())
208309124Sdim      .addImm(MI->getOperand(1).getImm())
209309124Sdim      .addImm(MI->getOperand(2).getImm())
210309124Sdim      .addReg(SystemZ::R14D)
211309124Sdim      .addImm(0);
212309124Sdim    break;
213309124Sdim
214261991Sdim  case SystemZ::CallBRASL:
215261991Sdim    LoweredMI = MCInstBuilder(SystemZ::BRASL)
216261991Sdim      .addReg(SystemZ::R14D)
217261991Sdim      .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
218261991Sdim    break;
219261991Sdim
220261991Sdim  case SystemZ::CallBASR:
221261991Sdim    LoweredMI = MCInstBuilder(SystemZ::BASR)
222261991Sdim      .addReg(SystemZ::R14D)
223261991Sdim      .addReg(MI->getOperand(0).getReg());
224261991Sdim    break;
225261991Sdim
226261991Sdim  case SystemZ::CallJG:
227261991Sdim    LoweredMI = MCInstBuilder(SystemZ::JG)
228261991Sdim      .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
229261991Sdim    break;
230261991Sdim
231309124Sdim  case SystemZ::CallBRCL:
232309124Sdim    LoweredMI = MCInstBuilder(SystemZ::BRCL)
233309124Sdim      .addImm(MI->getOperand(0).getImm())
234309124Sdim      .addImm(MI->getOperand(1).getImm())
235309124Sdim      .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT));
236309124Sdim    break;
237309124Sdim
238261991Sdim  case SystemZ::CallBR:
239261991Sdim    LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R1D);
240261991Sdim    break;
241261991Sdim
242309124Sdim  case SystemZ::CallBCR:
243309124Sdim    LoweredMI = MCInstBuilder(SystemZ::BCR)
244309124Sdim      .addImm(MI->getOperand(0).getImm())
245309124Sdim      .addImm(MI->getOperand(1).getImm())
246309124Sdim      .addReg(SystemZ::R1D);
247309124Sdim    break;
248309124Sdim
249309124Sdim  case SystemZ::CRBCall:
250309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CRB)
251309124Sdim      .addReg(MI->getOperand(0).getReg())
252309124Sdim      .addReg(MI->getOperand(1).getReg())
253309124Sdim      .addImm(MI->getOperand(2).getImm())
254309124Sdim      .addReg(SystemZ::R1D)
255309124Sdim      .addImm(0);
256309124Sdim    break;
257309124Sdim
258309124Sdim  case SystemZ::CGRBCall:
259309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CGRB)
260309124Sdim      .addReg(MI->getOperand(0).getReg())
261309124Sdim      .addReg(MI->getOperand(1).getReg())
262309124Sdim      .addImm(MI->getOperand(2).getImm())
263309124Sdim      .addReg(SystemZ::R1D)
264309124Sdim      .addImm(0);
265309124Sdim    break;
266309124Sdim
267309124Sdim  case SystemZ::CIBCall:
268309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CIB)
269309124Sdim      .addReg(MI->getOperand(0).getReg())
270309124Sdim      .addImm(MI->getOperand(1).getImm())
271309124Sdim      .addImm(MI->getOperand(2).getImm())
272309124Sdim      .addReg(SystemZ::R1D)
273309124Sdim      .addImm(0);
274309124Sdim    break;
275309124Sdim
276309124Sdim  case SystemZ::CGIBCall:
277309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CGIB)
278309124Sdim      .addReg(MI->getOperand(0).getReg())
279309124Sdim      .addImm(MI->getOperand(1).getImm())
280309124Sdim      .addImm(MI->getOperand(2).getImm())
281309124Sdim      .addReg(SystemZ::R1D)
282309124Sdim      .addImm(0);
283309124Sdim    break;
284309124Sdim
285309124Sdim  case SystemZ::CLRBCall:
286309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CLRB)
287309124Sdim      .addReg(MI->getOperand(0).getReg())
288309124Sdim      .addReg(MI->getOperand(1).getReg())
289309124Sdim      .addImm(MI->getOperand(2).getImm())
290309124Sdim      .addReg(SystemZ::R1D)
291309124Sdim      .addImm(0);
292309124Sdim    break;
293309124Sdim
294309124Sdim  case SystemZ::CLGRBCall:
295309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CLGRB)
296309124Sdim      .addReg(MI->getOperand(0).getReg())
297309124Sdim      .addReg(MI->getOperand(1).getReg())
298309124Sdim      .addImm(MI->getOperand(2).getImm())
299309124Sdim      .addReg(SystemZ::R1D)
300309124Sdim      .addImm(0);
301309124Sdim    break;
302309124Sdim
303309124Sdim  case SystemZ::CLIBCall:
304309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CLIB)
305309124Sdim      .addReg(MI->getOperand(0).getReg())
306309124Sdim      .addImm(MI->getOperand(1).getImm())
307309124Sdim      .addImm(MI->getOperand(2).getImm())
308309124Sdim      .addReg(SystemZ::R1D)
309309124Sdim      .addImm(0);
310309124Sdim    break;
311309124Sdim
312309124Sdim  case SystemZ::CLGIBCall:
313309124Sdim    LoweredMI = MCInstBuilder(SystemZ::CLGIB)
314309124Sdim      .addReg(MI->getOperand(0).getReg())
315309124Sdim      .addImm(MI->getOperand(1).getImm())
316309124Sdim      .addImm(MI->getOperand(2).getImm())
317309124Sdim      .addReg(SystemZ::R1D)
318309124Sdim      .addImm(0);
319309124Sdim    break;
320309124Sdim
321288943Sdim  case SystemZ::TLS_GDCALL:
322288943Sdim    LoweredMI = MCInstBuilder(SystemZ::BRASL)
323288943Sdim      .addReg(SystemZ::R14D)
324288943Sdim      .addExpr(getTLSGetOffset(MF->getContext()))
325288943Sdim      .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
326288943Sdim    break;
327288943Sdim
328288943Sdim  case SystemZ::TLS_LDCALL:
329288943Sdim    LoweredMI = MCInstBuilder(SystemZ::BRASL)
330288943Sdim      .addReg(SystemZ::R14D)
331288943Sdim      .addExpr(getTLSGetOffset(MF->getContext()))
332288943Sdim      .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
333288943Sdim    break;
334288943Sdim
335288943Sdim  case SystemZ::GOT:
336288943Sdim    LoweredMI = MCInstBuilder(SystemZ::LARL)
337288943Sdim      .addReg(MI->getOperand(0).getReg())
338288943Sdim      .addExpr(getGlobalOffsetTable(MF->getContext()));
339288943Sdim    break;
340288943Sdim
341261991Sdim  case SystemZ::IILF64:
342261991Sdim    LoweredMI = MCInstBuilder(SystemZ::IILF)
343261991Sdim      .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
344261991Sdim      .addImm(MI->getOperand(2).getImm());
345261991Sdim    break;
346261991Sdim
347261991Sdim  case SystemZ::IIHF64:
348261991Sdim    LoweredMI = MCInstBuilder(SystemZ::IIHF)
349261991Sdim      .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
350261991Sdim      .addImm(MI->getOperand(2).getImm());
351261991Sdim    break;
352261991Sdim
353261991Sdim  case SystemZ::RISBHH:
354261991Sdim  case SystemZ::RISBHL:
355261991Sdim    LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
356261991Sdim    break;
357261991Sdim
358261991Sdim  case SystemZ::RISBLH:
359261991Sdim  case SystemZ::RISBLL:
360261991Sdim    LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
361261991Sdim    break;
362261991Sdim
363288943Sdim  case SystemZ::VLVGP32:
364288943Sdim    LoweredMI = MCInstBuilder(SystemZ::VLVGP)
365288943Sdim      .addReg(MI->getOperand(0).getReg())
366288943Sdim      .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))
367288943Sdim      .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));
368288943Sdim    break;
369288943Sdim
370288943Sdim  case SystemZ::VLR32:
371288943Sdim  case SystemZ::VLR64:
372288943Sdim    LoweredMI = MCInstBuilder(SystemZ::VLR)
373288943Sdim      .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
374288943Sdim      .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));
375288943Sdim    break;
376288943Sdim
377353358Sdim  case SystemZ::VL:
378353358Sdim    Lower.lower(MI, LoweredMI);
379353358Sdim    lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);
380353358Sdim    break;
381353358Sdim
382353358Sdim  case SystemZ::VST:
383353358Sdim    Lower.lower(MI, LoweredMI);
384353358Sdim    lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);
385353358Sdim    break;
386353358Sdim
387353358Sdim  case SystemZ::VLM:
388353358Sdim    Lower.lower(MI, LoweredMI);
389353358Sdim    lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);
390353358Sdim    break;
391353358Sdim
392353358Sdim  case SystemZ::VSTM:
393353358Sdim    Lower.lower(MI, LoweredMI);
394353358Sdim    lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign);
395353358Sdim    break;
396353358Sdim
397288943Sdim  case SystemZ::VL32:
398288943Sdim    LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);
399288943Sdim    break;
400288943Sdim
401288943Sdim  case SystemZ::VL64:
402288943Sdim    LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);
403288943Sdim    break;
404288943Sdim
405288943Sdim  case SystemZ::VST32:
406288943Sdim    LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);
407288943Sdim    break;
408288943Sdim
409288943Sdim  case SystemZ::VST64:
410288943Sdim    LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);
411288943Sdim    break;
412288943Sdim
413288943Sdim  case SystemZ::LFER:
414288943Sdim    LoweredMI = MCInstBuilder(SystemZ::VLGVF)
415288943Sdim      .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))
416288943Sdim      .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))
417288943Sdim      .addReg(0).addImm(0);
418288943Sdim    break;
419288943Sdim
420288943Sdim  case SystemZ::LEFR:
421288943Sdim    LoweredMI = MCInstBuilder(SystemZ::VLVGF)
422288943Sdim      .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
423288943Sdim      .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
424288943Sdim      .addReg(MI->getOperand(1).getReg())
425288943Sdim      .addReg(0).addImm(0);
426288943Sdim    break;
427288943Sdim
428261991Sdim#define LOWER_LOW(NAME)                                                 \
429261991Sdim  case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
430261991Sdim
431261991Sdim  LOWER_LOW(IILL);
432261991Sdim  LOWER_LOW(IILH);
433261991Sdim  LOWER_LOW(TMLL);
434261991Sdim  LOWER_LOW(TMLH);
435261991Sdim  LOWER_LOW(NILL);
436261991Sdim  LOWER_LOW(NILH);
437261991Sdim  LOWER_LOW(NILF);
438261991Sdim  LOWER_LOW(OILL);
439261991Sdim  LOWER_LOW(OILH);
440261991Sdim  LOWER_LOW(OILF);
441261991Sdim  LOWER_LOW(XILF);
442261991Sdim
443261991Sdim#undef LOWER_LOW
444261991Sdim
445261991Sdim#define LOWER_HIGH(NAME) \
446261991Sdim  case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
447261991Sdim
448261991Sdim  LOWER_HIGH(IIHL);
449261991Sdim  LOWER_HIGH(IIHH);
450261991Sdim  LOWER_HIGH(TMHL);
451261991Sdim  LOWER_HIGH(TMHH);
452261991Sdim  LOWER_HIGH(NIHL);
453261991Sdim  LOWER_HIGH(NIHH);
454261991Sdim  LOWER_HIGH(NIHF);
455261991Sdim  LOWER_HIGH(OIHL);
456261991Sdim  LOWER_HIGH(OIHH);
457261991Sdim  LOWER_HIGH(OIHF);
458261991Sdim  LOWER_HIGH(XIHF);
459261991Sdim
460261991Sdim#undef LOWER_HIGH
461261991Sdim
462276479Sdim  case SystemZ::Serialize:
463288943Sdim    if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
464314564Sdim      LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
465276479Sdim        .addImm(14).addReg(SystemZ::R0D);
466276479Sdim    else
467314564Sdim      LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
468276479Sdim        .addImm(15).addReg(SystemZ::R0D);
469276479Sdim    break;
470276479Sdim
471309124Sdim  // Emit nothing here but a comment if we can.
472309124Sdim  case SystemZ::MemBarrier:
473309124Sdim    OutStreamer->emitRawComment("MEMBARRIER");
474309124Sdim    return;
475309124Sdim
476309124Sdim  // We want to emit "j .+2" for traps, jumping to the relative immediate field
477309124Sdim  // of the jump instruction, which is an illegal instruction. We cannot emit a
478309124Sdim  // "." symbol, so create and emit a temp label before the instruction and use
479309124Sdim  // that instead.
480309124Sdim  case SystemZ::Trap: {
481309124Sdim    MCSymbol *DotSym = OutContext.createTempSymbol();
482309124Sdim    OutStreamer->EmitLabel(DotSym);
483309124Sdim
484309124Sdim    const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
485309124Sdim    const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
486309124Sdim    LoweredMI = MCInstBuilder(SystemZ::J)
487309124Sdim      .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
488309124Sdim    }
489309124Sdim    break;
490309124Sdim
491309124Sdim  // Conditional traps will create a branch on condition instruction that jumps
492309124Sdim  // to the relative immediate field of the jump instruction. (eg. "jo .+2")
493309124Sdim  case SystemZ::CondTrap: {
494309124Sdim    MCSymbol *DotSym = OutContext.createTempSymbol();
495309124Sdim    OutStreamer->EmitLabel(DotSym);
496309124Sdim
497309124Sdim    const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
498309124Sdim    const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
499309124Sdim    LoweredMI = MCInstBuilder(SystemZ::BRC)
500309124Sdim      .addImm(MI->getOperand(0).getImm())
501309124Sdim      .addImm(MI->getOperand(1).getImm())
502309124Sdim      .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
503309124Sdim    }
504309124Sdim    break;
505309124Sdim
506360784Sdim  case TargetOpcode::FENTRY_CALL:
507360784Sdim    LowerFENTRY_CALL(*MI, Lower);
508360784Sdim    return;
509360784Sdim
510341825Sdim  case TargetOpcode::STACKMAP:
511341825Sdim    LowerSTACKMAP(*MI);
512341825Sdim    return;
513341825Sdim
514341825Sdim  case TargetOpcode::PATCHPOINT:
515341825Sdim    LowerPATCHPOINT(*MI, Lower);
516341825Sdim    return;
517341825Sdim
518261991Sdim  default:
519261991Sdim    Lower.lower(MI, LoweredMI);
520261991Sdim    break;
521261991Sdim  }
522288943Sdim  EmitToStreamer(*OutStreamer, LoweredMI);
523251607Sdim}
524251607Sdim
525341825Sdim
526341825Sdim// Emit the largest nop instruction smaller than or equal to NumBytes
527341825Sdim// bytes.  Return the size of nop emitted.
528341825Sdimstatic unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
529341825Sdim                        unsigned NumBytes, const MCSubtargetInfo &STI) {
530341825Sdim  if (NumBytes < 2) {
531341825Sdim    llvm_unreachable("Zero nops?");
532341825Sdim    return 0;
533341825Sdim  }
534341825Sdim  else if (NumBytes < 4) {
535341825Sdim    OutStreamer.EmitInstruction(MCInstBuilder(SystemZ::BCRAsm)
536341825Sdim                                  .addImm(0).addReg(SystemZ::R0D), STI);
537341825Sdim    return 2;
538341825Sdim  }
539341825Sdim  else if (NumBytes < 6) {
540341825Sdim    OutStreamer.EmitInstruction(MCInstBuilder(SystemZ::BCAsm)
541341825Sdim                                  .addImm(0).addReg(0).addImm(0).addReg(0),
542341825Sdim                                STI);
543341825Sdim    return 4;
544341825Sdim  }
545341825Sdim  else {
546341825Sdim    MCSymbol *DotSym = OutContext.createTempSymbol();
547341825Sdim    const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
548360784Sdim    OutStreamer.EmitLabel(DotSym);
549341825Sdim    OutStreamer.EmitInstruction(MCInstBuilder(SystemZ::BRCLAsm)
550341825Sdim                                  .addImm(0).addExpr(Dot), STI);
551341825Sdim    return 6;
552341825Sdim  }
553341825Sdim}
554341825Sdim
555360784Sdimvoid SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
556360784Sdim                                         SystemZMCInstLower &Lower) {
557360784Sdim  MCContext &Ctx = MF->getContext();
558360784Sdim  if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
559360784Sdim    MCSymbol *DotSym = OutContext.createTempSymbol();
560360784Sdim    OutStreamer->PushSection();
561360784Sdim    OutStreamer->SwitchSection(
562360784Sdim        Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
563360784Sdim    OutStreamer->EmitSymbolValue(DotSym, 8);
564360784Sdim    OutStreamer->PopSection();
565360784Sdim    OutStreamer->EmitLabel(DotSym);
566360784Sdim  }
567360784Sdim
568360784Sdim  if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
569360784Sdim    EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
570360784Sdim    return;
571360784Sdim  }
572360784Sdim
573360784Sdim  MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
574360784Sdim  const MCSymbolRefExpr *Op =
575360784Sdim      MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
576360784Sdim  OutStreamer->EmitInstruction(MCInstBuilder(SystemZ::BRASL)
577360784Sdim                       .addReg(SystemZ::R0D).addExpr(Op), getSubtargetInfo());
578360784Sdim}
579360784Sdim
580341825Sdimvoid SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
581341825Sdim  const SystemZInstrInfo *TII =
582341825Sdim    static_cast<const SystemZInstrInfo *>(MF->getSubtarget().getInstrInfo());
583341825Sdim
584341825Sdim  unsigned NumNOPBytes = MI.getOperand(1).getImm();
585341825Sdim
586360784Sdim  auto &Ctx = OutStreamer->getContext();
587360784Sdim  MCSymbol *MILabel = Ctx.createTempSymbol();
588360784Sdim  OutStreamer->EmitLabel(MILabel);
589360784Sdim
590360784Sdim  SM.recordStackMap(*MILabel, MI);
591341825Sdim  assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
592341825Sdim
593341825Sdim  // Scan ahead to trim the shadow.
594341825Sdim  unsigned ShadowBytes = 0;
595341825Sdim  const MachineBasicBlock &MBB = *MI.getParent();
596341825Sdim  MachineBasicBlock::const_iterator MII(MI);
597341825Sdim  ++MII;
598341825Sdim  while (ShadowBytes < NumNOPBytes) {
599341825Sdim    if (MII == MBB.end() ||
600341825Sdim        MII->getOpcode() == TargetOpcode::PATCHPOINT ||
601341825Sdim        MII->getOpcode() == TargetOpcode::STACKMAP)
602341825Sdim      break;
603341825Sdim    ShadowBytes += TII->getInstSizeInBytes(*MII);
604341825Sdim    if (MII->isCall())
605341825Sdim      break;
606341825Sdim    ++MII;
607341825Sdim  }
608341825Sdim
609341825Sdim  // Emit nops.
610341825Sdim  while (ShadowBytes < NumNOPBytes)
611341825Sdim    ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
612341825Sdim                           getSubtargetInfo());
613341825Sdim}
614341825Sdim
615341825Sdim// Lower a patchpoint of the form:
616341825Sdim// [<def>], <id>, <numBytes>, <target>, <numArgs>
617341825Sdimvoid SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
618341825Sdim                                        SystemZMCInstLower &Lower) {
619360784Sdim  auto &Ctx = OutStreamer->getContext();
620360784Sdim  MCSymbol *MILabel = Ctx.createTempSymbol();
621360784Sdim  OutStreamer->EmitLabel(MILabel);
622360784Sdim
623360784Sdim  SM.recordPatchPoint(*MILabel, MI);
624341825Sdim  PatchPointOpers Opers(&MI);
625341825Sdim
626341825Sdim  unsigned EncodedBytes = 0;
627341825Sdim  const MachineOperand &CalleeMO = Opers.getCallTarget();
628341825Sdim
629341825Sdim  if (CalleeMO.isImm()) {
630341825Sdim    uint64_t CallTarget = CalleeMO.getImm();
631341825Sdim    if (CallTarget) {
632341825Sdim      unsigned ScratchIdx = -1;
633341825Sdim      unsigned ScratchReg = 0;
634341825Sdim      do {
635341825Sdim        ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
636341825Sdim        ScratchReg = MI.getOperand(ScratchIdx).getReg();
637341825Sdim      } while (ScratchReg == SystemZ::R0D);
638341825Sdim
639341825Sdim      // Materialize the call target address
640341825Sdim      EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
641341825Sdim                                      .addReg(ScratchReg)
642341825Sdim                                      .addImm(CallTarget & 0xFFFFFFFF));
643341825Sdim      EncodedBytes += 6;
644341825Sdim      if (CallTarget >> 32) {
645341825Sdim        EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
646341825Sdim                                        .addReg(ScratchReg)
647341825Sdim                                        .addImm(CallTarget >> 32));
648341825Sdim        EncodedBytes += 6;
649341825Sdim      }
650341825Sdim
651341825Sdim      EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
652341825Sdim                                     .addReg(SystemZ::R14D)
653341825Sdim                                     .addReg(ScratchReg));
654341825Sdim      EncodedBytes += 2;
655341825Sdim    }
656341825Sdim  } else if (CalleeMO.isGlobal()) {
657341825Sdim    const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT);
658341825Sdim    EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
659341825Sdim                                   .addReg(SystemZ::R14D)
660341825Sdim                                   .addExpr(Expr));
661341825Sdim    EncodedBytes += 6;
662341825Sdim  }
663341825Sdim
664341825Sdim  // Emit padding.
665341825Sdim  unsigned NumBytes = Opers.getNumPatchBytes();
666341825Sdim  assert(NumBytes >= EncodedBytes &&
667341825Sdim         "Patchpoint can't request size less than the length of a call.");
668341825Sdim  assert((NumBytes - EncodedBytes) % 2 == 0 &&
669341825Sdim         "Invalid number of NOP bytes requested!");
670341825Sdim  while (EncodedBytes < NumBytes)
671341825Sdim    EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
672341825Sdim                            getSubtargetInfo());
673341825Sdim}
674341825Sdim
675251607Sdim// Convert a SystemZ-specific constant pool modifier into the associated
676251607Sdim// MCSymbolRefExpr variant kind.
677251607Sdimstatic MCSymbolRefExpr::VariantKind
678251607SdimgetModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
679251607Sdim  switch (Modifier) {
680288943Sdim  case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
681288943Sdim  case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
682288943Sdim  case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
683251607Sdim  case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
684251607Sdim  }
685251607Sdim  llvm_unreachable("Invalid SystemCPModifier!");
686251607Sdim}
687251607Sdim
688251607Sdimvoid SystemZAsmPrinter::
689251607SdimEmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
690276479Sdim  auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
691251607Sdim
692251607Sdim  const MCExpr *Expr =
693288943Sdim    MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
694251607Sdim                            getModifierVariantKind(ZCPV->getModifier()),
695251607Sdim                            OutContext);
696296417Sdim  uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
697251607Sdim
698288943Sdim  OutStreamer->EmitValue(Expr, Size);
699251607Sdim}
700251607Sdim
701353358Sdimbool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
702251607Sdim                                        const char *ExtraCode,
703251607Sdim                                        raw_ostream &OS) {
704353358Sdim  if (ExtraCode)
705353358Sdim    return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
706353358Sdim  SystemZMCInstLower Lower(MF->getContext(), *this);
707353358Sdim  MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo)));
708353358Sdim  SystemZInstPrinter::printOperand(MO, MAI, OS);
709251607Sdim  return false;
710251607Sdim}
711251607Sdim
712251607Sdimbool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
713251607Sdim                                              unsigned OpNo,
714251607Sdim                                              const char *ExtraCode,
715251607Sdim                                              raw_ostream &OS) {
716251607Sdim  SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(),
717251607Sdim                                   MI->getOperand(OpNo + 1).getImm(),
718251607Sdim                                   MI->getOperand(OpNo + 2).getReg(), OS);
719251607Sdim  return false;
720251607Sdim}
721251607Sdim
722341825Sdimvoid SystemZAsmPrinter::EmitEndOfAsmFile(Module &M) {
723344779Sdim  emitStackMaps(SM);
724341825Sdim}
725341825Sdim
726251607Sdim// Force static initialization.
727360784Sdimextern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
728314564Sdim  RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
729251607Sdim}
730