blob: 6af9836e29b6a35ced2f962dbde5062e044c0273 [file] [log] [blame]
Chris Lattnere88f78c2001-09-19 13:47:27 +00001//===-- EmitAssembly.cpp - Emit Sparc Specific .s File ---------------------==//
John Criswellb576c942003-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 Lattnere88f78c2001-09-19 13:47:27 +00009//
Misha Brukman5560c9d2003-08-18 14:43:39 +000010// This file implements all of the stuff necessary to output a .s file from
Chris Lattnere88f78c2001-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 Lattnerf57b8452002-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 Lattnere88f78c2001-09-19 13:47:27 +000018//
19//===----------------------------------------------------------------------===//
20
Chris Lattnere88f78c2001-09-19 13:47:27 +000021#include "llvm/CodeGen/MachineInstr.h"
Misha Brukmanf905ed52003-11-07 17:45:28 +000022#include "llvm/CodeGen/MachineConstantPool.h"
Misha Brukmanfce11432002-10-28 00:28:31 +000023#include "llvm/CodeGen/MachineFunction.h"
Chris Lattnerd0fe5f52002-12-28 20:15:01 +000024#include "llvm/CodeGen/MachineFunctionInfo.h"
Chris Lattner31bcdb82002-04-28 19:55:58 +000025#include "llvm/Constants.h"
Vikram S. Adve953c83e2001-10-28 21:38:52 +000026#include "llvm/DerivedTypes.h"
Chris Lattnere88f78c2001-09-19 13:47:27 +000027#include "llvm/Module.h"
Chris Lattnerb5794002002-04-07 22:49:37 +000028#include "llvm/SlotCalculator.h"
Chris Lattnerd50b6712002-04-28 20:40:59 +000029#include "llvm/Pass.h"
Chris Lattner4b1de8e2002-04-18 18:15:38 +000030#include "llvm/Assembly/Writer.h"
Chris Lattnercee8f9a2001-11-27 00:03:19 +000031#include "Support/StringExtras.h"
Brian Gaeke2c9b9132003-10-06 15:41:21 +000032#include "Support/Statistic.h"
Misha Brukmanf4de7832003-08-05 16:01:50 +000033#include "SparcInternals.h"
34#include <string>
Chris Lattnere88f78c2001-09-19 13:47:27 +000035
Brian Gaeked0fde302003-11-11 22:41:34 +000036namespace llvm {
37
Chris Lattnere88f78c2001-09-19 13:47:27 +000038namespace {
39
Brian Gaeke2c9b9132003-10-06 15:41:21 +000040Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
41
Vikram S. Adved198c472002-03-18 03:07:26 +000042class GlobalIdTable: public Annotation {
43 static AnnotationID AnnotId;
44 friend class AsmPrinter; // give access to AnnotId
Vikram S. Adve953c83e2001-10-28 21:38:52 +000045
Chris Lattner09ff1122002-07-24 21:21:32 +000046 typedef hash_map<const Value*, int> ValIdMap;
Vikram S. Adved198c472002-03-18 03:07:26 +000047 typedef ValIdMap::const_iterator ValIdMapConstIterator;
48 typedef ValIdMap:: iterator ValIdMapIterator;
49public:
Chris Lattnerfd63f25f2002-04-28 04:50:54 +000050 SlotCalculator Table; // map anonymous values to unique integer IDs
Chris Lattnerc19b8b12002-02-03 23:41:08 +000051 ValIdMap valToIdMap; // used for values not handled by SlotCalculator
Vikram S. Adved198c472002-03-18 03:07:26 +000052
Chris Lattnerfd63f25f2002-04-28 04:50:54 +000053 GlobalIdTable(Module* M) : Annotation(AnnotId), Table(M, true) {}
Vikram S. Adved198c472002-03-18 03:07:26 +000054};
55
56AnnotationID GlobalIdTable::AnnotId =
57 AnnotationManager::getID("ASM PRINTER GLOBAL TABLE ANNOT");
Misha Brukmanf905ed52003-11-07 17:45:28 +000058
59// Can we treat the specified array as a string? Only if it is an array of
60// ubytes or non-negative sbytes.
61//
62static bool isStringCompatible(const ConstantArray *CVA) {
63 const Type *ETy = cast<ArrayType>(CVA->getType())->getElementType();
64 if (ETy == Type::UByteTy) return true;
65 if (ETy != Type::SByteTy) return false;
66
67 for (unsigned i = 0; i < CVA->getNumOperands(); ++i)
68 if (cast<ConstantSInt>(CVA->getOperand(i))->getValue() < 0)
69 return false;
70
71 return true;
72}
73
74// toOctal - Convert the low order bits of X into an octal letter
75static inline char toOctal(int X) {
76 return (X&7)+'0';
77}
78
79// getAsCString - Return the specified array as a C compatible string, only if
80// the predicate isStringCompatible is true.
81//
82static std::string getAsCString(const ConstantArray *CVA) {
83 assert(isStringCompatible(CVA) && "Array is not string compatible!");
84
85 std::string Result;
86 const Type *ETy = cast<ArrayType>(CVA->getType())->getElementType();
87 Result = "\"";
88 for (unsigned i = 0; i < CVA->getNumOperands(); ++i) {
89 unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
90
91 if (C == '"') {
92 Result += "\\\"";
93 } else if (C == '\\') {
94 Result += "\\\\";
95 } else if (isprint(C)) {
96 Result += C;
97 } else {
98 Result += '\\'; // print all other chars as octal value
99 Result += toOctal(C >> 6);
100 Result += toOctal(C >> 3);
101 Result += toOctal(C >> 0);
102 }
103 }
104 Result += "\"";
105
106 return Result;
107}
108
109inline bool
110ArrayTypeIsString(const ArrayType* arrayType)
111{
112 return (arrayType->getElementType() == Type::UByteTy ||
113 arrayType->getElementType() == Type::SByteTy);
114}
115
116
117inline const std::string
118TypeToDataDirective(const Type* type)
119{
120 switch(type->getPrimitiveID())
121 {
122 case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
123 return ".byte";
124 case Type::UShortTyID: case Type::ShortTyID:
125 return ".half";
126 case Type::UIntTyID: case Type::IntTyID:
127 return ".word";
128 case Type::ULongTyID: case Type::LongTyID: case Type::PointerTyID:
129 return ".xword";
130 case Type::FloatTyID:
131 return ".word";
132 case Type::DoubleTyID:
133 return ".xword";
134 case Type::ArrayTyID:
135 if (ArrayTypeIsString((ArrayType*) type))
136 return ".ascii";
137 else
138 return "<InvaliDataTypeForPrinting>";
139 default:
140 return "<InvaliDataTypeForPrinting>";
141 }
142}
143
144// Get the size of the type
145//
146inline unsigned int
147TypeToSize(const Type* type, const TargetMachine& target)
148{
149 return target.findOptimalStorageSize(type);
150}
151
152// Get the size of the constant for the given target.
153// If this is an unsized array, return 0.
154//
155inline unsigned int
156ConstantToSize(const Constant* CV, const TargetMachine& target)
157{
158 if (const ConstantArray* CVA = dyn_cast<ConstantArray>(CV))
159 {
160 const ArrayType *aty = cast<ArrayType>(CVA->getType());
161 if (ArrayTypeIsString(aty))
162 return 1 + CVA->getNumOperands();
163 }
164
165 return TypeToSize(CV->getType(), target);
166}
167
168// Align data larger than one L1 cache line on L1 cache line boundaries.
169// Align all smaller data on the next higher 2^x boundary (4, 8, ...).
170//
171inline unsigned int
172SizeToAlignment(unsigned int size, const TargetMachine& target)
173{
174 unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1);
175 if (size > (unsigned) cacheLineSize / 2)
176 return cacheLineSize;
177 else
178 for (unsigned sz=1; /*no condition*/; sz *= 2)
179 if (sz >= size)
180 return sz;
181}
182
183// Get the size of the type and then use SizeToAlignment.
184//
185inline unsigned int
186TypeToAlignment(const Type* type, const TargetMachine& target)
187{
188 return SizeToAlignment(TypeToSize(type, target), target);
189}
190
191// Get the size of the constant and then use SizeToAlignment.
192// Handles strings as a special case;
193inline unsigned int
194ConstantToAlignment(const Constant* CV, const TargetMachine& target)
195{
196 if (const ConstantArray* CVA = dyn_cast<ConstantArray>(CV))
197 if (ArrayTypeIsString(cast<ArrayType>(CVA->getType())))
198 return SizeToAlignment(1 + CVA->getNumOperands(), target);
199
200 return TypeToAlignment(CV->getType(), target);
201}
Vikram S. Adved198c472002-03-18 03:07:26 +0000202
203//===---------------------------------------------------------------------===//
204// Code Shared By the two printer passes, as a mixin
205//===---------------------------------------------------------------------===//
206
207class AsmPrinter {
208 GlobalIdTable* idTable;
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000209public:
Chris Lattner697954c2002-01-20 22:54:45 +0000210 std::ostream &toAsm;
Chris Lattner59ba1092002-02-04 15:53:23 +0000211 const TargetMachine &Target;
Vikram S. Adved198c472002-03-18 03:07:26 +0000212
Chris Lattnere88f78c2001-09-19 13:47:27 +0000213 enum Sections {
214 Unknown,
215 Text,
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000216 ReadOnlyData,
217 InitRWData,
Vikram S. Advefee76262002-10-13 00:32:18 +0000218 ZeroInitRWData,
Chris Lattnere88f78c2001-09-19 13:47:27 +0000219 } CurSection;
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000220
Chris Lattner59ba1092002-02-04 15:53:23 +0000221 AsmPrinter(std::ostream &os, const TargetMachine &T)
Vikram S. Adved198c472002-03-18 03:07:26 +0000222 : idTable(0), toAsm(os), Target(T), CurSection(Unknown) {}
223
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000224 // (start|end)(Module|Function) - Callback methods to be invoked by subclasses
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000225 void startModule(Module &M) {
Vikram S. Adved198c472002-03-18 03:07:26 +0000226 // Create the global id table if it does not already exist
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000227 idTable = (GlobalIdTable*)M.getAnnotation(GlobalIdTable::AnnotId);
Vikram S. Adved198c472002-03-18 03:07:26 +0000228 if (idTable == NULL) {
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000229 idTable = new GlobalIdTable(&M);
230 M.addAnnotation(idTable);
Vikram S. Adved198c472002-03-18 03:07:26 +0000231 }
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000232 }
Misha Brukmanf905ed52003-11-07 17:45:28 +0000233
234 void
235 PrintZeroBytesToPad(int numBytes)
236 {
237 for ( ; numBytes >= 8; numBytes -= 8)
238 printSingleConstantValue(Constant::getNullValue(Type::ULongTy));
239
240 if (numBytes >= 4)
241 {
242 printSingleConstantValue(Constant::getNullValue(Type::UIntTy));
243 numBytes -= 4;
244 }
245
246 while (numBytes--)
247 printSingleConstantValue(Constant::getNullValue(Type::UByteTy));
248 }
249
250 // Print a single constant value.
251 void printSingleConstantValue(const Constant* CV)
252 {
253 assert(CV->getType() != Type::VoidTy &&
254 CV->getType() != Type::TypeTy &&
255 CV->getType() != Type::LabelTy &&
256 "Unexpected type for Constant");
257
258 assert((!isa<ConstantArray>(CV) && ! isa<ConstantStruct>(CV))
259 && "Aggregate types should be handled outside this function");
260
261 toAsm << "\t" << TypeToDataDirective(CV->getType()) << "\t";
262
263 if (const ConstantPointerRef* CPR = dyn_cast<ConstantPointerRef>(CV))
264 { // This is a constant address for a global variable or method.
265 // Use the name of the variable or method as the address value.
266 assert(isa<GlobalValue>(CPR->getValue()) && "Unexpected non-global");
267 toAsm << getID(CPR->getValue()) << "\n";
268 }
269 else if (isa<ConstantPointerNull>(CV))
270 { // Null pointer value
271 toAsm << "0\n";
272 }
273 else if (const ConstantExpr* CE = dyn_cast<ConstantExpr>(CV))
274 { // Constant expression built from operators, constants, and symbolic addrs
275 toAsm << ConstantExprToString(CE, Target) << "\n";
276 }
277 else if (CV->getType()->isPrimitiveType()) // Check primitive types last
278 {
279 if (CV->getType()->isFloatingPoint()) {
280 // FP Constants are printed as integer constants to avoid losing
281 // precision...
282 double Val = cast<ConstantFP>(CV)->getValue();
283 if (CV->getType() == Type::FloatTy) {
284 float FVal = (float)Val;
285 char *ProxyPtr = (char*)&FVal; // Abide by C TBAA rules
286 toAsm << *(unsigned int*)ProxyPtr;
287 } else if (CV->getType() == Type::DoubleTy) {
288 char *ProxyPtr = (char*)&Val; // Abide by C TBAA rules
289 toAsm << *(uint64_t*)ProxyPtr;
290 } else {
291 assert(0 && "Unknown floating point type!");
292 }
293
294 toAsm << "\t! " << CV->getType()->getDescription()
295 << " value: " << Val << "\n";
296 } else {
297 WriteAsOperand(toAsm, CV, false, false) << "\n";
298 }
299 }
300 else
301 {
302 assert(0 && "Unknown elementary type for constant");
303 }
304 }
305
306 // Print a constant value or values (it may be an aggregate).
307 // Uses printSingleConstantValue() to print each individual value.
308 void
309 printConstantValueOnly(const Constant* CV,
310 int numPadBytesAfter = 0)
311 {
312 const ConstantArray *CVA = dyn_cast<ConstantArray>(CV);
313
314 if (CVA && isStringCompatible(CVA))
315 { // print the string alone and return
316 toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n";
317 }
318 else if (CVA)
319 { // Not a string. Print the values in successive locations
320 const std::vector<Use> &constValues = CVA->getValues();
321 for (unsigned i=0; i < constValues.size(); i++)
322 printConstantValueOnly(cast<Constant>(constValues[i].get()));
323 }
324 else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
325 { // Print the fields in successive locations. Pad to align if needed!
326 const StructLayout *cvsLayout =
327 Target.getTargetData().getStructLayout(CVS->getType());
328 const std::vector<Use>& constValues = CVS->getValues();
329 unsigned sizeSoFar = 0;
330 for (unsigned i=0, N = constValues.size(); i < N; i++)
331 {
332 const Constant* field = cast<Constant>(constValues[i].get());
333
334 // Check if padding is needed and insert one or more 0s.
335 unsigned fieldSize =
336 Target.getTargetData().getTypeSize(field->getType());
337 int padSize = ((i == N-1? cvsLayout->StructSize
338 : cvsLayout->MemberOffsets[i+1])
339 - cvsLayout->MemberOffsets[i]) - fieldSize;
340 sizeSoFar += (fieldSize + padSize);
341
342 // Now print the actual field value
343 printConstantValueOnly(field, padSize);
344 }
345 assert(sizeSoFar == cvsLayout->StructSize &&
346 "Layout of constant struct may be incorrect!");
347 }
348 else
349 printSingleConstantValue(CV);
350
351 if (numPadBytesAfter)
352 PrintZeroBytesToPad(numPadBytesAfter);
353 }
354
355 // Print a constant (which may be an aggregate) prefixed by all the
356 // appropriate directives. Uses printConstantValueOnly() to print the
357 // value or values.
358 void printConstant(const Constant* CV, std::string valID = "")
359 {
360 if (valID.length() == 0)
361 valID = getID(CV);
362
363 toAsm << "\t.align\t" << ConstantToAlignment(CV, Target) << "\n";
364
365 // Print .size and .type only if it is not a string.
366 const ConstantArray *CVA = dyn_cast<ConstantArray>(CV);
367 if (CVA && isStringCompatible(CVA))
368 { // print it as a string and return
369 toAsm << valID << ":\n";
370 toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n";
371 return;
372 }
373
374 toAsm << "\t.type" << "\t" << valID << ",#object\n";
375
376 unsigned int constSize = ConstantToSize(CV, Target);
377 if (constSize)
378 toAsm << "\t.size" << "\t" << valID << "," << constSize << "\n";
379
380 toAsm << valID << ":\n";
381
382 printConstantValueOnly(CV);
383 }
384
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000385 void startFunction(Function &F) {
Chris Lattnerb5794002002-04-07 22:49:37 +0000386 // Make sure the slot table has information about this function...
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000387 idTable->Table.incorporateFunction(&F);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000388 }
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000389 void endFunction(Function &) {
Chris Lattnerfd63f25f2002-04-28 04:50:54 +0000390 idTable->Table.purgeFunction(); // Forget all about F
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000391 }
392 void endModule() {
Chris Lattnere88f78c2001-09-19 13:47:27 +0000393 }
394
Chris Lattner8b1b4e22002-07-16 18:35:16 +0000395 // Check if a value is external or accessible from external code.
Vikram S. Adved198c472002-03-18 03:07:26 +0000396 bool isExternal(const Value* V) {
Chris Lattner8b1b4e22002-07-16 18:35:16 +0000397 const GlobalValue *GV = dyn_cast<GlobalValue>(V);
398 return GV && GV->hasExternalLinkage();
Vikram S. Adved198c472002-03-18 03:07:26 +0000399 }
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000400
Chris Lattnere88f78c2001-09-19 13:47:27 +0000401 // enterSection - Use this method to enter a different section of the output
Misha Brukman5560c9d2003-08-18 14:43:39 +0000402 // executable. This is used to only output necessary section transitions.
Chris Lattnere88f78c2001-09-19 13:47:27 +0000403 //
404 void enterSection(enum Sections S) {
Misha Brukman5560c9d2003-08-18 14:43:39 +0000405 if (S == CurSection) return; // Only switch section if necessary
Chris Lattnere88f78c2001-09-19 13:47:27 +0000406 CurSection = S;
407
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000408 toAsm << "\n\t.section ";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000409 switch (S)
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000410 {
411 default: assert(0 && "Bad section name!");
412 case Text: toAsm << "\".text\""; break;
413 case ReadOnlyData: toAsm << "\".rodata\",#alloc"; break;
414 case InitRWData: toAsm << "\".data\",#alloc,#write"; break;
415 case ZeroInitRWData: toAsm << "\".bss\",#alloc,#write"; break;
416 }
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000417 toAsm << "\n";
Chris Lattnere88f78c2001-09-19 13:47:27 +0000418 }
419
Misha Brukmanf4de7832003-08-05 16:01:50 +0000420 static std::string getValidSymbolName(const std::string &S) {
421 std::string Result;
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000422
423 // Symbol names in Sparc assembly language have these rules:
424 // (a) Must match { letter | _ | . | $ } { letter | _ | . | $ | digit }*
425 // (b) A name beginning in "." is treated as a local name.
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000426 //
Chris Lattnerbb6b1212002-10-14 06:14:18 +0000427 if (isdigit(S[0]))
428 Result = "ll";
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000429
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000430 for (unsigned i = 0; i < S.size(); ++i)
431 {
432 char C = S[i];
433 if (C == '_' || C == '.' || C == '$' || isalpha(C) || isdigit(C))
434 Result += C;
435 else
436 {
437 Result += '_';
438 Result += char('0' + ((unsigned char)C >> 4));
439 Result += char('0' + (C & 0xF));
440 }
Chris Lattnerc56d7792001-09-28 15:07:24 +0000441 }
Chris Lattnerc56d7792001-09-28 15:07:24 +0000442 return Result;
443 }
444
Chris Lattnere88f78c2001-09-19 13:47:27 +0000445 // getID - Return a valid identifier for the specified value. Base it on
Vikram S. Adved198c472002-03-18 03:07:26 +0000446 // the name of the identifier if possible (qualified by the type), and
447 // use a numbered value based on prefix otherwise.
448 // FPrefix is always prepended to the output identifier.
Chris Lattnere88f78c2001-09-19 13:47:27 +0000449 //
Misha Brukmanf4de7832003-08-05 16:01:50 +0000450 std::string getID(const Value *V, const char *Prefix, const char *FPrefix = 0) {
451 std::string Result = FPrefix ? FPrefix : ""; // "Forced prefix"
Vikram S. Adve96918072002-10-30 20:16:38 +0000452
Misha Brukmanf4de7832003-08-05 16:01:50 +0000453 Result += V->hasName() ? V->getName() : std::string(Prefix);
Vikram S. Adve96918072002-10-30 20:16:38 +0000454
Vikram S. Adved198c472002-03-18 03:07:26 +0000455 // Qualify all internal names with a unique id.
456 if (!isExternal(V)) {
Alkis Evlogimenos60596382003-10-17 02:02:40 +0000457 int valId = idTable->Table.getSlot(V);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000458 if (valId == -1) {
Vikram S. Adved198c472002-03-18 03:07:26 +0000459 GlobalIdTable::ValIdMapConstIterator I = idTable->valToIdMap.find(V);
460 if (I == idTable->valToIdMap.end())
461 valId = idTable->valToIdMap[V] = idTable->valToIdMap.size();
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000462 else
463 valId = I->second;
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000464 }
Vikram S. Adved198c472002-03-18 03:07:26 +0000465 Result = Result + "_" + itostr(valId);
Vikram S. Adve96918072002-10-30 20:16:38 +0000466
467 // Replace or prefix problem characters in the name
468 Result = getValidSymbolName(Result);
Chris Lattnere88f78c2001-09-19 13:47:27 +0000469 }
Vikram S. Adve96918072002-10-30 20:16:38 +0000470
471 return Result;
Chris Lattnere88f78c2001-09-19 13:47:27 +0000472 }
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000473
Chris Lattnere88f78c2001-09-19 13:47:27 +0000474 // getID Wrappers - Ensure consistent usage...
Misha Brukmanf4de7832003-08-05 16:01:50 +0000475 std::string getID(const Function *F) {
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000476 return getID(F, "LLVMFunction_");
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000477 }
Misha Brukmanf4de7832003-08-05 16:01:50 +0000478 std::string getID(const BasicBlock *BB) {
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000479 return getID(BB, "LL", (".L_"+getID(BB->getParent())+"_").c_str());
480 }
Misha Brukmanf4de7832003-08-05 16:01:50 +0000481 std::string getID(const GlobalVariable *GV) {
Chris Lattner8b1b4e22002-07-16 18:35:16 +0000482 return getID(GV, "LLVMGlobal_");
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000483 }
Misha Brukmanf4de7832003-08-05 16:01:50 +0000484 std::string getID(const Constant *CV) {
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000485 return getID(CV, "LLVMConst_", ".C_");
486 }
Misha Brukmanf4de7832003-08-05 16:01:50 +0000487 std::string getID(const GlobalValue *GV) {
Chris Lattner8b1b4e22002-07-16 18:35:16 +0000488 if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV))
489 return getID(V);
490 else if (const Function *F = dyn_cast<Function>(GV))
491 return getID(F);
492 assert(0 && "Unexpected type of GlobalValue!");
493 return "";
494 }
Vikram S. Advee99941a2002-08-22 02:58:36 +0000495
Misha Brukmanf4de7832003-08-05 16:01:50 +0000496 // Combines expressions
497 inline std::string ConstantArithExprToString(const ConstantExpr* CE,
498 const TargetMachine &TM,
499 const std::string &op) {
500 return "(" + valToExprString(CE->getOperand(0), TM) + op
501 + valToExprString(CE->getOperand(1), TM) + ")";
502 }
503
Vikram S. Adve537a8772002-09-05 18:28:10 +0000504 // ConstantExprToString() - Convert a ConstantExpr to an asm expression
505 // and return this as a string.
Misha Brukmanf4de7832003-08-05 16:01:50 +0000506 std::string ConstantExprToString(const ConstantExpr* CE,
507 const TargetMachine& target) {
508 std::string S;
Vikram S. Advee99941a2002-08-22 02:58:36 +0000509 switch(CE->getOpcode()) {
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000510 case Instruction::GetElementPtr:
511 { // generate a symbolic expression for the byte address
512 const Value* ptrVal = CE->getOperand(0);
513 std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
Misha Brukmanf4de7832003-08-05 16:01:50 +0000514 const TargetData &TD = target.getTargetData();
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000515 S += "(" + valToExprString(ptrVal, target) + ") + ("
516 + utostr(TD.getIndexedOffset(ptrVal->getType(),idxVec)) + ")";
517 break;
518 }
Vikram S. Advee99941a2002-08-22 02:58:36 +0000519
Vikram S. Adve537a8772002-09-05 18:28:10 +0000520 case Instruction::Cast:
521 // Support only non-converting casts for now, i.e., a no-op.
522 // This assertion is not a complete check.
Chris Lattnerd0fe5f52002-12-28 20:15:01 +0000523 assert(target.getTargetData().getTypeSize(CE->getType()) ==
524 target.getTargetData().getTypeSize(CE->getOperand(0)->getType()));
Vikram S. Adve537a8772002-09-05 18:28:10 +0000525 S += "(" + valToExprString(CE->getOperand(0), target) + ")";
526 break;
527
528 case Instruction::Add:
Misha Brukmanf4de7832003-08-05 16:01:50 +0000529 S += ConstantArithExprToString(CE, target, ") + (");
Vikram S. Adve537a8772002-09-05 18:28:10 +0000530 break;
531
Vikram S. Adve72666e62003-08-01 15:55:53 +0000532 case Instruction::Sub:
Misha Brukmanf4de7832003-08-05 16:01:50 +0000533 S += ConstantArithExprToString(CE, target, ") - (");
Vikram S. Adve72666e62003-08-01 15:55:53 +0000534 break;
535
536 case Instruction::Mul:
Misha Brukmanf4de7832003-08-05 16:01:50 +0000537 S += ConstantArithExprToString(CE, target, ") * (");
Vikram S. Adve72666e62003-08-01 15:55:53 +0000538 break;
539
540 case Instruction::Div:
Misha Brukmanf4de7832003-08-05 16:01:50 +0000541 S += ConstantArithExprToString(CE, target, ") / (");
Vikram S. Adve72666e62003-08-01 15:55:53 +0000542 break;
543
544 case Instruction::Rem:
Misha Brukmanf4de7832003-08-05 16:01:50 +0000545 S += ConstantArithExprToString(CE, target, ") % (");
Vikram S. Adve72666e62003-08-01 15:55:53 +0000546 break;
547
548 case Instruction::And:
549 // Logical && for booleans; bitwise & otherwise
Misha Brukmanf4de7832003-08-05 16:01:50 +0000550 S += ConstantArithExprToString(CE, target,
551 ((CE->getType() == Type::BoolTy)? ") && (" : ") & ("));
Vikram S. Adve72666e62003-08-01 15:55:53 +0000552 break;
553
554 case Instruction::Or:
555 // Logical || for booleans; bitwise | otherwise
Misha Brukmanf4de7832003-08-05 16:01:50 +0000556 S += ConstantArithExprToString(CE, target,
557 ((CE->getType() == Type::BoolTy)? ") || (" : ") | ("));
Vikram S. Adve72666e62003-08-01 15:55:53 +0000558 break;
559
560 case Instruction::Xor:
561 // Bitwise ^ for all types
Misha Brukmanf4de7832003-08-05 16:01:50 +0000562 S += ConstantArithExprToString(CE, target, ") ^ (");
Vikram S. Adve72666e62003-08-01 15:55:53 +0000563 break;
564
Vikram S. Advee99941a2002-08-22 02:58:36 +0000565 default:
566 assert(0 && "Unsupported operator in ConstantExprToString()");
567 break;
568 }
569
570 return S;
571 }
572
573 // valToExprString - Helper function for ConstantExprToString().
574 // Appends result to argument string S.
575 //
Misha Brukmanf4de7832003-08-05 16:01:50 +0000576 std::string valToExprString(const Value* V, const TargetMachine& target) {
577 std::string S;
Vikram S. Advee99941a2002-08-22 02:58:36 +0000578 bool failed = false;
579 if (const Constant* CV = dyn_cast<Constant>(V)) { // symbolic or known
580
581 if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV))
Misha Brukmanf4de7832003-08-05 16:01:50 +0000582 S += std::string(CB == ConstantBool::True ? "1" : "0");
Vikram S. Advee99941a2002-08-22 02:58:36 +0000583 else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
584 S += itostr(CI->getValue());
585 else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
586 S += utostr(CI->getValue());
587 else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))
588 S += ftostr(CFP->getValue());
589 else if (isa<ConstantPointerNull>(CV))
590 S += "0";
591 else if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(CV))
Vikram S. Adve537a8772002-09-05 18:28:10 +0000592 S += valToExprString(CPR->getValue(), target);
Vikram S. Advee99941a2002-08-22 02:58:36 +0000593 else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV))
594 S += ConstantExprToString(CE, target);
595 else
596 failed = true;
597
598 } else if (const GlobalValue* GV = dyn_cast<GlobalValue>(V)) {
599 S += getID(GV);
600 }
601 else
602 failed = true;
603
604 if (failed) {
605 assert(0 && "Cannot convert value to string");
606 S += "<illegal-value>";
607 }
Vikram S. Adve537a8772002-09-05 18:28:10 +0000608 return S;
Vikram S. Advee99941a2002-08-22 02:58:36 +0000609 }
610
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000611};
612
613
614
615//===----------------------------------------------------------------------===//
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000616// SparcFunctionAsmPrinter Code
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000617//===----------------------------------------------------------------------===//
618
Chris Lattnerf57b8452002-04-27 06:56:12 +0000619struct SparcFunctionAsmPrinter : public FunctionPass, public AsmPrinter {
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000620 inline SparcFunctionAsmPrinter(std::ostream &os, const TargetMachine &t)
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000621 : AsmPrinter(os, t) {}
622
Misha Brukmanf905ed52003-11-07 17:45:28 +0000623 const Function *currFunction;
624
Chris Lattner96c466b2002-04-29 14:57:45 +0000625 const char *getPassName() const {
626 return "Output Sparc Assembly for Functions";
627 }
628
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000629 virtual bool doInitialization(Module &M) {
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000630 startModule(M);
631 return false;
632 }
633
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000634 virtual bool runOnFunction(Function &F) {
Misha Brukmanf905ed52003-11-07 17:45:28 +0000635 currFunction = &F;
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000636 startFunction(F);
637 emitFunction(F);
638 endFunction(F);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000639 return false;
640 }
641
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000642 virtual bool doFinalization(Module &M) {
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000643 endModule();
644 return false;
645 }
646
Chris Lattner97e52e42002-04-28 21:27:06 +0000647 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
648 AU.setPreservesAll();
649 }
650
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000651 void emitFunction(const Function &F);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000652private :
Misha Brukmane585a7d2002-10-28 20:01:13 +0000653 void emitBasicBlock(const MachineBasicBlock &MBB);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000654 void emitMachineInst(const MachineInstr *MI);
655
656 unsigned int printOperands(const MachineInstr *MI, unsigned int opNum);
Vikram S. Adve78a4f232003-05-27 00:02:22 +0000657 void printOneOperand(const MachineOperand &Op, MachineOpCode opCode);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000658
659 bool OpIsBranchTargetLabel(const MachineInstr *MI, unsigned int opNum);
660 bool OpIsMemoryAddressBase(const MachineInstr *MI, unsigned int opNum);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000661
Chris Lattnere88f78c2001-09-19 13:47:27 +0000662 unsigned getOperandMask(unsigned Opcode) {
663 switch (Opcode) {
Misha Brukman71ed1c92003-05-27 22:35:43 +0000664 case V9::SUBccr:
665 case V9::SUBcci: return 1 << 3; // Remove CC argument
Vikram S. Adveb2debdc2002-07-08 23:30:59 +0000666 //case BA: return 1 << 0; // Remove Arg #0, which is always null or xcc
Chris Lattnere88f78c2001-09-19 13:47:27 +0000667 default: return 0; // By default, don't hack operands...
668 }
669 }
670};
671
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000672inline bool
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000673SparcFunctionAsmPrinter::OpIsBranchTargetLabel(const MachineInstr *MI,
674 unsigned int opNum) {
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000675 switch (MI->getOpCode()) {
Misha Brukman71ed1c92003-05-27 22:35:43 +0000676 case V9::JMPLCALLr:
677 case V9::JMPLCALLi:
678 case V9::JMPLRETr:
679 case V9::JMPLRETi:
Misha Brukmana98cd452003-05-20 20:32:24 +0000680 return (opNum == 0);
681 default:
682 return false;
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000683 }
684}
685
686
687inline bool
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000688SparcFunctionAsmPrinter::OpIsMemoryAddressBase(const MachineInstr *MI,
689 unsigned int opNum) {
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000690 if (Target.getInstrInfo().isLoad(MI->getOpCode()))
691 return (opNum == 0);
692 else if (Target.getInstrInfo().isStore(MI->getOpCode()))
693 return (opNum == 1);
694 else
695 return false;
696}
697
698
Vikram S. Adve78a4f232003-05-27 00:02:22 +0000699#define PrintOp1PlusOp2(mop1, mop2, opCode) \
700 printOneOperand(mop1, opCode); \
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000701 toAsm << "+"; \
Vikram S. Adve78a4f232003-05-27 00:02:22 +0000702 printOneOperand(mop2, opCode);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000703
704unsigned int
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000705SparcFunctionAsmPrinter::printOperands(const MachineInstr *MI,
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000706 unsigned int opNum)
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000707{
Vikram S. Adve195a5d52002-07-10 21:41:21 +0000708 const MachineOperand& mop = MI->getOperand(opNum);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000709
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000710 if (OpIsBranchTargetLabel(MI, opNum))
711 {
712 PrintOp1PlusOp2(mop, MI->getOperand(opNum+1), MI->getOpCode());
713 return 2;
714 }
715 else if (OpIsMemoryAddressBase(MI, opNum))
716 {
717 toAsm << "[";
718 PrintOp1PlusOp2(mop, MI->getOperand(opNum+1), MI->getOpCode());
719 toAsm << "]";
720 return 2;
721 }
722 else
723 {
724 printOneOperand(mop, MI->getOpCode());
725 return 1;
726 }
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000727}
728
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000729void
Vikram S. Adve78a4f232003-05-27 00:02:22 +0000730SparcFunctionAsmPrinter::printOneOperand(const MachineOperand &mop,
731 MachineOpCode opCode)
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000732{
Vikram S. Adve195a5d52002-07-10 21:41:21 +0000733 bool needBitsFlag = true;
734
735 if (mop.opHiBits32())
736 toAsm << "%lm(";
737 else if (mop.opLoBits32())
738 toAsm << "%lo(";
739 else if (mop.opHiBits64())
740 toAsm << "%hh(";
741 else if (mop.opLoBits64())
742 toAsm << "%hm(";
743 else
744 needBitsFlag = false;
745
Chris Lattner133f0792002-10-28 04:45:29 +0000746 switch (mop.getType())
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000747 {
Vikram S. Adve786833a2003-07-06 20:13:59 +0000748 case MachineOperand::MO_VirtualRegister:
Vikram S. Adveb15f8d42003-07-10 19:42:11 +0000749 case MachineOperand::MO_CCRegister:
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000750 case MachineOperand::MO_MachineRegister:
751 {
752 int regNum = (int)mop.getAllocatedRegNum();
Vikram S. Adveb15f8d42003-07-10 19:42:11 +0000753
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000754 if (regNum == Target.getRegInfo().getInvalidRegNum()) {
755 // better to print code with NULL registers than to die
756 toAsm << "<NULL VALUE>";
757 } else {
758 toAsm << "%" << Target.getRegInfo().getUnifiedRegName(regNum);
759 }
760 break;
761 }
Misha Brukmanb3fabe02003-05-31 06:22:37 +0000762
Misha Brukmanf905ed52003-11-07 17:45:28 +0000763 case MachineOperand::MO_ConstantPoolIndex:
764 {
765 toAsm << ".CPI_" << currFunction->getName()
766 << "_" << mop.getConstantPoolIndex();
767 break;
768 }
769
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000770 case MachineOperand::MO_PCRelativeDisp:
771 {
772 const Value *Val = mop.getVRegValue();
773 assert(Val && "\tNULL Value in SparcFunctionAsmPrinter");
Misha Brukmanb3fabe02003-05-31 06:22:37 +0000774
Chris Lattner949a3622003-07-23 15:30:06 +0000775 if (const BasicBlock *BB = dyn_cast<BasicBlock>(Val))
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000776 toAsm << getID(BB);
777 else if (const Function *M = dyn_cast<Function>(Val))
778 toAsm << getID(M);
779 else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Val))
780 toAsm << getID(GV);
781 else if (const Constant *CV = dyn_cast<Constant>(Val))
782 toAsm << getID(CV);
783 else
784 assert(0 && "Unrecognized value in SparcFunctionAsmPrinter");
785 break;
786 }
Misha Brukmanb3fabe02003-05-31 06:22:37 +0000787
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000788 case MachineOperand::MO_SignExtendedImmed:
789 toAsm << mop.getImmedValue();
790 break;
Misha Brukmanb3fabe02003-05-31 06:22:37 +0000791
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000792 case MachineOperand::MO_UnextendedImmed:
793 toAsm << (uint64_t) mop.getImmedValue();
794 break;
Misha Brukmanb3fabe02003-05-31 06:22:37 +0000795
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000796 default:
797 toAsm << mop; // use dump field
798 break;
799 }
Vikram S. Adve195a5d52002-07-10 21:41:21 +0000800
801 if (needBitsFlag)
802 toAsm << ")";
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000803}
804
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000805void
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000806SparcFunctionAsmPrinter::emitMachineInst(const MachineInstr *MI)
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000807{
808 unsigned Opcode = MI->getOpCode();
809
Vikram S. Advec227a9a2002-11-06 00:34:26 +0000810 if (Target.getInstrInfo().isDummyPhiInstr(Opcode))
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000811 return; // IGNORE PHI NODES
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000812
Chris Lattnerf44f9052002-10-29 17:35:41 +0000813 toAsm << "\t" << Target.getInstrInfo().getName(Opcode) << "\t";
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000814
815 unsigned Mask = getOperandMask(Opcode);
816
817 bool NeedComma = false;
818 unsigned N = 1;
819 for (unsigned OpNum = 0; OpNum < MI->getNumOperands(); OpNum += N)
820 if (! ((1 << OpNum) & Mask)) { // Ignore this operand?
Misha Brukman8b2fe192003-09-23 17:27:28 +0000821 if (NeedComma) toAsm << ", "; // Handle comma outputting
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000822 NeedComma = true;
823 N = printOperands(MI, OpNum);
Chris Lattnerebdc7f32002-11-17 22:57:23 +0000824 } else
825 N = 1;
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000826
827 toAsm << "\n";
Brian Gaeke2c9b9132003-10-06 15:41:21 +0000828 ++EmittedInsts;
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000829}
830
831void
Misha Brukmane585a7d2002-10-28 20:01:13 +0000832SparcFunctionAsmPrinter::emitBasicBlock(const MachineBasicBlock &MBB)
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000833{
834 // Emit a label for the basic block
Misha Brukmane585a7d2002-10-28 20:01:13 +0000835 toAsm << getID(MBB.getBasicBlock()) << ":\n";
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000836
837 // Loop over all of the instructions in the basic block...
Misha Brukmane585a7d2002-10-28 20:01:13 +0000838 for (MachineBasicBlock::const_iterator MII = MBB.begin(), MIE = MBB.end();
Chris Lattner55291ea2002-10-28 01:41:47 +0000839 MII != MIE; ++MII)
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000840 emitMachineInst(*MII);
Misha Brukmanbc0e9982003-07-14 17:20:40 +0000841 toAsm << "\n"; // Separate BB's with newlines
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000842}
843
844void
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000845SparcFunctionAsmPrinter::emitFunction(const Function &F)
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000846{
Misha Brukmanf4de7832003-08-05 16:01:50 +0000847 std::string methName = getID(&F);
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000848 toAsm << "!****** Outputing Function: " << methName << " ******\n";
Misha Brukmanf905ed52003-11-07 17:45:28 +0000849
850 // Emit constant pool for this function
851 const MachineConstantPool *MCP = MachineFunction::get(&F).getConstantPool();
852 const std::vector<Constant*> &CP = MCP->getConstants();
853
854 enterSection(AsmPrinter::ReadOnlyData);
855 for (unsigned i = 0, e = CP.size(); i != e; ++i) {
856 std::string cpiName = ".CPI_" + F.getName() + "_" + utostr(i);
857 printConstant(CP[i], cpiName);
858 }
859
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000860 enterSection(AsmPrinter::Text);
861 toAsm << "\t.align\t4\n\t.global\t" << methName << "\n";
862 //toAsm << "\t.type\t" << methName << ",#function\n";
863 toAsm << "\t.type\t" << methName << ", 2\n";
864 toAsm << methName << ":\n";
865
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000866 // Output code for all of the basic blocks in the function...
Misha Brukmane585a7d2002-10-28 20:01:13 +0000867 MachineFunction &MF = MachineFunction::get(&F);
Chris Lattnerd0fe5f52002-12-28 20:15:01 +0000868 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E;++I)
Misha Brukmane585a7d2002-10-28 20:01:13 +0000869 emitBasicBlock(*I);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000870
871 // Output a .size directive so the debugger knows the extents of the function
872 toAsm << ".EndOf_" << methName << ":\n\t.size "
873 << methName << ", .EndOf_"
874 << methName << "-" << methName << "\n";
875
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000876 // Put some spaces between the functions
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000877 toAsm << "\n\n";
878}
879
880} // End anonymous namespace
881
Brian Gaeked0fde302003-11-11 22:41:34 +0000882namespace llvm {
883
Vikram S. Adve13f1d712002-09-16 15:54:02 +0000884Pass *UltraSparc::getFunctionAsmPrinterPass(std::ostream &Out) {
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000885 return new SparcFunctionAsmPrinter(Out, *this);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000886}
887
Brian Gaeked0fde302003-11-11 22:41:34 +0000888} // End llvm namespace
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000889
890
891//===----------------------------------------------------------------------===//
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000892// SparcFunctionAsmPrinter Code
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000893//===----------------------------------------------------------------------===//
894
895namespace {
896
897class SparcModuleAsmPrinter : public Pass, public AsmPrinter {
898public:
Chris Lattner49b8a9c2002-02-24 23:02:40 +0000899 SparcModuleAsmPrinter(std::ostream &os, TargetMachine &t)
900 : AsmPrinter(os, t) {}
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000901
Chris Lattner96c466b2002-04-29 14:57:45 +0000902 const char *getPassName() const { return "Output Sparc Assembly for Module"; }
903
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000904 virtual bool run(Module &M) {
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000905 startModule(M);
Misha Brukmanf905ed52003-11-07 17:45:28 +0000906 emitGlobals(M);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000907 endModule();
908 return false;
909 }
910
Chris Lattner97e52e42002-04-28 21:27:06 +0000911 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
912 AU.setPreservesAll();
913 }
914
915private:
Misha Brukmanf905ed52003-11-07 17:45:28 +0000916 void emitGlobals(const Module &M);
917 void printGlobalVariable(const GlobalVariable *GV);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000918};
919
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000920void SparcModuleAsmPrinter::printGlobalVariable(const GlobalVariable* GV)
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000921{
Vikram S. Adve13f1d712002-09-16 15:54:02 +0000922 if (GV->hasExternalLinkage())
923 toAsm << "\t.global\t" << getID(GV) << "\n";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000924
Vikram S. Advefee76262002-10-13 00:32:18 +0000925 if (GV->hasInitializer() && ! GV->getInitializer()->isNullValue())
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000926 printConstant(GV->getInitializer(), getID(GV));
927 else {
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000928 toAsm << "\t.align\t" << TypeToAlignment(GV->getType()->getElementType(),
929 Target) << "\n";
Chris Lattner697954c2002-01-20 22:54:45 +0000930 toAsm << "\t.type\t" << getID(GV) << ",#object\n";
Vikram S. Adveffbba0f2001-11-08 14:29:57 +0000931 toAsm << "\t.reserve\t" << getID(GV) << ","
Vikram S. Advefee76262002-10-13 00:32:18 +0000932 << TypeToSize(GV->getType()->getElementType(), Target)
Chris Lattner697954c2002-01-20 22:54:45 +0000933 << "\n";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000934 }
935}
936
Misha Brukmanf905ed52003-11-07 17:45:28 +0000937void SparcModuleAsmPrinter::emitGlobals(const Module &M) {
Chris Lattner637ed862002-08-07 21:39:48 +0000938 // Output global variables...
Vikram S. Advefee76262002-10-13 00:32:18 +0000939 for (Module::const_giterator GI = M.gbegin(), GE = M.gend(); GI != GE; ++GI)
940 if (! GI->isExternal()) {
941 assert(GI->hasInitializer());
942 if (GI->isConstant())
943 enterSection(AsmPrinter::ReadOnlyData); // read-only, initialized data
944 else if (GI->getInitializer()->isNullValue())
945 enterSection(AsmPrinter::ZeroInitRWData); // read-write zero data
946 else
947 enterSection(AsmPrinter::InitRWData); // read-write non-zero data
948
949 printGlobalVariable(GI);
Chris Lattner637ed862002-08-07 21:39:48 +0000950 }
Chris Lattner637ed862002-08-07 21:39:48 +0000951
Chris Lattner697954c2002-01-20 22:54:45 +0000952 toAsm << "\n";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000953}
954
Chris Lattnere88f78c2001-09-19 13:47:27 +0000955} // End anonymous namespace
956
Vikram S. Adve13f1d712002-09-16 15:54:02 +0000957Pass *UltraSparc::getModuleAsmPrinterPass(std::ostream &Out) {
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000958 return new SparcModuleAsmPrinter(Out, *this);
Chris Lattnerc019a172002-02-03 07:48:06 +0000959}
Brian Gaeked0fde302003-11-11 22:41:34 +0000960
961} // End llvm namespace