blob: 18e37e32b0a077e7bc021b4f86bed653970eb906 [file] [log] [blame]
Ulrich Weigand5f613df2013-05-06 16:15:19 +00001//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Streams SystemZ assembly language and associated data, in the form of
11// MCInsts and MCExprs respectively.
12//
13//===----------------------------------------------------------------------===//
14
15#include "SystemZAsmPrinter.h"
16#include "InstPrinter/SystemZInstPrinter.h"
17#include "SystemZConstantPoolValue.h"
18#include "SystemZMCInstLower.h"
19#include "llvm/CodeGen/MachineModuleInfoImpls.h"
20#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
Rafael Espindola894843c2014-01-07 21:19:40 +000021#include "llvm/IR/Mangler.h"
Ulrich Weigand5f613df2013-05-06 16:15:19 +000022#include "llvm/MC/MCExpr.h"
Richard Sandiford9ab97cd2013-09-25 10:20:08 +000023#include "llvm/MC/MCInstBuilder.h"
Ulrich Weigand5f613df2013-05-06 16:15:19 +000024#include "llvm/MC/MCStreamer.h"
25#include "llvm/Support/TargetRegistry.h"
Ulrich Weigand5f613df2013-05-06 16:15:19 +000026
27using namespace llvm;
28
Richard Sandiford652784e2013-09-25 11:11:53 +000029// Return an RI instruction like MI with opcode Opcode, but with the
30// GR64 register operands turned into GR32s.
31static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
Richard Sandifordf03789c2013-11-22 17:28:28 +000032 if (MI->isCompare())
33 return MCInstBuilder(Opcode)
34 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
35 .addImm(MI->getOperand(1).getImm());
36 else
37 return MCInstBuilder(Opcode)
38 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
39 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
40 .addImm(MI->getOperand(2).getImm());
Richard Sandiford652784e2013-09-25 11:11:53 +000041}
42
Richard Sandiford0755c932013-10-01 11:26:28 +000043// Return an RI instruction like MI with opcode Opcode, but with the
Richard Sandiford1a569312013-10-01 13:18:56 +000044// GR64 register operands turned into GRH32s.
45static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
Richard Sandifordf03789c2013-11-22 17:28:28 +000046 if (MI->isCompare())
47 return MCInstBuilder(Opcode)
48 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
49 .addImm(MI->getOperand(1).getImm());
50 else
51 return MCInstBuilder(Opcode)
52 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
53 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))
54 .addImm(MI->getOperand(2).getImm());
Richard Sandiford1a569312013-10-01 13:18:56 +000055}
56
57// Return an RI instruction like MI with opcode Opcode, but with the
Richard Sandiford0755c932013-10-01 11:26:28 +000058// R2 register turned into a GR64.
59static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
60 return MCInstBuilder(Opcode)
61 .addReg(MI->getOperand(0).getReg())
62 .addReg(MI->getOperand(1).getReg())
63 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
64 .addImm(MI->getOperand(3).getImm())
65 .addImm(MI->getOperand(4).getImm())
66 .addImm(MI->getOperand(5).getImm());
67}
68
Ulrich Weigand7db69182015-02-18 09:13:27 +000069static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
70 StringRef Name = "__tls_get_offset";
71 return MCSymbolRefExpr::Create(Context.GetOrCreateSymbol(Name),
72 MCSymbolRefExpr::VK_PLT,
73 Context);
74}
75
76static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
77 StringRef Name = "_GLOBAL_OFFSET_TABLE_";
78 return MCSymbolRefExpr::Create(Context.GetOrCreateSymbol(Name),
79 MCSymbolRefExpr::VK_None,
80 Context);
81}
82
Ulrich Weigand5f613df2013-05-06 16:15:19 +000083void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
Rafael Espindola69c1d632013-10-29 16:18:15 +000084 SystemZMCInstLower Lower(MF->getContext(), *this);
Ulrich Weigand5f613df2013-05-06 16:15:19 +000085 MCInst LoweredMI;
Richard Sandiford9ab97cd2013-09-25 10:20:08 +000086 switch (MI->getOpcode()) {
87 case SystemZ::Return:
88 LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
89 break;
90
Richard Sandifordf348f832013-09-25 10:37:17 +000091 case SystemZ::CallBRASL:
92 LoweredMI = MCInstBuilder(SystemZ::BRASL)
93 .addReg(SystemZ::R14D)
94 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
95 break;
96
97 case SystemZ::CallBASR:
98 LoweredMI = MCInstBuilder(SystemZ::BASR)
99 .addReg(SystemZ::R14D)
100 .addReg(MI->getOperand(0).getReg());
101 break;
102
103 case SystemZ::CallJG:
104 LoweredMI = MCInstBuilder(SystemZ::JG)
105 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
106 break;
107
108 case SystemZ::CallBR:
109 LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R1D);
110 break;
111
Ulrich Weigand7db69182015-02-18 09:13:27 +0000112 case SystemZ::TLS_GDCALL:
113 LoweredMI = MCInstBuilder(SystemZ::BRASL)
114 .addReg(SystemZ::R14D)
115 .addExpr(getTLSGetOffset(MF->getContext()))
116 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
117 break;
118
119 case SystemZ::TLS_LDCALL:
120 LoweredMI = MCInstBuilder(SystemZ::BRASL)
121 .addReg(SystemZ::R14D)
122 .addExpr(getTLSGetOffset(MF->getContext()))
123 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
124 break;
125
126 case SystemZ::GOT:
127 LoweredMI = MCInstBuilder(SystemZ::LARL)
128 .addReg(MI->getOperand(0).getReg())
129 .addExpr(getGlobalOffsetTable(MF->getContext()));
130 break;
131
Richard Sandiford652784e2013-09-25 11:11:53 +0000132 case SystemZ::IILF64:
133 LoweredMI = MCInstBuilder(SystemZ::IILF)
134 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
135 .addImm(MI->getOperand(2).getImm());
136 break;
137
Richard Sandiford01240232013-10-01 13:02:28 +0000138 case SystemZ::IIHF64:
139 LoweredMI = MCInstBuilder(SystemZ::IIHF)
140 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
141 .addImm(MI->getOperand(2).getImm());
142 break;
143
Richard Sandiford0755c932013-10-01 11:26:28 +0000144 case SystemZ::RISBHH:
145 case SystemZ::RISBHL:
146 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
147 break;
148
149 case SystemZ::RISBLH:
150 case SystemZ::RISBLL:
151 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
152 break;
153
Richard Sandiford652784e2013-09-25 11:11:53 +0000154#define LOWER_LOW(NAME) \
155 case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
156
157 LOWER_LOW(IILL);
158 LOWER_LOW(IILH);
Richard Sandifordf03789c2013-11-22 17:28:28 +0000159 LOWER_LOW(TMLL);
160 LOWER_LOW(TMLH);
Richard Sandiford652784e2013-09-25 11:11:53 +0000161 LOWER_LOW(NILL);
162 LOWER_LOW(NILH);
163 LOWER_LOW(NILF);
164 LOWER_LOW(OILL);
165 LOWER_LOW(OILH);
166 LOWER_LOW(OILF);
167 LOWER_LOW(XILF);
168
169#undef LOWER_LOW
170
Richard Sandiford1a569312013-10-01 13:18:56 +0000171#define LOWER_HIGH(NAME) \
172 case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
173
174 LOWER_HIGH(IIHL);
175 LOWER_HIGH(IIHH);
Richard Sandifordf03789c2013-11-22 17:28:28 +0000176 LOWER_HIGH(TMHL);
177 LOWER_HIGH(TMHH);
Richard Sandiford70284282013-10-01 14:20:41 +0000178 LOWER_HIGH(NIHL);
179 LOWER_HIGH(NIHH);
180 LOWER_HIGH(NIHF);
Richard Sandiford6e96ac62013-10-01 13:22:41 +0000181 LOWER_HIGH(OIHL);
182 LOWER_HIGH(OIHH);
183 LOWER_HIGH(OIHF);
Richard Sandiford5718dac2013-10-01 14:08:44 +0000184 LOWER_HIGH(XIHF);
Richard Sandiford1a569312013-10-01 13:18:56 +0000185
186#undef LOWER_HIGH
187
Richard Sandiford9afe6132013-12-10 10:36:34 +0000188 case SystemZ::Serialize:
Eric Christopherd84f5d32015-02-19 01:26:28 +0000189 if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
Richard Sandiford9afe6132013-12-10 10:36:34 +0000190 LoweredMI = MCInstBuilder(SystemZ::AsmBCR)
191 .addImm(14).addReg(SystemZ::R0D);
192 else
193 LoweredMI = MCInstBuilder(SystemZ::AsmBCR)
194 .addImm(15).addReg(SystemZ::R0D);
195 break;
196
Richard Sandiford9ab97cd2013-09-25 10:20:08 +0000197 default:
Richard Sandifordf348f832013-09-25 10:37:17 +0000198 Lower.lower(MI, LoweredMI);
Richard Sandiford9ab97cd2013-09-25 10:20:08 +0000199 break;
200 }
David Woodhousee6c13e42014-01-28 23:12:42 +0000201 EmitToStreamer(OutStreamer, LoweredMI);
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000202}
203
204// Convert a SystemZ-specific constant pool modifier into the associated
205// MCSymbolRefExpr variant kind.
206static MCSymbolRefExpr::VariantKind
207getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
208 switch (Modifier) {
Ulrich Weigand7db69182015-02-18 09:13:27 +0000209 case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
210 case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
211 case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000212 case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
213 }
214 llvm_unreachable("Invalid SystemCPModifier!");
215}
216
217void SystemZAsmPrinter::
218EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
Richard Sandiford21f5d682014-03-06 11:22:58 +0000219 auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000220
221 const MCExpr *Expr =
Rafael Espindola79858aa2013-10-29 17:07:16 +0000222 MCSymbolRefExpr::Create(getSymbol(ZCPV->getGlobalValue()),
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000223 getModifierVariantKind(ZCPV->getModifier()),
224 OutContext);
Eric Christopher8b770652015-01-26 19:03:15 +0000225 uint64_t Size = TM.getDataLayout()->getTypeAllocSize(ZCPV->getType());
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000226
227 OutStreamer.EmitValue(Expr, Size);
228}
229
230bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
231 unsigned OpNo,
232 unsigned AsmVariant,
233 const char *ExtraCode,
234 raw_ostream &OS) {
235 if (ExtraCode && *ExtraCode == 'n') {
236 if (!MI->getOperand(OpNo).isImm())
237 return true;
238 OS << -int64_t(MI->getOperand(OpNo).getImm());
239 } else {
Rafael Espindola69c1d632013-10-29 16:18:15 +0000240 SystemZMCInstLower Lower(MF->getContext(), *this);
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000241 MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo)));
242 SystemZInstPrinter::printOperand(MO, OS);
243 }
244 return false;
245}
246
247bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
248 unsigned OpNo,
249 unsigned AsmVariant,
250 const char *ExtraCode,
251 raw_ostream &OS) {
252 SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(),
253 MI->getOperand(OpNo + 1).getImm(),
254 MI->getOperand(OpNo + 2).getReg(), OS);
255 return false;
256}
257
258void SystemZAsmPrinter::EmitEndOfAsmFile(Module &M) {
Eric Christopherd84f5d32015-02-19 01:26:28 +0000259 if (Triple(TM.getTargetTriple()).isOSBinFormatELF()) {
Richard Sandiford21f5d682014-03-06 11:22:58 +0000260 auto &TLOFELF =
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000261 static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering());
262
263 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
264
265 // Output stubs for external and common global variables.
266 MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
267 if (!Stubs.empty()) {
268 OutStreamer.SwitchSection(TLOFELF.getDataRelSection());
Eric Christopher8b770652015-01-26 19:03:15 +0000269 const DataLayout *TD = TM.getDataLayout();
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000270
271 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
272 OutStreamer.EmitLabel(Stubs[i].first);
273 OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(),
Rafael Espindola64e1af82013-07-02 15:49:13 +0000274 TD->getPointerSize(0));
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000275 }
276 Stubs.clear();
277 }
278 }
279}
280
281// Force static initialization.
282extern "C" void LLVMInitializeSystemZAsmPrinter() {
283 RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
284}