blob: a4a8d6aabbb37fd6762b0c46ab6ce4f0f5d0919c [file] [log] [blame]
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +00001//===-- 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"
Dan Gohman2aa282f2009-08-13 01:36:44 +000022#include "llvm/Assembly/Writer.h"
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000023#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"
Chris Lattner73266f92009-08-19 05:49:37 +000029#include "llvm/MC/MCStreamer.h"
Chris Lattner621c44d2009-08-22 20:48:53 +000030#include "llvm/MC/MCAsmInfo.h"
Chris Lattnerc6f802d2009-09-13 17:14:04 +000031#include "llvm/MC/MCSymbol.h"
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000032#include "llvm/Target/TargetData.h"
Chris Lattnerc4c40a92009-07-28 03:13:23 +000033#include "llvm/Target/TargetLoweringObjectFile.h"
Anton Korobeynikov147a9a72009-07-16 14:36:52 +000034#include "llvm/Target/TargetRegistry.h"
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000035#include "llvm/ADT/Statistic.h"
Anton Korobeynikov147a9a72009-07-16 14:36:52 +000036#include "llvm/Support/FormattedStream.h"
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000037#include "llvm/Support/Mangler.h"
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000038
39using namespace llvm;
40
41STATISTIC(EmittedInsts, "Number of machine instrs printed");
42
43namespace {
Nick Lewycky492d06e2009-10-25 06:33:48 +000044 class SystemZAsmPrinter : public AsmPrinter {
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000045 public:
Anton Korobeynikov147a9a72009-07-16 14:36:52 +000046 SystemZAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
Chris Lattnera5ef4d32009-08-22 21:43:10 +000047 const MCAsmInfo *MAI, bool V)
48 : AsmPrinter(O, TM, MAI, V) {}
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000049
50 virtual const char *getPassName() const {
51 return "SystemZ Assembly Printer";
52 }
53
54 void printOperand(const MachineInstr *MI, int OpNum,
55 const char* Modifier = 0);
Anton Korobeynikov1c2eedb2009-07-16 14:16:05 +000056 void printPCRelImmOperand(const MachineInstr *MI, int OpNum);
Anton Korobeynikova58fac92009-07-16 13:43:18 +000057 void printRIAddrOperand(const MachineInstr *MI, int OpNum,
58 const char* Modifier = 0);
Anton Korobeynikov87b83aa2009-07-16 13:44:00 +000059 void printRRIAddrOperand(const MachineInstr *MI, int OpNum,
60 const char* Modifier = 0);
Anton Korobeynikovbf21bac2009-07-16 14:02:45 +000061 void printS16ImmOperand(const MachineInstr *MI, int OpNum) {
62 O << (int16_t)MI->getOperand(OpNum).getImm();
63 }
64 void printS32ImmOperand(const MachineInstr *MI, int OpNum) {
65 O << (int32_t)MI->getOperand(OpNum).getImm();
66 }
67
Chris Lattnerddb259a2009-08-08 01:32:19 +000068 void printInstruction(const MachineInstr *MI); // autogenerated.
Chris Lattner213703c2009-09-13 20:19:22 +000069 static const char *getRegisterName(unsigned RegNo);
Chris Lattner92221692009-09-13 20:08:00 +000070
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000071 void printMachineInstruction(const MachineInstr * MI);
72
73 void emitFunctionHeader(const MachineFunction &MF);
74 bool runOnMachineFunction(MachineFunction &F);
Chris Lattnerae982212009-07-21 18:38:57 +000075 void PrintGlobalVariable(const GlobalVariable* GVar);
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000076
77 void getAnalysisUsage(AnalysisUsage &AU) const {
78 AsmPrinter::getAnalysisUsage(AU);
79 AU.setPreservesAll();
80 }
81 };
82} // end of anonymous namespace
83
84#include "SystemZGenAsmWriter.inc"
85
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000086void SystemZAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
Anton Korobeynikov147a9a72009-07-16 14:36:52 +000087 unsigned FnAlign = MF.getAlignment();
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000088 const Function *F = MF.getFunction();
89
Chris Lattner73266f92009-08-19 05:49:37 +000090 OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000091
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000092 EmitAlignment(FnAlign, F);
93
94 switch (F->getLinkage()) {
95 default: assert(0 && "Unknown linkage type!");
96 case Function::InternalLinkage: // Symbols default to internal.
97 case Function::PrivateLinkage:
Bill Wendling41a07852009-07-20 01:03:30 +000098 case Function::LinkerPrivateLinkage:
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +000099 break;
100 case Function::ExternalLinkage:
101 O << "\t.globl\t" << CurrentFnName << '\n';
102 break;
103 case Function::LinkOnceAnyLinkage:
104 case Function::LinkOnceODRLinkage:
105 case Function::WeakAnyLinkage:
106 case Function::WeakODRLinkage:
107 O << "\t.weak\t" << CurrentFnName << '\n';
108 break;
109 }
110
111 printVisibility(CurrentFnName, F->getVisibility());
112
113 O << "\t.type\t" << CurrentFnName << ",@function\n"
114 << CurrentFnName << ":\n";
115}
116
117bool SystemZAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
118 SetupMachineFunction(MF);
119 O << "\n\n";
120
Anton Korobeynikov67565d62009-07-16 14:19:35 +0000121 // Print out constants referenced by the function
122 EmitConstantPool(MF.getConstantPool());
123
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +0000124 // Print the 'header' of function
125 emitFunctionHeader(MF);
126
127 // Print out code for the function.
128 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
129 I != E; ++I) {
130 // Print a label for the basic block.
Dan Gohman5fda4342009-10-06 17:38:38 +0000131 EmitBasicBlockStart(I);
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +0000132
133 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
134 II != E; ++II)
135 // Print the assembly for the instruction.
136 printMachineInstruction(II);
137 }
138
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000139 if (MAI->hasDotTypeDotSizeDirective())
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +0000140 O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
141
Anton Korobeynikov23bf4412009-07-16 14:07:50 +0000142 // Print out jump tables referenced by the function.
143 EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
144
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +0000145 // We didn't modify anything
146 return false;
147}
148
149void SystemZAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
150 ++EmittedInsts;
151
Devang Patel5450fc12009-10-06 02:19:11 +0000152 processDebugLoc(MI, true);
Chris Lattner32d4cc72009-09-09 23:14:36 +0000153
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +0000154 // Call the autogenerated instruction printer routines.
Chris Lattner7d337492009-08-08 00:05:42 +0000155 printInstruction(MI);
Chris Lattner32d4cc72009-09-09 23:14:36 +0000156
157 if (VerboseAsm && !MI->getDebugLoc().isUnknown())
158 EmitComments(*MI);
159 O << '\n';
Devang Patel5450fc12009-10-06 02:19:11 +0000160
161 processDebugLoc(MI, false);
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +0000162}
163
Chris Lattnerc6f802d2009-09-13 17:14:04 +0000164void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum){
Anton Korobeynikov1c2eedb2009-07-16 14:16:05 +0000165 const MachineOperand &MO = MI->getOperand(OpNum);
166 switch (MO.getType()) {
Anton Korobeynikovb4de0b82009-07-16 14:17:07 +0000167 case MachineOperand::MO_Immediate:
168 O << MO.getImm();
169 return;
170 case MachineOperand::MO_MachineBasicBlock:
Chris Lattnerc6f802d2009-09-13 17:14:04 +0000171 GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
Anton Korobeynikovb4de0b82009-07-16 14:17:07 +0000172 return;
Anton Korobeynikov1c2eedb2009-07-16 14:16:05 +0000173 case MachineOperand::MO_GlobalAddress: {
174 const GlobalValue *GV = MO.getGlobal();
Anton Korobeynikov147a9a72009-07-16 14:36:52 +0000175 std::string Name = Mang->getMangledName(GV);
Anton Korobeynikov1c2eedb2009-07-16 14:16:05 +0000176
177 O << Name;
178
179 // Assemble calls via PLT for externally visible symbols if PIC.
180 if (TM.getRelocationModel() == Reloc::PIC_ &&
181 !GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
182 !GV->hasLocalLinkage())
183 O << "@PLT";
184
185 printOffset(MO.getOffset());
186 return;
187 }
188 case MachineOperand::MO_ExternalSymbol: {
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000189 std::string Name(MAI->getGlobalPrefix());
Anton Korobeynikov1c2eedb2009-07-16 14:16:05 +0000190 Name += MO.getSymbolName();
191 O << Name;
192
193 if (TM.getRelocationModel() == Reloc::PIC_)
194 O << "@PLT";
195
196 return;
197 }
198 default:
199 assert(0 && "Not implemented yet!");
200 }
201}
202
203
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +0000204void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
Anton Korobeynikova58fac92009-07-16 13:43:18 +0000205 const char* Modifier) {
Anton Korobeynikovf259c6c2009-07-16 13:29:38 +0000206 const MachineOperand &MO = MI->getOperand(OpNum);
207 switch (MO.getType()) {
Anton Korobeynikov8a563652009-07-16 14:04:01 +0000208 case MachineOperand::MO_Register: {
Anton Korobeynikovf259c6c2009-07-16 13:29:38 +0000209 assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
210 "Virtual registers should be already mapped!");
Anton Korobeynikov8a563652009-07-16 14:04:01 +0000211 unsigned Reg = MO.getReg();
212 if (Modifier && strncmp(Modifier, "subreg", 6) == 0) {
213 if (strncmp(Modifier + 7, "even", 4) == 0)
214 Reg = TRI->getSubReg(Reg, SystemZ::SUBREG_EVEN);
215 else if (strncmp(Modifier + 7, "odd", 3) == 0)
216 Reg = TRI->getSubReg(Reg, SystemZ::SUBREG_ODD);
217 else
218 assert(0 && "Invalid subreg modifier");
219 }
220
Chris Lattnerf0a25de2009-09-13 20:31:40 +0000221 O << '%' << getRegisterName(Reg);
Anton Korobeynikovf259c6c2009-07-16 13:29:38 +0000222 return;
Anton Korobeynikov8a563652009-07-16 14:04:01 +0000223 }
Anton Korobeynikovf259c6c2009-07-16 13:29:38 +0000224 case MachineOperand::MO_Immediate:
Anton Korobeynikov8eef4042009-07-16 14:01:10 +0000225 O << MO.getImm();
Anton Korobeynikovf259c6c2009-07-16 13:29:38 +0000226 return;
227 case MachineOperand::MO_MachineBasicBlock:
Chris Lattnerc6f802d2009-09-13 17:14:04 +0000228 GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
Anton Korobeynikovf259c6c2009-07-16 13:29:38 +0000229 return;
Anton Korobeynikov23bf4412009-07-16 14:07:50 +0000230 case MachineOperand::MO_JumpTableIndex:
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000231 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
Anton Korobeynikov23bf4412009-07-16 14:07:50 +0000232 << MO.getIndex();
233
234 return;
Anton Korobeynikov67565d62009-07-16 14:19:35 +0000235 case MachineOperand::MO_ConstantPoolIndex:
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000236 O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
Anton Korobeynikov67565d62009-07-16 14:19:35 +0000237 << MO.getIndex();
238
239 printOffset(MO.getOffset());
240 break;
Anton Korobeynikov961cd4a2009-07-16 13:50:21 +0000241 case MachineOperand::MO_GlobalAddress: {
Anton Korobeynikovfafa2de2009-07-16 14:04:22 +0000242 const GlobalValue *GV = MO.getGlobal();
Anton Korobeynikov147a9a72009-07-16 14:36:52 +0000243 std::string Name = Mang->getMangledName(GV);
Anton Korobeynikov961cd4a2009-07-16 13:50:21 +0000244
245 O << Name;
Anton Korobeynikov1c2eedb2009-07-16 14:16:05 +0000246 break;
Anton Korobeynikov961cd4a2009-07-16 13:50:21 +0000247 }
248 case MachineOperand::MO_ExternalSymbol: {
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000249 std::string Name(MAI->getGlobalPrefix());
Anton Korobeynikov961cd4a2009-07-16 13:50:21 +0000250 Name += MO.getSymbolName();
251 O << Name;
Anton Korobeynikov1c2eedb2009-07-16 14:16:05 +0000252 break;
Anton Korobeynikov961cd4a2009-07-16 13:50:21 +0000253 }
Anton Korobeynikovf259c6c2009-07-16 13:29:38 +0000254 default:
255 assert(0 && "Not implemented yet!");
256 }
Anton Korobeynikov1c2eedb2009-07-16 14:16:05 +0000257
258 switch (MO.getTargetFlags()) {
259 default:
Anton Korobeynikov917cbe12009-07-18 13:33:17 +0000260 llvm_unreachable("Unknown target flag on GV operand");
Anton Korobeynikov1c2eedb2009-07-16 14:16:05 +0000261 case SystemZII::MO_NO_FLAG:
262 break;
263 case SystemZII::MO_GOTENT: O << "@GOTENT"; break;
264 case SystemZII::MO_PLT: O << "@PLT"; break;
265 }
266
267 printOffset(MO.getOffset());
Anton Korobeynikov32b7d5b2009-07-16 13:27:25 +0000268}
Anton Korobeynikova58fac92009-07-16 13:43:18 +0000269
270void SystemZAsmPrinter::printRIAddrOperand(const MachineInstr *MI, int OpNum,
271 const char* Modifier) {
272 const MachineOperand &Base = MI->getOperand(OpNum);
273
274 // Print displacement operand.
275 printOperand(MI, OpNum+1);
276
277 // Print base operand (if any)
Anton Korobeynikov87b83aa2009-07-16 13:44:00 +0000278 if (Base.getReg()) {
Anton Korobeynikova58fac92009-07-16 13:43:18 +0000279 O << '(';
280 printOperand(MI, OpNum);
281 O << ')';
282 }
283}
284
Anton Korobeynikov87b83aa2009-07-16 13:44:00 +0000285void SystemZAsmPrinter::printRRIAddrOperand(const MachineInstr *MI, int OpNum,
286 const char* Modifier) {
287 const MachineOperand &Base = MI->getOperand(OpNum);
Anton Korobeynikovf7cefd92009-07-16 13:48:42 +0000288 const MachineOperand &Index = MI->getOperand(OpNum+2);
Anton Korobeynikov87b83aa2009-07-16 13:44:00 +0000289
290 // Print displacement operand.
Anton Korobeynikovf7cefd92009-07-16 13:48:42 +0000291 printOperand(MI, OpNum+1);
Anton Korobeynikov87b83aa2009-07-16 13:44:00 +0000292
293 // Print base operand (if any)
294 if (Base.getReg()) {
295 O << '(';
296 printOperand(MI, OpNum);
297 if (Index.getReg()) {
298 O << ',';
Anton Korobeynikovf7cefd92009-07-16 13:48:42 +0000299 printOperand(MI, OpNum+2);
Anton Korobeynikov87b83aa2009-07-16 13:44:00 +0000300 }
301 O << ')';
302 } else
303 assert(!Index.getReg() && "Should allocate base register first!");
304}
305
Chris Lattnerae982212009-07-21 18:38:57 +0000306void SystemZAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
Anton Korobeynikovfafa2de2009-07-16 14:04:22 +0000307 const TargetData *TD = TM.getTargetData();
308
309 if (!GVar->hasInitializer())
310 return; // External global require no code
311
312 // Check to see if this is a special global used by LLVM, if so, emit it.
313 if (EmitSpecialLLVMGlobal(GVar))
314 return;
315
Anton Korobeynikov147a9a72009-07-16 14:36:52 +0000316 std::string name = Mang->getMangledName(GVar);
Anton Korobeynikovfafa2de2009-07-16 14:04:22 +0000317 Constant *C = GVar->getInitializer();
Anton Korobeynikov147a9a72009-07-16 14:36:52 +0000318 unsigned Size = TD->getTypeAllocSize(C->getType());
Anton Korobeynikovfafa2de2009-07-16 14:04:22 +0000319 unsigned Align = std::max(1U, TD->getPreferredAlignmentLog(GVar));
320
321 printVisibility(name, GVar->getVisibility());
322
323 O << "\t.type\t" << name << ",@object\n";
324
Chris Lattner73266f92009-08-19 05:49:37 +0000325 OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
326 TM));
Anton Korobeynikovfafa2de2009-07-16 14:04:22 +0000327
328 if (C->isNullValue() && !GVar->hasSection() &&
329 !GVar->isThreadLocal() &&
330 (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
331
332 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
333
334 if (GVar->hasLocalLinkage())
335 O << "\t.local\t" << name << '\n';
336
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000337 O << MAI->getCOMMDirective() << name << ',' << Size;
338 if (MAI->getCOMMDirectiveTakesAlignment())
339 O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
Anton Korobeynikovfafa2de2009-07-16 14:04:22 +0000340
341 if (VerboseAsm) {
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000342 O << "\t\t" << MAI->getCommentString() << ' ';
Dan Gohman2aa282f2009-08-13 01:36:44 +0000343 WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
Anton Korobeynikovfafa2de2009-07-16 14:04:22 +0000344 }
345 O << '\n';
346 return;
347 }
348
349 switch (GVar->getLinkage()) {
350 case GlobalValue::CommonLinkage:
351 case GlobalValue::LinkOnceAnyLinkage:
352 case GlobalValue::LinkOnceODRLinkage:
353 case GlobalValue::WeakAnyLinkage:
354 case GlobalValue::WeakODRLinkage:
355 O << "\t.weak\t" << name << '\n';
356 break;
357 case GlobalValue::DLLExportLinkage:
358 case GlobalValue::AppendingLinkage:
359 // FIXME: appending linkage variables should go into a section of
360 // their name or something. For now, just emit them as external.
361 case GlobalValue::ExternalLinkage:
362 // If external or appending, declare as a global symbol
363 O << "\t.globl " << name << '\n';
364 // FALL THROUGH
365 case GlobalValue::PrivateLinkage:
Bill Wendling41a07852009-07-20 01:03:30 +0000366 case GlobalValue::LinkerPrivateLinkage:
Anton Korobeynikovfafa2de2009-07-16 14:04:22 +0000367 case GlobalValue::InternalLinkage:
368 break;
369 default:
370 assert(0 && "Unknown linkage type!");
371 }
372
373 // Use 16-bit alignment by default to simplify bunch of stuff
374 EmitAlignment(Align, GVar, 1);
375 O << name << ":";
376 if (VerboseAsm) {
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000377 O << "\t\t\t\t" << MAI->getCommentString() << ' ';
Dan Gohman2aa282f2009-08-13 01:36:44 +0000378 WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent());
Anton Korobeynikovfafa2de2009-07-16 14:04:22 +0000379 }
380 O << '\n';
Chris Lattnera5ef4d32009-08-22 21:43:10 +0000381 if (MAI->hasDotTypeDotSizeDirective())
Anton Korobeynikovfafa2de2009-07-16 14:04:22 +0000382 O << "\t.size\t" << name << ", " << Size << '\n';
383
384 EmitGlobalConstant(C);
385}
Anton Korobeynikov147a9a72009-07-16 14:36:52 +0000386
387// Force static initialization.
388extern "C" void LLVMInitializeSystemZAsmPrinter() {
Daniel Dunbarc680b012009-07-25 06:49:55 +0000389 RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
Anton Korobeynikov147a9a72009-07-16 14:36:52 +0000390}