SystemZAsmPrinter.cpp revision b9dcca8265e9da01119c47e65f114c3adc972ba6
1//===-- 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"
21#include "llvm/MC/MCExpr.h"
22#include "llvm/MC/MCInstBuilder.h"
23#include "llvm/MC/MCStreamer.h"
24#include "llvm/Support/TargetRegistry.h"
25#include "llvm/Target/Mangler.h"
26
27using namespace llvm;
28
29// 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) {
32  return MCInstBuilder(Opcode)
33    .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
34    .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
35    .addImm(MI->getOperand(2).getImm());
36}
37
38// Return an RI instruction like MI with opcode Opcode, but with the
39// GR64 register operands turned into GRH32s.
40static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
41  return MCInstBuilder(Opcode)
42    .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
43    .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))
44    .addImm(MI->getOperand(2).getImm());
45}
46
47// Return an RI instruction like MI with opcode Opcode, but with the
48// R2 register turned into a GR64.
49static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
50  return MCInstBuilder(Opcode)
51    .addReg(MI->getOperand(0).getReg())
52    .addReg(MI->getOperand(1).getReg())
53    .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
54    .addImm(MI->getOperand(3).getImm())
55    .addImm(MI->getOperand(4).getImm())
56    .addImm(MI->getOperand(5).getImm());
57}
58
59void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
60  SystemZMCInstLower Lower(Mang, MF->getContext(), *this);
61  MCInst LoweredMI;
62  switch (MI->getOpcode()) {
63  case SystemZ::Return:
64    LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
65    break;
66
67  case SystemZ::CallBRASL:
68    LoweredMI = MCInstBuilder(SystemZ::BRASL)
69      .addReg(SystemZ::R14D)
70      .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
71    break;
72
73  case SystemZ::CallBASR:
74    LoweredMI = MCInstBuilder(SystemZ::BASR)
75      .addReg(SystemZ::R14D)
76      .addReg(MI->getOperand(0).getReg());
77    break;
78
79  case SystemZ::CallJG:
80    LoweredMI = MCInstBuilder(SystemZ::JG)
81      .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
82    break;
83
84  case SystemZ::CallBR:
85    LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R1D);
86    break;
87
88  case SystemZ::IILF64:
89    LoweredMI = MCInstBuilder(SystemZ::IILF)
90      .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
91      .addImm(MI->getOperand(2).getImm());
92    break;
93
94  case SystemZ::IIHF64:
95    LoweredMI = MCInstBuilder(SystemZ::IIHF)
96      .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
97      .addImm(MI->getOperand(2).getImm());
98    break;
99
100  case SystemZ::RISBHH:
101  case SystemZ::RISBHL:
102    LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
103    break;
104
105  case SystemZ::RISBLH:
106  case SystemZ::RISBLL:
107    LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
108    break;
109
110#define LOWER_LOW(NAME)                                                 \
111  case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
112
113  LOWER_LOW(IILL);
114  LOWER_LOW(IILH);
115  LOWER_LOW(NILL);
116  LOWER_LOW(NILH);
117  LOWER_LOW(NILF);
118  LOWER_LOW(OILL);
119  LOWER_LOW(OILH);
120  LOWER_LOW(OILF);
121  LOWER_LOW(XILF);
122
123#undef LOWER_LOW
124
125#define LOWER_HIGH(NAME) \
126  case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
127
128  LOWER_HIGH(IIHL);
129  LOWER_HIGH(IIHH);
130  LOWER_HIGH(NIHL);
131  LOWER_HIGH(NIHH);
132  LOWER_HIGH(NIHF);
133  LOWER_HIGH(OIHL);
134  LOWER_HIGH(OIHH);
135  LOWER_HIGH(OIHF);
136  LOWER_HIGH(XIHF);
137
138#undef LOWER_HIGH
139
140  default:
141    Lower.lower(MI, LoweredMI);
142    break;
143  }
144  OutStreamer.EmitInstruction(LoweredMI);
145}
146
147// Convert a SystemZ-specific constant pool modifier into the associated
148// MCSymbolRefExpr variant kind.
149static MCSymbolRefExpr::VariantKind
150getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
151  switch (Modifier) {
152  case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
153  }
154  llvm_unreachable("Invalid SystemCPModifier!");
155}
156
157void SystemZAsmPrinter::
158EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
159  SystemZConstantPoolValue *ZCPV =
160    static_cast<SystemZConstantPoolValue*>(MCPV);
161
162  const MCExpr *Expr =
163    MCSymbolRefExpr::Create(Mang->getSymbol(ZCPV->getGlobalValue()),
164                            getModifierVariantKind(ZCPV->getModifier()),
165                            OutContext);
166  uint64_t Size = TM.getDataLayout()->getTypeAllocSize(ZCPV->getType());
167
168  OutStreamer.EmitValue(Expr, Size);
169}
170
171bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
172                                        unsigned OpNo,
173                                        unsigned AsmVariant,
174                                        const char *ExtraCode,
175                                        raw_ostream &OS) {
176  if (ExtraCode && *ExtraCode == 'n') {
177    if (!MI->getOperand(OpNo).isImm())
178      return true;
179    OS << -int64_t(MI->getOperand(OpNo).getImm());
180  } else {
181    SystemZMCInstLower Lower(Mang, MF->getContext(), *this);
182    MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo)));
183    SystemZInstPrinter::printOperand(MO, OS);
184  }
185  return false;
186}
187
188bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
189                                              unsigned OpNo,
190                                              unsigned AsmVariant,
191                                              const char *ExtraCode,
192                                              raw_ostream &OS) {
193  SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(),
194                                   MI->getOperand(OpNo + 1).getImm(),
195                                   MI->getOperand(OpNo + 2).getReg(), OS);
196  return false;
197}
198
199void SystemZAsmPrinter::EmitEndOfAsmFile(Module &M) {
200  if (Subtarget->isTargetELF()) {
201    const TargetLoweringObjectFileELF &TLOFELF =
202      static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering());
203
204    MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
205
206    // Output stubs for external and common global variables.
207    MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
208    if (!Stubs.empty()) {
209      OutStreamer.SwitchSection(TLOFELF.getDataRelSection());
210      const DataLayout *TD = TM.getDataLayout();
211
212      for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
213        OutStreamer.EmitLabel(Stubs[i].first);
214        OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(),
215                                    TD->getPointerSize(0));
216      }
217      Stubs.clear();
218    }
219  }
220}
221
222// Force static initialization.
223extern "C" void LLVMInitializeSystemZAsmPrinter() {
224  RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
225}
226