SystemZAsmPrinter.cpp revision 1139691e3aadff751c035f38f835d436ec6cf10a
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 printS32ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
59      O << (int32_t)MI->getOperand(OpNum).getImm();
60    }
61
62    void printInstruction(const MachineInstr *MI, raw_ostream &O);
63    static const char *getRegisterName(unsigned RegNo);
64
65    void EmitInstruction(const MachineInstr *MI);
66  };
67} // end of anonymous namespace
68
69#include "SystemZGenAsmWriter.inc"
70
71void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
72  SmallString<128> Str;
73  raw_svector_ostream OS(Str);
74  printInstruction(MI, OS);
75  OutStreamer.EmitRawText(OS.str());
76}
77
78void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum,
79                                             raw_ostream &O) {
80  const MachineOperand &MO = MI->getOperand(OpNum);
81  switch (MO.getType()) {
82  case MachineOperand::MO_Immediate:
83    O << MO.getImm();
84    return;
85  case MachineOperand::MO_MachineBasicBlock:
86    O << *MO.getMBB()->getSymbol();
87    return;
88  case MachineOperand::MO_GlobalAddress: {
89    const GlobalValue *GV = MO.getGlobal();
90    O << *Mang->getSymbol(GV);
91
92    // Assemble calls via PLT for externally visible symbols if PIC.
93    if (TM.getRelocationModel() == Reloc::PIC_ &&
94        !GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
95        !GV->hasLocalLinkage())
96      O << "@PLT";
97
98    printOffset(MO.getOffset(), O);
99    return;
100  }
101  case MachineOperand::MO_ExternalSymbol: {
102    std::string Name(MAI->getGlobalPrefix());
103    Name += MO.getSymbolName();
104    O << Name;
105
106    if (TM.getRelocationModel() == Reloc::PIC_)
107      O << "@PLT";
108
109    return;
110  }
111  default:
112    assert(0 && "Not implemented yet!");
113  }
114}
115
116
117void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
118                                     raw_ostream &O, const char *Modifier) {
119  const MachineOperand &MO = MI->getOperand(OpNum);
120  switch (MO.getType()) {
121  case MachineOperand::MO_Register: {
122    assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
123            "Virtual registers should be already mapped!");
124    unsigned Reg = MO.getReg();
125    if (Modifier && strncmp(Modifier, "subreg", 6) == 0) {
126      if (strncmp(Modifier + 7, "even", 4) == 0)
127        Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::subreg_32bit);
128      else if (strncmp(Modifier + 7, "odd", 3) == 0)
129        Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::subreg_odd32);
130      else
131        assert(0 && "Invalid subreg modifier");
132    }
133
134    O << '%' << getRegisterName(Reg);
135    return;
136  }
137  case MachineOperand::MO_Immediate:
138    O << MO.getImm();
139    return;
140  case MachineOperand::MO_MachineBasicBlock:
141    O << *MO.getMBB()->getSymbol();
142    return;
143  case MachineOperand::MO_JumpTableIndex:
144    O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
145      << MO.getIndex();
146
147    return;
148  case MachineOperand::MO_ConstantPoolIndex:
149    O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
150      << MO.getIndex();
151
152    printOffset(MO.getOffset(), O);
153    break;
154  case MachineOperand::MO_GlobalAddress:
155    O << *Mang->getSymbol(MO.getGlobal());
156    break;
157  case MachineOperand::MO_ExternalSymbol: {
158    O << *GetExternalSymbolSymbol(MO.getSymbolName());
159    break;
160  }
161  default:
162    assert(0 && "Not implemented yet!");
163  }
164
165  switch (MO.getTargetFlags()) {
166  default: assert(0 && "Unknown target flag on GV operand");
167  case SystemZII::MO_NO_FLAG:
168    break;
169  case SystemZII::MO_GOTENT:    O << "@GOTENT";    break;
170  case SystemZII::MO_PLT:       O << "@PLT";       break;
171  }
172
173  printOffset(MO.getOffset(), O);
174}
175
176void SystemZAsmPrinter::printRIAddrOperand(const MachineInstr *MI, int OpNum,
177                                           raw_ostream &O,
178                                           const char *Modifier) {
179  const MachineOperand &Base = MI->getOperand(OpNum);
180
181  // Print displacement operand.
182  printOperand(MI, OpNum+1, O);
183
184  // Print base operand (if any)
185  if (Base.getReg()) {
186    O << '(';
187    printOperand(MI, OpNum, O);
188    O << ')';
189  }
190}
191
192void SystemZAsmPrinter::printRRIAddrOperand(const MachineInstr *MI, int OpNum,
193                                            raw_ostream &O,
194                                            const char *Modifier) {
195  const MachineOperand &Base = MI->getOperand(OpNum);
196  const MachineOperand &Index = MI->getOperand(OpNum+2);
197
198  // Print displacement operand.
199  printOperand(MI, OpNum+1, O);
200
201  // Print base operand (if any)
202  if (Base.getReg()) {
203    O << '(';
204    printOperand(MI, OpNum, O);
205    if (Index.getReg()) {
206      O << ',';
207      printOperand(MI, OpNum+2, O);
208    }
209    O << ')';
210  } else
211    assert(!Index.getReg() && "Should allocate base register first!");
212}
213
214// Force static initialization.
215extern "C" void LLVMInitializeSystemZAsmPrinter() {
216  RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
217}
218