SystemZAsmPrinter.cpp revision cf2cdc9cae27a25deb50013b1337abb0c522c354
1//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly writer ---------------===//
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// This file contains a printer that converts from our internal representation
11// of machine-dependent LLVM code to the SystemZ assembly language.
12//
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "asm-printer"
16#include "SystemZ.h"
17#include "SystemZInstrInfo.h"
18#include "SystemZTargetMachine.h"
19#include "llvm/Constants.h"
20#include "llvm/DerivedTypes.h"
21#include "llvm/Module.h"
22#include "llvm/Assembly/Writer.h"
23#include "llvm/CodeGen/AsmPrinter.h"
24#include "llvm/CodeGen/MachineModuleInfo.h"
25#include "llvm/CodeGen/MachineFunctionPass.h"
26#include "llvm/CodeGen/MachineConstantPool.h"
27#include "llvm/MC/MCStreamer.h"
28#include "llvm/MC/MCAsmInfo.h"
29#include "llvm/MC/MCSymbol.h"
30#include "llvm/Target/Mangler.h"
31#include "llvm/Target/TargetData.h"
32#include "llvm/Target/TargetLoweringObjectFile.h"
33#include "llvm/Target/TargetRegistry.h"
34#include "llvm/ADT/SmallString.h"
35#include "llvm/Support/raw_ostream.h"
36using namespace llvm;
37
38namespace {
39  class SystemZAsmPrinter : public AsmPrinter {
40  public:
41    SystemZAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
42      : AsmPrinter(TM, Streamer) {}
43
44    virtual const char *getPassName() const {
45      return "SystemZ Assembly Printer";
46    }
47
48    void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
49                      const char* Modifier = 0);
50    void printPCRelImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
51    void printRIAddrOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
52                            const char* Modifier = 0);
53    void printRRIAddrOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
54                             const char* Modifier = 0);
55    void printS16ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
56      O << (int16_t)MI->getOperand(OpNum).getImm();
57    }
58    void printU16ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
59      O << (uint16_t)MI->getOperand(OpNum).getImm();
60    }
61    void printS32ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
62      O << (int32_t)MI->getOperand(OpNum).getImm();
63    }
64    void printU32ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
65      O << (uint32_t)MI->getOperand(OpNum).getImm();
66    }
67
68    void printInstruction(const MachineInstr *MI, raw_ostream &O);
69    static const char *getRegisterName(unsigned RegNo);
70
71    void EmitInstruction(const MachineInstr *MI);
72  };
73} // end of anonymous namespace
74
75#include "SystemZGenAsmWriter.inc"
76
77void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
78  SmallString<128> Str;
79  raw_svector_ostream OS(Str);
80  printInstruction(MI, OS);
81  OutStreamer.EmitRawText(OS.str());
82}
83
84void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum,
85                                             raw_ostream &O) {
86  const MachineOperand &MO = MI->getOperand(OpNum);
87  switch (MO.getType()) {
88  case MachineOperand::MO_Immediate:
89    O << MO.getImm();
90    return;
91  case MachineOperand::MO_MachineBasicBlock:
92    O << *MO.getMBB()->getSymbol();
93    return;
94  case MachineOperand::MO_GlobalAddress: {
95    const GlobalValue *GV = MO.getGlobal();
96    O << *Mang->getSymbol(GV);
97
98    // Assemble calls via PLT for externally visible symbols if PIC.
99    if (TM.getRelocationModel() == Reloc::PIC_ &&
100        !GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
101        !GV->hasLocalLinkage())
102      O << "@PLT";
103
104    printOffset(MO.getOffset(), O);
105    return;
106  }
107  case MachineOperand::MO_ExternalSymbol: {
108    std::string Name(MAI->getGlobalPrefix());
109    Name += MO.getSymbolName();
110    O << Name;
111
112    if (TM.getRelocationModel() == Reloc::PIC_)
113      O << "@PLT";
114
115    return;
116  }
117  default:
118    assert(0 && "Not implemented yet!");
119  }
120}
121
122
123void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
124                                     raw_ostream &O, const char *Modifier) {
125  const MachineOperand &MO = MI->getOperand(OpNum);
126  switch (MO.getType()) {
127  case MachineOperand::MO_Register: {
128    assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
129            "Virtual registers should be already mapped!");
130    unsigned Reg = MO.getReg();
131    if (Modifier && strncmp(Modifier, "subreg", 6) == 0) {
132      if (strncmp(Modifier + 7, "even", 4) == 0)
133        Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::subreg_32bit);
134      else if (strncmp(Modifier + 7, "odd", 3) == 0)
135        Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::subreg_odd32);
136      else
137        assert(0 && "Invalid subreg modifier");
138    }
139
140    O << '%' << getRegisterName(Reg);
141    return;
142  }
143  case MachineOperand::MO_Immediate:
144    O << MO.getImm();
145    return;
146  case MachineOperand::MO_MachineBasicBlock:
147    O << *MO.getMBB()->getSymbol();
148    return;
149  case MachineOperand::MO_JumpTableIndex:
150    O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
151      << MO.getIndex();
152
153    return;
154  case MachineOperand::MO_ConstantPoolIndex:
155    O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
156      << MO.getIndex();
157
158    printOffset(MO.getOffset(), O);
159    break;
160  case MachineOperand::MO_GlobalAddress:
161    O << *Mang->getSymbol(MO.getGlobal());
162    break;
163  case MachineOperand::MO_ExternalSymbol: {
164    O << *GetExternalSymbolSymbol(MO.getSymbolName());
165    break;
166  }
167  default:
168    assert(0 && "Not implemented yet!");
169  }
170
171  switch (MO.getTargetFlags()) {
172  default: assert(0 && "Unknown target flag on GV operand");
173  case SystemZII::MO_NO_FLAG:
174    break;
175  case SystemZII::MO_GOTENT:    O << "@GOTENT";    break;
176  case SystemZII::MO_PLT:       O << "@PLT";       break;
177  }
178
179  printOffset(MO.getOffset(), O);
180}
181
182void SystemZAsmPrinter::printRIAddrOperand(const MachineInstr *MI, int OpNum,
183                                           raw_ostream &O,
184                                           const char *Modifier) {
185  const MachineOperand &Base = MI->getOperand(OpNum);
186
187  // Print displacement operand.
188  printOperand(MI, OpNum+1, O);
189
190  // Print base operand (if any)
191  if (Base.getReg()) {
192    O << '(';
193    printOperand(MI, OpNum, O);
194    O << ')';
195  }
196}
197
198void SystemZAsmPrinter::printRRIAddrOperand(const MachineInstr *MI, int OpNum,
199                                            raw_ostream &O,
200                                            const char *Modifier) {
201  const MachineOperand &Base = MI->getOperand(OpNum);
202  const MachineOperand &Index = MI->getOperand(OpNum+2);
203
204  // Print displacement operand.
205  printOperand(MI, OpNum+1, O);
206
207  // Print base operand (if any)
208  if (Base.getReg()) {
209    O << '(';
210    printOperand(MI, OpNum, O);
211    if (Index.getReg()) {
212      O << ',';
213      printOperand(MI, OpNum+2, O);
214    }
215    O << ')';
216  } else
217    assert(!Index.getReg() && "Should allocate base register first!");
218}
219
220// Force static initialization.
221extern "C" void LLVMInitializeSystemZAsmPrinter() {
222  RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
223}
224