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"
34 using namespace llvm;
35
36 namespace {
37 class SystemZAsmPrinter : public AsmPrinter {
38 public:
SystemZAsmPrinter(TargetMachine & TM,MCStreamer & Streamer)39 SystemZAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
40 : AsmPrinter(TM, Streamer) {}
41
getPassName() const42 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);
printS16ImmOperand(const MachineInstr * MI,int OpNum,raw_ostream & O)53 void printS16ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
54 O << (int16_t)MI->getOperand(OpNum).getImm();
55 }
printU16ImmOperand(const MachineInstr * MI,int OpNum,raw_ostream & O)56 void printU16ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
57 O << (uint16_t)MI->getOperand(OpNum).getImm();
58 }
printS32ImmOperand(const MachineInstr * MI,int OpNum,raw_ostream & O)59 void printS32ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
60 O << (int32_t)MI->getOperand(OpNum).getImm();
61 }
printU32ImmOperand(const MachineInstr * MI,int OpNum,raw_ostream & O)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
EmitInstruction(const MachineInstr * MI)75 void 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
printPCRelImmOperand(const MachineInstr * MI,int OpNum,raw_ostream & O)82 void 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
printOperand(const MachineInstr * MI,int OpNum,raw_ostream & O,const char * Modifier)121 void 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
printRIAddrOperand(const MachineInstr * MI,int OpNum,raw_ostream & O,const char * Modifier)180 void 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
printRRIAddrOperand(const MachineInstr * MI,int OpNum,raw_ostream & O,const char * Modifier)196 void 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.
LLVMInitializeSystemZAsmPrinter()219 extern "C" void LLVMInitializeSystemZAsmPrinter() {
220 RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
221 }
222