1 //===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Streams SystemZ assembly language and associated data, in the form of
10 // MCInsts and MCExprs respectively.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "SystemZAsmPrinter.h"
15 #include "MCTargetDesc/SystemZInstPrinter.h"
16 #include "SystemZConstantPoolValue.h"
17 #include "SystemZMCInstLower.h"
18 #include "TargetInfo/SystemZTargetInfo.h"
19 #include "llvm/BinaryFormat/ELF.h"
20 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
21 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
22 #include "llvm/IR/Mangler.h"
23 #include "llvm/MC/MCExpr.h"
24 #include "llvm/MC/MCInstBuilder.h"
25 #include "llvm/MC/MCSectionELF.h"
26 #include "llvm/MC/MCStreamer.h"
27 #include "llvm/Support/TargetRegistry.h"
28
29 using namespace llvm;
30
31 // Return an RI instruction like MI with opcode Opcode, but with the
32 // GR64 register operands turned into GR32s.
lowerRILow(const MachineInstr * MI,unsigned Opcode)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.
lowerRIHigh(const MachineInstr * MI,unsigned Opcode)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.
lowerRIEfLow(const MachineInstr * MI,unsigned Opcode)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
getTLSGetOffset(MCContext & Context)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
getGlobalOffsetTable(MCContext & Context)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.
lowerAlignmentHint(const MachineInstr * MI,MCInst & LoweredMI,unsigned Opcode)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.
lowerSubvectorLoad(const MachineInstr * MI,unsigned Opcode)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.
lowerSubvectorStore(const MachineInstr * MI,unsigned Opcode)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
emitInstruction(const MachineInstr * MI)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 MCSymbol *DotSym = nullptr;
553 MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
554 .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
555 MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
556 EXRLT2SymMap::iterator I = EXRLTargets2Sym.find(ET_STI);
557 if (I != EXRLTargets2Sym.end())
558 DotSym = I->second;
559 else
560 EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
561 const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
562 EmitToStreamer(
563 *OutStreamer,
564 MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
565 return;
566 }
567
568 default:
569 Lower.lower(MI, LoweredMI);
570 break;
571 }
572 EmitToStreamer(*OutStreamer, LoweredMI);
573 }
574
575 // Emit the largest nop instruction smaller than or equal to NumBytes
576 // bytes. Return the size of nop emitted.
EmitNop(MCContext & OutContext,MCStreamer & OutStreamer,unsigned NumBytes,const MCSubtargetInfo & STI)577 static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
578 unsigned NumBytes, const MCSubtargetInfo &STI) {
579 if (NumBytes < 2) {
580 llvm_unreachable("Zero nops?");
581 return 0;
582 }
583 else if (NumBytes < 4) {
584 OutStreamer.emitInstruction(
585 MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
586 return 2;
587 }
588 else if (NumBytes < 6) {
589 OutStreamer.emitInstruction(
590 MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
591 STI);
592 return 4;
593 }
594 else {
595 MCSymbol *DotSym = OutContext.createTempSymbol();
596 const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
597 OutStreamer.emitLabel(DotSym);
598 OutStreamer.emitInstruction(
599 MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
600 return 6;
601 }
602 }
603
LowerFENTRY_CALL(const MachineInstr & MI,SystemZMCInstLower & Lower)604 void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
605 SystemZMCInstLower &Lower) {
606 MCContext &Ctx = MF->getContext();
607 if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
608 MCSymbol *DotSym = OutContext.createTempSymbol();
609 OutStreamer->PushSection();
610 OutStreamer->SwitchSection(
611 Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
612 OutStreamer->emitSymbolValue(DotSym, 8);
613 OutStreamer->PopSection();
614 OutStreamer->emitLabel(DotSym);
615 }
616
617 if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
618 EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
619 return;
620 }
621
622 MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
623 const MCSymbolRefExpr *Op =
624 MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
625 OutStreamer->emitInstruction(
626 MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
627 getSubtargetInfo());
628 }
629
LowerSTACKMAP(const MachineInstr & MI)630 void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
631 const SystemZInstrInfo *TII =
632 static_cast<const SystemZInstrInfo *>(MF->getSubtarget().getInstrInfo());
633
634 unsigned NumNOPBytes = MI.getOperand(1).getImm();
635
636 auto &Ctx = OutStreamer->getContext();
637 MCSymbol *MILabel = Ctx.createTempSymbol();
638 OutStreamer->emitLabel(MILabel);
639
640 SM.recordStackMap(*MILabel, MI);
641 assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
642
643 // Scan ahead to trim the shadow.
644 unsigned ShadowBytes = 0;
645 const MachineBasicBlock &MBB = *MI.getParent();
646 MachineBasicBlock::const_iterator MII(MI);
647 ++MII;
648 while (ShadowBytes < NumNOPBytes) {
649 if (MII == MBB.end() ||
650 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
651 MII->getOpcode() == TargetOpcode::STACKMAP)
652 break;
653 ShadowBytes += TII->getInstSizeInBytes(*MII);
654 if (MII->isCall())
655 break;
656 ++MII;
657 }
658
659 // Emit nops.
660 while (ShadowBytes < NumNOPBytes)
661 ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
662 getSubtargetInfo());
663 }
664
665 // Lower a patchpoint of the form:
666 // [<def>], <id>, <numBytes>, <target>, <numArgs>
LowerPATCHPOINT(const MachineInstr & MI,SystemZMCInstLower & Lower)667 void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
668 SystemZMCInstLower &Lower) {
669 auto &Ctx = OutStreamer->getContext();
670 MCSymbol *MILabel = Ctx.createTempSymbol();
671 OutStreamer->emitLabel(MILabel);
672
673 SM.recordPatchPoint(*MILabel, MI);
674 PatchPointOpers Opers(&MI);
675
676 unsigned EncodedBytes = 0;
677 const MachineOperand &CalleeMO = Opers.getCallTarget();
678
679 if (CalleeMO.isImm()) {
680 uint64_t CallTarget = CalleeMO.getImm();
681 if (CallTarget) {
682 unsigned ScratchIdx = -1;
683 unsigned ScratchReg = 0;
684 do {
685 ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
686 ScratchReg = MI.getOperand(ScratchIdx).getReg();
687 } while (ScratchReg == SystemZ::R0D);
688
689 // Materialize the call target address
690 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
691 .addReg(ScratchReg)
692 .addImm(CallTarget & 0xFFFFFFFF));
693 EncodedBytes += 6;
694 if (CallTarget >> 32) {
695 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
696 .addReg(ScratchReg)
697 .addImm(CallTarget >> 32));
698 EncodedBytes += 6;
699 }
700
701 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
702 .addReg(SystemZ::R14D)
703 .addReg(ScratchReg));
704 EncodedBytes += 2;
705 }
706 } else if (CalleeMO.isGlobal()) {
707 const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT);
708 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
709 .addReg(SystemZ::R14D)
710 .addExpr(Expr));
711 EncodedBytes += 6;
712 }
713
714 // Emit padding.
715 unsigned NumBytes = Opers.getNumPatchBytes();
716 assert(NumBytes >= EncodedBytes &&
717 "Patchpoint can't request size less than the length of a call.");
718 assert((NumBytes - EncodedBytes) % 2 == 0 &&
719 "Invalid number of NOP bytes requested!");
720 while (EncodedBytes < NumBytes)
721 EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
722 getSubtargetInfo());
723 }
724
emitEXRLTargetInstructions()725 void SystemZAsmPrinter::emitEXRLTargetInstructions() {
726 if (EXRLTargets2Sym.empty())
727 return;
728 // Switch to the .text section.
729 OutStreamer->SwitchSection(getObjFileLowering().getTextSection());
730 for (auto &I : EXRLTargets2Sym) {
731 OutStreamer->emitLabel(I.second);
732 const MCInstSTIPair &MCI_STI = I.first;
733 OutStreamer->emitInstruction(MCI_STI.first, *MCI_STI.second);
734 }
735 EXRLTargets2Sym.clear();
736 }
737
738 // Convert a SystemZ-specific constant pool modifier into the associated
739 // MCSymbolRefExpr variant kind.
740 static MCSymbolRefExpr::VariantKind
getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier)741 getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
742 switch (Modifier) {
743 case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
744 case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
745 case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
746 case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
747 }
748 llvm_unreachable("Invalid SystemCPModifier!");
749 }
750
emitMachineConstantPoolValue(MachineConstantPoolValue * MCPV)751 void SystemZAsmPrinter::emitMachineConstantPoolValue(
752 MachineConstantPoolValue *MCPV) {
753 auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
754
755 const MCExpr *Expr =
756 MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
757 getModifierVariantKind(ZCPV->getModifier()),
758 OutContext);
759 uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
760
761 OutStreamer->emitValue(Expr, Size);
762 }
763
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & OS)764 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
765 const char *ExtraCode,
766 raw_ostream &OS) {
767 const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
768 const MachineOperand &MO = MI->getOperand(OpNo);
769 MCOperand MCOp;
770 if (ExtraCode) {
771 if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
772 SystemZ::GR128BitRegClass.contains(MO.getReg()))
773 MCOp =
774 MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
775 else
776 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
777 } else {
778 SystemZMCInstLower Lower(MF->getContext(), *this);
779 MCOp = Lower.lowerOperand(MO);
780 }
781 SystemZInstPrinter::printOperand(MCOp, MAI, OS);
782 return false;
783 }
784
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & OS)785 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
786 unsigned OpNo,
787 const char *ExtraCode,
788 raw_ostream &OS) {
789 SystemZInstPrinter::printAddress(MAI, MI->getOperand(OpNo).getReg(),
790 MI->getOperand(OpNo + 1).getImm(),
791 MI->getOperand(OpNo + 2).getReg(), OS);
792 return false;
793 }
794
emitEndOfAsmFile(Module & M)795 void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
796 emitEXRLTargetInstructions();
797 emitStackMaps(SM);
798 }
799
800 // Force static initialization.
LLVMInitializeSystemZAsmPrinter()801 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
802 RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
803 }
804