blob: d6c401a3e6a869f4e41d9e5631663c640b6d12eb [file] [log] [blame]
Chris Lattner0bc33332004-12-16 16:47:03 +00001//===-- SparcV9AsmPrinter.cpp - Emit SparcV9 Specific .s File --------------==//
John Criswell482202a2003-10-20 19:43:21 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Chris Lattner036a3172001-09-19 13:47:27 +00009//
Misha Brukman7eb05a12003-08-18 14:43:39 +000010// This file implements all of the stuff necessary to output a .s file from
Chris Lattner036a3172001-09-19 13:47:27 +000011// LLVM. The code in this file assumes that the specified module has already
12// been compiled into the internal data structures of the Module.
13//
Chris Lattnerc8e66542002-04-27 06:56:12 +000014// This code largely consists of two LLVM Pass's: a FunctionPass and a Pass.
15// The FunctionPass is pipelined together with all of the rest of the code
16// generation stages, and the Pass runs at the end to emit code for global
17// variables and such.
Chris Lattner036a3172001-09-19 13:47:27 +000018//
19//===----------------------------------------------------------------------===//
20
Chris Lattnerca142372002-04-28 19:55:58 +000021#include "llvm/Constants.h"
Vikram S. Adve71b265a2001-10-28 21:38:52 +000022#include "llvm/DerivedTypes.h"
Chris Lattner036a3172001-09-19 13:47:27 +000023#include "llvm/Module.h"
Chris Lattner63c52f32002-04-28 20:40:59 +000024#include "llvm/Pass.h"
Chris Lattnerc3728c22002-04-18 18:15:38 +000025#include "llvm/Assembly/Writer.h"
Misha Brukman0f425852003-12-17 22:06:28 +000026#include "llvm/CodeGen/MachineConstantPool.h"
27#include "llvm/CodeGen/MachineFunction.h"
Misha Brukman0f425852003-12-17 22:06:28 +000028#include "llvm/CodeGen/MachineInstr.h"
Misha Brukman929d1d12004-01-15 22:44:19 +000029#include "llvm/Support/Mangler.h"
Reid Spencer7c16caa2004-09-01 22:55:40 +000030#include "llvm/ADT/StringExtras.h"
31#include "llvm/ADT/Statistic.h"
Brian Gaeke94e95d22004-02-25 18:44:15 +000032#include "SparcV9Internals.h"
Chris Lattner9fb30a42004-08-16 21:55:02 +000033#include "MachineFunctionInfo.h"
Misha Brukman1e88cfb2003-08-05 16:01:50 +000034#include <string>
Misha Brukman6675f982003-11-13 00:22:19 +000035using namespace llvm;
36
Chris Lattner036a3172001-09-19 13:47:27 +000037namespace {
Misha Brukman6675f982003-11-13 00:22:19 +000038 Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
Brian Gaeke86584742004-09-10 18:01:45 +000039
40 //===--------------------------------------------------------------------===//
41 // Utility functions
42
43 /// getAsCString - Return the specified array as a C compatible string, only
44 /// if the predicate isString() is true.
45 ///
46 std::string getAsCString(const ConstantArray *CVA) {
47 assert(CVA->isString() && "Array is not string compatible!");
48
49 std::string Result = "\"";
50 for (unsigned i = 0; i != CVA->getNumOperands(); ++i) {
51 unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
52
53 if (C == '"') {
54 Result += "\\\"";
55 } else if (C == '\\') {
56 Result += "\\\\";
57 } else if (isprint(C)) {
58 Result += C;
59 } else {
60 Result += '\\'; // print all other chars as octal value
61 // Convert C to octal representation
62 Result += ((C >> 6) & 7) + '0';
63 Result += ((C >> 3) & 7) + '0';
64 Result += ((C >> 0) & 7) + '0';
65 }
66 }
67 Result += "\"";
68
69 return Result;
70 }
71
72 inline bool ArrayTypeIsString(const ArrayType* arrayType) {
73 return (arrayType->getElementType() == Type::UByteTy ||
74 arrayType->getElementType() == Type::SByteTy);
75 }
76
77 unsigned findOptimalStorageSize(const TargetMachine &TM, const Type *Ty) {
78 // All integer types smaller than ints promote to 4 byte integers.
79 if (Ty->isIntegral() && Ty->getPrimitiveSize() < 4)
80 return 4;
81
82 return TM.getTargetData().getTypeSize(Ty);
83 }
84
85
86 inline const std::string
87 TypeToDataDirective(const Type* type) {
88 switch(type->getTypeID()) {
89 case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
90 return ".byte";
91 case Type::UShortTyID: case Type::ShortTyID:
92 return ".half";
93 case Type::UIntTyID: case Type::IntTyID:
94 return ".word";
95 case Type::ULongTyID: case Type::LongTyID: case Type::PointerTyID:
96 return ".xword";
97 case Type::FloatTyID:
98 return ".word";
99 case Type::DoubleTyID:
100 return ".xword";
101 case Type::ArrayTyID:
102 if (ArrayTypeIsString((ArrayType*) type))
103 return ".ascii";
104 else
105 return "<InvaliDataTypeForPrinting>";
106 default:
107 return "<InvaliDataTypeForPrinting>";
108 }
109 }
110
111 /// Get the size of the constant for the given target.
112 /// If this is an unsized array, return 0.
113 ///
114 inline unsigned int
115 ConstantToSize(const Constant* CV, const TargetMachine& target) {
116 if (const ConstantArray* CVA = dyn_cast<ConstantArray>(CV)) {
117 const ArrayType *aty = cast<ArrayType>(CVA->getType());
118 if (ArrayTypeIsString(aty))
119 return 1 + CVA->getNumOperands();
120 }
121
122 return findOptimalStorageSize(target, CV->getType());
123 }
124
125 /// Align data larger than one L1 cache line on L1 cache line boundaries.
126 /// Align all smaller data on the next higher 2^x boundary (4, 8, ...).
127 ///
128 inline unsigned int
129 SizeToAlignment(unsigned int size, const TargetMachine& target) {
130 const unsigned short cacheLineSize = 16;
131 if (size > (unsigned) cacheLineSize / 2)
132 return cacheLineSize;
133 else
134 for (unsigned sz=1; /*no condition*/; sz *= 2)
135 if (sz >= size)
136 return sz;
137 }
138
139 /// Get the size of the type and then use SizeToAlignment.
140 ///
141 inline unsigned int
142 TypeToAlignment(const Type* type, const TargetMachine& target) {
143 return SizeToAlignment(findOptimalStorageSize(target, type), target);
144 }
145
146 /// Get the size of the constant and then use SizeToAlignment.
147 /// Handles strings as a special case;
148 inline unsigned int
149 ConstantToAlignment(const Constant* CV, const TargetMachine& target) {
150 if (const ConstantArray* CVA = dyn_cast<ConstantArray>(CV))
151 if (ArrayTypeIsString(cast<ArrayType>(CVA->getType())))
152 return SizeToAlignment(1 + CVA->getNumOperands(), target);
153
154 return TypeToAlignment(CV->getType(), target);
155 }
156
157} // End anonymous namespace
Vikram S. Adve270f56a2002-03-18 03:07:26 +0000158
Misha Brukman6675f982003-11-13 00:22:19 +0000159namespace {
Brian Gaeke86584742004-09-10 18:01:45 +0000160 enum Sections {
161 Unknown,
162 Text,
163 ReadOnlyData,
164 InitRWData,
165 ZeroInitRWData,
166 };
167
168 class AsmPrinter {
169 // Mangle symbol names appropriately
170 Mangler *Mang;
171
Misha Brukman6675f982003-11-13 00:22:19 +0000172 public:
Brian Gaeke86584742004-09-10 18:01:45 +0000173 std::ostream &O;
174 const TargetMachine &TM;
Misha Brukman6675f982003-11-13 00:22:19 +0000175
Brian Gaeke86584742004-09-10 18:01:45 +0000176 enum Sections CurSection;
177
178 AsmPrinter(std::ostream &os, const TargetMachine &T)
179 : /* idTable(0), */ O(os), TM(T), CurSection(Unknown) {}
180
181 ~AsmPrinter() {
182 delete Mang;
Misha Brukman929d1d12004-01-15 22:44:19 +0000183 }
184
Brian Gaeke86584742004-09-10 18:01:45 +0000185 // (start|end)(Module|Function) - Callback methods invoked by subclasses
186 void startModule(Module &M) {
187 Mang = new Mangler(M);
Misha Brukman2133b052003-11-07 17:45:28 +0000188 }
Misha Brukman2133b052003-11-07 17:45:28 +0000189
Brian Gaeke86584742004-09-10 18:01:45 +0000190 void PrintZeroBytesToPad(int numBytes) {
191 //
192 // Always use single unsigned bytes for padding. We don't know upon
193 // what data size the beginning address is aligned, so using anything
194 // other than a byte may cause alignment errors in the assembler.
195 //
196 while (numBytes--)
197 printSingleConstantValue(Constant::getNullValue(Type::UByteTy));
198 }
199
200 /// Print a single constant value.
201 ///
202 void printSingleConstantValue(const Constant* CV);
203
204 /// Print a constant value or values (it may be an aggregate).
205 /// Uses printSingleConstantValue() to print each individual value.
206 ///
207 void printConstantValueOnly(const Constant* CV, int numPadBytesAfter = 0);
208
Misha Brukman6675f982003-11-13 00:22:19 +0000209 // Print a constant (which may be an aggregate) prefixed by all the
210 // appropriate directives. Uses printConstantValueOnly() to print the
211 // value or values.
Brian Gaeke86584742004-09-10 18:01:45 +0000212 void printConstant(const Constant* CV, std::string valID = "") {
213 if (valID.length() == 0)
214 valID = getID(CV);
215
216 O << "\t.align\t" << ConstantToAlignment(CV, TM) << "\n";
217
218 // Print .size and .type only if it is not a string.
219 if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV))
220 if (CVA->isString()) {
221 // print it as a string and return
222 O << valID << ":\n";
223 O << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n";
224 return;
225 }
226
Chris Lattner12754fe2004-08-18 05:29:08 +0000227 O << "\t.type" << "\t" << valID << ",#object\n";
Misha Brukman6675f982003-11-13 00:22:19 +0000228
Brian Gaeke86584742004-09-10 18:01:45 +0000229 unsigned int constSize = ConstantToSize(CV, TM);
230 if (constSize)
231 O << "\t.size" << "\t" << valID << "," << constSize << "\n";
Misha Brukman6675f982003-11-13 00:22:19 +0000232
Chris Lattner12754fe2004-08-18 05:29:08 +0000233 O << valID << ":\n";
Misha Brukman6675f982003-11-13 00:22:19 +0000234
Brian Gaeke86584742004-09-10 18:01:45 +0000235 printConstantValueOnly(CV);
Misha Brukman6675f982003-11-13 00:22:19 +0000236 }
237
Misha Brukman6675f982003-11-13 00:22:19 +0000238 // enterSection - Use this method to enter a different section of the output
239 // executable. This is used to only output necessary section transitions.
240 //
241 void enterSection(enum Sections S) {
242 if (S == CurSection) return; // Only switch section if necessary
243 CurSection = S;
Misha Brukman2133b052003-11-07 17:45:28 +0000244
Chris Lattner12754fe2004-08-18 05:29:08 +0000245 O << "\n\t.section ";
Misha Brukman6675f982003-11-13 00:22:19 +0000246 switch (S)
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000247 {
248 default: assert(0 && "Bad section name!");
Chris Lattner12754fe2004-08-18 05:29:08 +0000249 case Text: O << "\".text\""; break;
250 case ReadOnlyData: O << "\".rodata\",#alloc"; break;
251 case InitRWData: O << "\".data\",#alloc,#write"; break;
252 case ZeroInitRWData: O << "\".bss\",#alloc,#write"; break;
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000253 }
Chris Lattner12754fe2004-08-18 05:29:08 +0000254 O << "\n";
Misha Brukman6675f982003-11-13 00:22:19 +0000255 }
Chris Lattner036a3172001-09-19 13:47:27 +0000256
Misha Brukman929d1d12004-01-15 22:44:19 +0000257 // getID Wrappers - Ensure consistent usage
Brian Gaeke94e95d22004-02-25 18:44:15 +0000258 // Symbol names in SparcV9 assembly language have these rules:
Misha Brukman929d1d12004-01-15 22:44:19 +0000259 // (a) Must match { letter | _ | . | $ } { letter | _ | . | $ | digit }*
260 // (b) A name beginning in "." is treated as a local name.
Misha Brukman6675f982003-11-13 00:22:19 +0000261 std::string getID(const Function *F) {
Misha Brukman929d1d12004-01-15 22:44:19 +0000262 return Mang->getValueName(F);
Misha Brukman6675f982003-11-13 00:22:19 +0000263 }
264 std::string getID(const BasicBlock *BB) {
Misha Brukman929d1d12004-01-15 22:44:19 +0000265 return ".L_" + getID(BB->getParent()) + "_" + Mang->getValueName(BB);
Misha Brukman6675f982003-11-13 00:22:19 +0000266 }
267 std::string getID(const GlobalVariable *GV) {
Misha Brukman929d1d12004-01-15 22:44:19 +0000268 return Mang->getValueName(GV);
Misha Brukman6675f982003-11-13 00:22:19 +0000269 }
270 std::string getID(const Constant *CV) {
Misha Brukman929d1d12004-01-15 22:44:19 +0000271 return ".C_" + Mang->getValueName(CV);
Misha Brukman6675f982003-11-13 00:22:19 +0000272 }
273 std::string getID(const GlobalValue *GV) {
274 if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV))
275 return getID(V);
276 else if (const Function *F = dyn_cast<Function>(GV))
277 return getID(F);
278 assert(0 && "Unexpected type of GlobalValue!");
279 return "";
280 }
Vikram S. Advec3a5e4e2002-08-22 02:58:36 +0000281
Brian Gaeke86584742004-09-10 18:01:45 +0000282 // Combines expressions
283 inline std::string ConstantArithExprToString(const ConstantExpr* CE,
284 const TargetMachine &TM,
285 const std::string &op) {
286 return "(" + valToExprString(CE->getOperand(0), TM) + op
287 + valToExprString(CE->getOperand(1), TM) + ")";
288 }
289
290 /// ConstantExprToString() - Convert a ConstantExpr to an asm expression
291 /// and return this as a string.
292 ///
293 std::string ConstantExprToString(const ConstantExpr* CE,
294 const TargetMachine& target);
295
296 /// valToExprString - Helper function for ConstantExprToString().
297 /// Appends result to argument string S.
298 ///
299 std::string valToExprString(const Value* V, const TargetMachine& target);
300 };
301} // End anonymous namespace
302
303
304/// Print a single constant value.
305///
306void AsmPrinter::printSingleConstantValue(const Constant* CV) {
307 assert(CV->getType() != Type::VoidTy &&
308 CV->getType() != Type::LabelTy &&
309 "Unexpected type for Constant");
310
311 assert((!isa<ConstantArray>(CV) && ! isa<ConstantStruct>(CV))
312 && "Aggregate types should be handled outside this function");
313
314 O << "\t" << TypeToDataDirective(CV->getType()) << "\t";
315
316 if (const GlobalValue* GV = dyn_cast<GlobalValue>(CV)) {
317 O << getID(GV) << "\n";
Chris Lattnerea9a85a2004-10-16 18:14:10 +0000318 } else if (isa<ConstantPointerNull>(CV) || isa<UndefValue>(CV)) {
Brian Gaeke86584742004-09-10 18:01:45 +0000319 // Null pointer value
320 O << "0\n";
321 } else if (const ConstantExpr* CE = dyn_cast<ConstantExpr>(CV)) {
322 // Constant expression built from operators, constants, and symbolic addrs
323 O << ConstantExprToString(CE, TM) << "\n";
324 } else if (CV->getType()->isPrimitiveType()) {
325 // Check primitive types last
Chris Lattnerf6666db2004-10-17 02:44:45 +0000326 if (isa<UndefValue>(CV)) {
327 O << "0\n";
328 } else if (CV->getType()->isFloatingPoint()) {
Brian Gaeke86584742004-09-10 18:01:45 +0000329 // FP Constants are printed as integer constants to avoid losing
330 // precision...
331 double Val = cast<ConstantFP>(CV)->getValue();
332 if (CV->getType() == Type::FloatTy) {
333 float FVal = (float)Val;
334 char *ProxyPtr = (char*)&FVal; // Abide by C TBAA rules
335 O << *(unsigned int*)ProxyPtr;
336 } else if (CV->getType() == Type::DoubleTy) {
337 char *ProxyPtr = (char*)&Val; // Abide by C TBAA rules
338 O << *(uint64_t*)ProxyPtr;
339 } else {
340 assert(0 && "Unknown floating point type!");
341 }
342
343 O << "\t! " << CV->getType()->getDescription()
344 << " value: " << Val << "\n";
345 } else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
346 O << (int)CB->getValue() << "\n";
347 } else {
348 WriteAsOperand(O, CV, false, false) << "\n";
349 }
350 } else {
351 assert(0 && "Unknown elementary type for constant");
352 }
353}
354
355/// Print a constant value or values (it may be an aggregate).
356/// Uses printSingleConstantValue() to print each individual value.
357///
358void AsmPrinter::printConstantValueOnly(const Constant* CV,
359 int numPadBytesAfter) {
360 if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
361 if (CVA->isString()) {
362 // print the string alone and return
363 O << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n";
364 } else {
365 // Not a string. Print the values in successive locations
366 for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
367 printConstantValueOnly(CVA->getOperand(i));
368 }
369 } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
370 // Print the fields in successive locations. Pad to align if needed!
371 const StructLayout *cvsLayout =
372 TM.getTargetData().getStructLayout(CVS->getType());
373 unsigned sizeSoFar = 0;
374 for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
375 const Constant* field = CVS->getOperand(i);
376
377 // Check if padding is needed and insert one or more 0s.
378 unsigned fieldSize =
379 TM.getTargetData().getTypeSize(field->getType());
380 int padSize = ((i == e-1? cvsLayout->StructSize
381 : cvsLayout->MemberOffsets[i+1])
382 - cvsLayout->MemberOffsets[i]) - fieldSize;
383 sizeSoFar += (fieldSize + padSize);
384
385 // Now print the actual field value
386 printConstantValueOnly(field, padSize);
387 }
388 assert(sizeSoFar == cvsLayout->StructSize &&
389 "Layout of constant struct may be incorrect!");
Chris Lattnerf6666db2004-10-17 02:44:45 +0000390 } else if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV)) {
Brian Gaeke86584742004-09-10 18:01:45 +0000391 PrintZeroBytesToPad(TM.getTargetData().getTypeSize(CV->getType()));
392 } else
393 printSingleConstantValue(CV);
394
395 if (numPadBytesAfter)
396 PrintZeroBytesToPad(numPadBytesAfter);
397}
398
399/// ConstantExprToString() - Convert a ConstantExpr to an asm expression
400/// and return this as a string.
401///
402std::string AsmPrinter::ConstantExprToString(const ConstantExpr* CE,
403 const TargetMachine& target) {
404 std::string S;
405 switch(CE->getOpcode()) {
406 case Instruction::GetElementPtr:
407 { // generate a symbolic expression for the byte address
408 const Value* ptrVal = CE->getOperand(0);
409 std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
410 const TargetData &TD = target.getTargetData();
411 S += "(" + valToExprString(ptrVal, target) + ") + ("
412 + utostr(TD.getIndexedOffset(ptrVal->getType(),idxVec)) + ")";
413 break;
414 }
415
416 case Instruction::Cast:
417 // Support only non-converting casts for now, i.e., a no-op.
418 // This assertion is not a complete check.
419 assert(target.getTargetData().getTypeSize(CE->getType()) ==
420 target.getTargetData().getTypeSize(CE->getOperand(0)->getType()));
421 S += "(" + valToExprString(CE->getOperand(0), target) + ")";
422 break;
423
424 case Instruction::Add:
425 S += ConstantArithExprToString(CE, target, ") + (");
426 break;
427
428 case Instruction::Sub:
429 S += ConstantArithExprToString(CE, target, ") - (");
430 break;
431
432 case Instruction::Mul:
433 S += ConstantArithExprToString(CE, target, ") * (");
434 break;
435
436 case Instruction::Div:
437 S += ConstantArithExprToString(CE, target, ") / (");
438 break;
439
440 case Instruction::Rem:
441 S += ConstantArithExprToString(CE, target, ") % (");
442 break;
443
444 case Instruction::And:
445 // Logical && for booleans; bitwise & otherwise
446 S += ConstantArithExprToString(CE, target,
447 ((CE->getType() == Type::BoolTy)? ") && (" : ") & ("));
448 break;
449
450 case Instruction::Or:
451 // Logical || for booleans; bitwise | otherwise
452 S += ConstantArithExprToString(CE, target,
453 ((CE->getType() == Type::BoolTy)? ") || (" : ") | ("));
454 break;
455
456 case Instruction::Xor:
457 // Bitwise ^ for all types
458 S += ConstantArithExprToString(CE, target, ") ^ (");
459 break;
460
461 default:
462 assert(0 && "Unsupported operator in ConstantExprToString()");
463 break;
464 }
465
466 return S;
467}
468
469/// valToExprString - Helper function for ConstantExprToString().
470/// Appends result to argument string S.
471///
472std::string AsmPrinter::valToExprString(const Value* V,
473 const TargetMachine& target) {
474 std::string S;
475 bool failed = false;
476 if (const GlobalValue* GV = dyn_cast<GlobalValue>(V)) {
477 S += getID(GV);
478 } else if (const Constant* CV = dyn_cast<Constant>(V)) { // symbolic or known
479 if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV))
480 S += std::string(CB == ConstantBool::True ? "1" : "0");
481 else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
482 S += itostr(CI->getValue());
483 else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
484 S += utostr(CI->getValue());
485 else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))
486 S += ftostr(CFP->getValue());
Chris Lattnerea9a85a2004-10-16 18:14:10 +0000487 else if (isa<ConstantPointerNull>(CV) || isa<UndefValue>(CV))
Brian Gaeke86584742004-09-10 18:01:45 +0000488 S += "0";
489 else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV))
490 S += ConstantExprToString(CE, target);
491 else
492 failed = true;
493 } else
494 failed = true;
495
496 if (failed) {
497 assert(0 && "Cannot convert value to string");
498 S += "<illegal-value>";
499 }
500 return S;
501}
502
503namespace {
504
505 struct SparcV9AsmPrinter : public FunctionPass, public AsmPrinter {
506 inline SparcV9AsmPrinter(std::ostream &os, const TargetMachine &t)
507 : AsmPrinter(os, t) {}
508
509 const Function *currFunction;
510
511 const char *getPassName() const {
512 return "Output SparcV9 Assembly for Functions";
513 }
514
515 virtual bool doInitialization(Module &M) {
516 startModule(M);
517 return false;
518 }
519
520 virtual bool runOnFunction(Function &F) {
521 currFunction = &F;
522 emitFunction(F);
Misha Brukman6675f982003-11-13 00:22:19 +0000523 return false;
524 }
525
526 virtual bool doFinalization(Module &M) {
527 emitGlobals(M);
528 return false;
529 }
530
Brian Gaeke86584742004-09-10 18:01:45 +0000531 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
532 AU.setPreservesAll();
533 }
534
535 void emitFunction(const Function &F);
Misha Brukman6675f982003-11-13 00:22:19 +0000536 private :
537 void emitBasicBlock(const MachineBasicBlock &MBB);
538 void emitMachineInst(const MachineInstr *MI);
539
540 unsigned int printOperands(const MachineInstr *MI, unsigned int opNum);
541 void printOneOperand(const MachineOperand &Op, MachineOpCode opCode);
542
543 bool OpIsBranchTargetLabel(const MachineInstr *MI, unsigned int opNum);
544 bool OpIsMemoryAddressBase(const MachineInstr *MI, unsigned int opNum);
545
546 unsigned getOperandMask(unsigned Opcode) {
547 switch (Opcode) {
548 case V9::SUBccr:
549 case V9::SUBcci: return 1 << 3; // Remove CC argument
550 default: return 0; // By default, don't hack operands...
551 }
552 }
553
554 void emitGlobals(const Module &M);
555 void printGlobalVariable(const GlobalVariable *GV);
556 };
557
558} // End anonymous namespace
Chris Lattner036a3172001-09-19 13:47:27 +0000559
Chris Lattnerd6820452002-02-03 23:41:08 +0000560inline bool
Brian Gaeke94e95d22004-02-25 18:44:15 +0000561SparcV9AsmPrinter::OpIsBranchTargetLabel(const MachineInstr *MI,
Misha Brukman6675f982003-11-13 00:22:19 +0000562 unsigned int opNum) {
Brian Gaekeb22186a2004-02-11 20:47:34 +0000563 switch (MI->getOpcode()) {
Misha Brukman8bde6a62003-05-27 22:35:43 +0000564 case V9::JMPLCALLr:
565 case V9::JMPLCALLi:
566 case V9::JMPLRETr:
567 case V9::JMPLRETi:
Misha Brukman56f4fa12003-05-20 20:32:24 +0000568 return (opNum == 0);
569 default:
570 return false;
Chris Lattnerd6820452002-02-03 23:41:08 +0000571 }
572}
573
Chris Lattnerd6820452002-02-03 23:41:08 +0000574inline bool
Brian Gaeke94e95d22004-02-25 18:44:15 +0000575SparcV9AsmPrinter::OpIsMemoryAddressBase(const MachineInstr *MI,
Misha Brukman6675f982003-11-13 00:22:19 +0000576 unsigned int opNum) {
Chris Lattner12754fe2004-08-18 05:29:08 +0000577 if (TM.getInstrInfo()->isLoad(MI->getOpcode()))
Chris Lattnerd6820452002-02-03 23:41:08 +0000578 return (opNum == 0);
Chris Lattner12754fe2004-08-18 05:29:08 +0000579 else if (TM.getInstrInfo()->isStore(MI->getOpcode()))
Chris Lattnerd6820452002-02-03 23:41:08 +0000580 return (opNum == 1);
581 else
582 return false;
583}
584
Chris Lattnerd6820452002-02-03 23:41:08 +0000585unsigned int
Chris Lattner12754fe2004-08-18 05:29:08 +0000586SparcV9AsmPrinter::printOperands(const MachineInstr *MI, unsigned opNum) {
Vikram S. Adve4e1ee142002-07-10 21:41:21 +0000587 const MachineOperand& mop = MI->getOperand(opNum);
Misha Brukman6675f982003-11-13 00:22:19 +0000588 if (OpIsBranchTargetLabel(MI, opNum)) {
Chris Lattner12754fe2004-08-18 05:29:08 +0000589 printOneOperand(mop, MI->getOpcode());
590 O << "+";
591 printOneOperand(MI->getOperand(opNum+1), MI->getOpcode());
Misha Brukman6675f982003-11-13 00:22:19 +0000592 return 2;
593 } else if (OpIsMemoryAddressBase(MI, opNum)) {
Chris Lattner12754fe2004-08-18 05:29:08 +0000594 O << "[";
595 printOneOperand(mop, MI->getOpcode());
596 O << "+";
597 printOneOperand(MI->getOperand(opNum+1), MI->getOpcode());
598 O << "]";
Misha Brukman6675f982003-11-13 00:22:19 +0000599 return 2;
600 } else {
Brian Gaekeb22186a2004-02-11 20:47:34 +0000601 printOneOperand(mop, MI->getOpcode());
Misha Brukman6675f982003-11-13 00:22:19 +0000602 return 1;
603 }
Chris Lattnerd6820452002-02-03 23:41:08 +0000604}
605
Chris Lattnerd6820452002-02-03 23:41:08 +0000606void
Brian Gaeke94e95d22004-02-25 18:44:15 +0000607SparcV9AsmPrinter::printOneOperand(const MachineOperand &mop,
Chris Lattner12754fe2004-08-18 05:29:08 +0000608 MachineOpCode opCode)
Chris Lattnerd6820452002-02-03 23:41:08 +0000609{
Vikram S. Adve4e1ee142002-07-10 21:41:21 +0000610 bool needBitsFlag = true;
611
Alkis Evlogimenosaaba4632003-12-14 13:24:17 +0000612 if (mop.isHiBits32())
Chris Lattner12754fe2004-08-18 05:29:08 +0000613 O << "%lm(";
Alkis Evlogimenosaaba4632003-12-14 13:24:17 +0000614 else if (mop.isLoBits32())
Chris Lattner12754fe2004-08-18 05:29:08 +0000615 O << "%lo(";
Alkis Evlogimenosaaba4632003-12-14 13:24:17 +0000616 else if (mop.isHiBits64())
Chris Lattner12754fe2004-08-18 05:29:08 +0000617 O << "%hh(";
Alkis Evlogimenosaaba4632003-12-14 13:24:17 +0000618 else if (mop.isLoBits64())
Chris Lattner12754fe2004-08-18 05:29:08 +0000619 O << "%hm(";
Vikram S. Adve4e1ee142002-07-10 21:41:21 +0000620 else
621 needBitsFlag = false;
622
Chris Lattner6a30b022002-10-28 04:45:29 +0000623 switch (mop.getType())
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000624 {
Vikram S. Adved09c4c32003-07-06 20:13:59 +0000625 case MachineOperand::MO_VirtualRegister:
Vikram S. Adve65280672003-07-10 19:42:11 +0000626 case MachineOperand::MO_CCRegister:
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000627 case MachineOperand::MO_MachineRegister:
628 {
Alkis Evlogimenos8cdd0212004-02-13 21:01:20 +0000629 int regNum = (int)mop.getReg();
Vikram S. Adve65280672003-07-10 19:42:11 +0000630
Chris Lattner12754fe2004-08-18 05:29:08 +0000631 if (regNum == TM.getRegInfo()->getInvalidRegNum()) {
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000632 // better to print code with NULL registers than to die
Chris Lattner12754fe2004-08-18 05:29:08 +0000633 O << "<NULL VALUE>";
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000634 } else {
Chris Lattner12754fe2004-08-18 05:29:08 +0000635 O << "%" << TM.getRegInfo()->getUnifiedRegName(regNum);
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000636 }
637 break;
638 }
Misha Brukman8d531672003-05-31 06:22:37 +0000639
Misha Brukman2133b052003-11-07 17:45:28 +0000640 case MachineOperand::MO_ConstantPoolIndex:
641 {
Brian Gaeke86584742004-09-10 18:01:45 +0000642 O << ".CPI_" << getID(currFunction)
643 << "_" << mop.getConstantPoolIndex();
Misha Brukman2133b052003-11-07 17:45:28 +0000644 break;
645 }
646
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000647 case MachineOperand::MO_PCRelativeDisp:
648 {
649 const Value *Val = mop.getVRegValue();
Brian Gaeke94e95d22004-02-25 18:44:15 +0000650 assert(Val && "\tNULL Value in SparcV9AsmPrinter");
Misha Brukman8d531672003-05-31 06:22:37 +0000651
Chris Lattnerf26a8ee2003-07-23 15:30:06 +0000652 if (const BasicBlock *BB = dyn_cast<BasicBlock>(Val))
Chris Lattner12754fe2004-08-18 05:29:08 +0000653 O << getID(BB);
Brian Gaekef2ff5dd2004-05-04 21:09:02 +0000654 else if (const Function *F = dyn_cast<Function>(Val))
Chris Lattner12754fe2004-08-18 05:29:08 +0000655 O << getID(F);
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000656 else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Val))
Chris Lattner12754fe2004-08-18 05:29:08 +0000657 O << getID(GV);
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000658 else if (const Constant *CV = dyn_cast<Constant>(Val))
Chris Lattner12754fe2004-08-18 05:29:08 +0000659 O << getID(CV);
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000660 else
Brian Gaeke94e95d22004-02-25 18:44:15 +0000661 assert(0 && "Unrecognized value in SparcV9AsmPrinter");
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000662 break;
663 }
Misha Brukman8d531672003-05-31 06:22:37 +0000664
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000665 case MachineOperand::MO_SignExtendedImmed:
Chris Lattner12754fe2004-08-18 05:29:08 +0000666 O << mop.getImmedValue();
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000667 break;
Misha Brukman8d531672003-05-31 06:22:37 +0000668
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000669 case MachineOperand::MO_UnextendedImmed:
Chris Lattner12754fe2004-08-18 05:29:08 +0000670 O << (uint64_t) mop.getImmedValue();
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000671 break;
Misha Brukman8d531672003-05-31 06:22:37 +0000672
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000673 default:
Chris Lattner12754fe2004-08-18 05:29:08 +0000674 O << mop; // use dump field
Vikram S. Adve96b801a2003-05-31 07:27:17 +0000675 break;
676 }
Vikram S. Adve4e1ee142002-07-10 21:41:21 +0000677
678 if (needBitsFlag)
Chris Lattner12754fe2004-08-18 05:29:08 +0000679 O << ")";
Chris Lattnerd6820452002-02-03 23:41:08 +0000680}
681
Brian Gaeke94e95d22004-02-25 18:44:15 +0000682void SparcV9AsmPrinter::emitMachineInst(const MachineInstr *MI) {
Brian Gaekeb22186a2004-02-11 20:47:34 +0000683 unsigned Opcode = MI->getOpcode();
Chris Lattnerd6820452002-02-03 23:41:08 +0000684
Brian Gaeke75935252004-08-18 20:04:24 +0000685 if (Opcode == V9::PHI)
686 return; // Ignore Machine-PHI nodes.
Chris Lattnerd6820452002-02-03 23:41:08 +0000687
Chris Lattner12754fe2004-08-18 05:29:08 +0000688 O << "\t" << TM.getInstrInfo()->getName(Opcode) << "\t";
Chris Lattnerd6820452002-02-03 23:41:08 +0000689
690 unsigned Mask = getOperandMask(Opcode);
691
692 bool NeedComma = false;
693 unsigned N = 1;
694 for (unsigned OpNum = 0; OpNum < MI->getNumOperands(); OpNum += N)
695 if (! ((1 << OpNum) & Mask)) { // Ignore this operand?
Chris Lattner12754fe2004-08-18 05:29:08 +0000696 if (NeedComma) O << ", "; // Handle comma outputting
Chris Lattnerd6820452002-02-03 23:41:08 +0000697 NeedComma = true;
698 N = printOperands(MI, OpNum);
Chris Lattner59611022002-11-17 22:57:23 +0000699 } else
700 N = 1;
Chris Lattnerd6820452002-02-03 23:41:08 +0000701
Chris Lattner12754fe2004-08-18 05:29:08 +0000702 O << "\n";
Brian Gaeke4547ab12003-10-06 15:41:21 +0000703 ++EmittedInsts;
Chris Lattnerd6820452002-02-03 23:41:08 +0000704}
705
Brian Gaeke94e95d22004-02-25 18:44:15 +0000706void SparcV9AsmPrinter::emitBasicBlock(const MachineBasicBlock &MBB) {
Chris Lattnerd6820452002-02-03 23:41:08 +0000707 // Emit a label for the basic block
Chris Lattner12754fe2004-08-18 05:29:08 +0000708 O << getID(MBB.getBasicBlock()) << ":\n";
Chris Lattnerd6820452002-02-03 23:41:08 +0000709
710 // Loop over all of the instructions in the basic block...
Misha Brukman181ea4a2002-10-28 20:01:13 +0000711 for (MachineBasicBlock::const_iterator MII = MBB.begin(), MIE = MBB.end();
Chris Lattner8710aab2002-10-28 01:41:47 +0000712 MII != MIE; ++MII)
Alkis Evlogimenos80da8652004-02-12 02:27:10 +0000713 emitMachineInst(MII);
Chris Lattner12754fe2004-08-18 05:29:08 +0000714 O << "\n"; // Separate BB's with newlines
Chris Lattnerd6820452002-02-03 23:41:08 +0000715}
716
Brian Gaeke86584742004-09-10 18:01:45 +0000717void SparcV9AsmPrinter::emitFunction(const Function &F) {
718 std::string CurrentFnName = getID(&F);
719 MachineFunction &MF = MachineFunction::get(&F);
Chris Lattner12754fe2004-08-18 05:29:08 +0000720 O << "!****** Outputing Function: " << CurrentFnName << " ******\n";
Misha Brukman2133b052003-11-07 17:45:28 +0000721
722 // Emit constant pool for this function
Chris Lattner12754fe2004-08-18 05:29:08 +0000723 const MachineConstantPool *MCP = MF.getConstantPool();
Misha Brukman2133b052003-11-07 17:45:28 +0000724 const std::vector<Constant*> &CP = MCP->getConstants();
725
Chris Lattner12754fe2004-08-18 05:29:08 +0000726 enterSection(ReadOnlyData);
Misha Brukman2133b052003-11-07 17:45:28 +0000727 for (unsigned i = 0, e = CP.size(); i != e; ++i) {
Chris Lattner12754fe2004-08-18 05:29:08 +0000728 std::string cpiName = ".CPI_" + CurrentFnName + "_" + utostr(i);
Misha Brukman2133b052003-11-07 17:45:28 +0000729 printConstant(CP[i], cpiName);
730 }
731
Chris Lattner12754fe2004-08-18 05:29:08 +0000732 enterSection(Text);
733 O << "\t.align\t4\n\t.global\t" << CurrentFnName << "\n";
734 //O << "\t.type\t" << CurrentFnName << ",#function\n";
735 O << "\t.type\t" << CurrentFnName << ", 2\n";
736 O << CurrentFnName << ":\n";
Chris Lattnerd6820452002-02-03 23:41:08 +0000737
Chris Lattner62b7fd12002-04-07 20:49:59 +0000738 // Output code for all of the basic blocks in the function...
Chris Lattner4d84d492002-12-28 20:15:01 +0000739 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E;++I)
Misha Brukman181ea4a2002-10-28 20:01:13 +0000740 emitBasicBlock(*I);
Chris Lattnerd6820452002-02-03 23:41:08 +0000741
742 // Output a .size directive so the debugger knows the extents of the function
Chris Lattner12754fe2004-08-18 05:29:08 +0000743 O << ".EndOf_" << CurrentFnName << ":\n\t.size "
744 << CurrentFnName << ", .EndOf_"
745 << CurrentFnName << "-" << CurrentFnName << "\n";
Chris Lattnerd6820452002-02-03 23:41:08 +0000746
Chris Lattner62b7fd12002-04-07 20:49:59 +0000747 // Put some spaces between the functions
Chris Lattner12754fe2004-08-18 05:29:08 +0000748 O << "\n\n";
Chris Lattnerd6820452002-02-03 23:41:08 +0000749}
750
Brian Gaeke94e95d22004-02-25 18:44:15 +0000751void SparcV9AsmPrinter::printGlobalVariable(const GlobalVariable* GV) {
Vikram S. Adve8cbdbd82002-09-16 15:54:02 +0000752 if (GV->hasExternalLinkage())
Chris Lattner12754fe2004-08-18 05:29:08 +0000753 O << "\t.global\t" << getID(GV) << "\n";
Vikram S. Adve71b265a2001-10-28 21:38:52 +0000754
Chris Lattnerea9a85a2004-10-16 18:14:10 +0000755 if (GV->hasInitializer() &&
756 !(GV->getInitializer()->isNullValue() ||
757 isa<UndefValue>(GV->getInitializer()))) {
Vikram S. Adve71b265a2001-10-28 21:38:52 +0000758 printConstant(GV->getInitializer(), getID(GV));
Misha Brukman6675f982003-11-13 00:22:19 +0000759 } else {
Brian Gaeke86584742004-09-10 18:01:45 +0000760 O << "\t.align\t" << TypeToAlignment(GV->getType()->getElementType(),
761 TM) << "\n";
Chris Lattner12754fe2004-08-18 05:29:08 +0000762 O << "\t.type\t" << getID(GV) << ",#object\n";
763 O << "\t.reserve\t" << getID(GV) << ","
Brian Gaeke86584742004-09-10 18:01:45 +0000764 << findOptimalStorageSize(TM, GV->getType()->getElementType())
Chris Lattner12754fe2004-08-18 05:29:08 +0000765 << "\n";
Vikram S. Adve71b265a2001-10-28 21:38:52 +0000766 }
767}
768
Brian Gaeke94e95d22004-02-25 18:44:15 +0000769void SparcV9AsmPrinter::emitGlobals(const Module &M) {
Chris Lattnerc93df6b2002-08-07 21:39:48 +0000770 // Output global variables...
Vikram S. Adve10d81642002-10-13 00:32:18 +0000771 for (Module::const_giterator GI = M.gbegin(), GE = M.gend(); GI != GE; ++GI)
772 if (! GI->isExternal()) {
773 assert(GI->hasInitializer());
774 if (GI->isConstant())
Chris Lattner12754fe2004-08-18 05:29:08 +0000775 enterSection(ReadOnlyData); // read-only, initialized data
Chris Lattnerea9a85a2004-10-16 18:14:10 +0000776 else if (GI->getInitializer()->isNullValue() ||
777 isa<UndefValue>(GI->getInitializer()))
Chris Lattner12754fe2004-08-18 05:29:08 +0000778 enterSection(ZeroInitRWData); // read-write zero data
Vikram S. Adve10d81642002-10-13 00:32:18 +0000779 else
Chris Lattner12754fe2004-08-18 05:29:08 +0000780 enterSection(InitRWData); // read-write non-zero data
Vikram S. Adve10d81642002-10-13 00:32:18 +0000781
782 printGlobalVariable(GI);
Chris Lattnerc93df6b2002-08-07 21:39:48 +0000783 }
Chris Lattnerc93df6b2002-08-07 21:39:48 +0000784
Chris Lattner12754fe2004-08-18 05:29:08 +0000785 O << "\n";
Vikram S. Adve71b265a2001-10-28 21:38:52 +0000786}
787
Chris Lattner12754fe2004-08-18 05:29:08 +0000788FunctionPass *llvm::createAsmPrinterPass(std::ostream &Out, TargetMachine &TM) {
Brian Gaeke94e95d22004-02-25 18:44:15 +0000789 return new SparcV9AsmPrinter(Out, TM);
Chris Lattnere772d282002-02-03 07:48:06 +0000790}