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