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