blob: 36da80bb2d5653572dfd1a9bada3bbfb21c3638a [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 Lattner31bcdb82002-04-28 19:55:58 +000021#include "llvm/Constants.h"
Vikram S. Adve953c83e2001-10-28 21:38:52 +000022#include "llvm/DerivedTypes.h"
Chris Lattnere88f78c2001-09-19 13:47:27 +000023#include "llvm/Module.h"
Chris Lattnerd50b6712002-04-28 20:40:59 +000024#include "llvm/Pass.h"
Chris Lattner4b1de8e2002-04-18 18:15:38 +000025#include "llvm/Assembly/Writer.h"
Misha Brukman3d0ad412003-12-17 22:06:28 +000026#include "llvm/CodeGen/MachineConstantPool.h"
27#include "llvm/CodeGen/MachineFunction.h"
28#include "llvm/CodeGen/MachineFunctionInfo.h"
29#include "llvm/CodeGen/MachineInstr.h"
Chris Lattnercee8f9a2001-11-27 00:03:19 +000030#include "Support/StringExtras.h"
Brian Gaeke2c9b9132003-10-06 15:41:21 +000031#include "Support/Statistic.h"
Misha Brukmanf4de7832003-08-05 16:01:50 +000032#include "SparcInternals.h"
33#include <string>
Misha Brukman6275a042003-11-13 00:22:19 +000034using namespace llvm;
35
Chris Lattnere88f78c2001-09-19 13:47:27 +000036namespace {
Misha Brukman6275a042003-11-13 00:22:19 +000037 Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
Brian Gaeke2c9b9132003-10-06 15:41:21 +000038
Misha Brukman6275a042003-11-13 00:22:19 +000039 class GlobalIdTable: public Annotation {
40 static AnnotationID AnnotId;
41 friend class AsmPrinter; // give access to AnnotId
Misha Brukman6275a042003-11-13 00:22:19 +000042 public:
Chris Lattner7446dc02004-01-13 21:27:59 +000043 // AnonymousObjectMap - map anonymous values to unique integer IDs
44 std::map<const Value*, unsigned> AnonymousObjectMap;
45 unsigned LastAnonIDUsed;
Misha Brukman6275a042003-11-13 00:22:19 +000046
Chris Lattner7446dc02004-01-13 21:27:59 +000047 GlobalIdTable() : Annotation(AnnotId), LastAnonIDUsed(0) {}
Misha Brukman6275a042003-11-13 00:22:19 +000048 };
Vikram S. Adved198c472002-03-18 03:07:26 +000049
Misha Brukman6275a042003-11-13 00:22:19 +000050 AnnotationID GlobalIdTable::AnnotId =
Vikram S. Adved198c472002-03-18 03:07:26 +000051 AnnotationManager::getID("ASM PRINTER GLOBAL TABLE ANNOT");
Misha Brukman6275a042003-11-13 00:22:19 +000052
53 //===--------------------------------------------------------------------===//
54 // Utility functions
Misha Brukmanf905ed52003-11-07 17:45:28 +000055
Misha Brukman6275a042003-11-13 00:22:19 +000056 /// Can we treat the specified array as a string? Only if it is an array of
57 /// ubytes or non-negative sbytes.
58 ///
59 bool isStringCompatible(const ConstantArray *CVA) {
60 const Type *ETy = cast<ArrayType>(CVA->getType())->getElementType();
61 if (ETy == Type::UByteTy) return true;
62 if (ETy != Type::SByteTy) return false;
Misha Brukmanf905ed52003-11-07 17:45:28 +000063
Misha Brukman6275a042003-11-13 00:22:19 +000064 for (unsigned i = 0; i < CVA->getNumOperands(); ++i)
65 if (cast<ConstantSInt>(CVA->getOperand(i))->getValue() < 0)
66 return false;
Misha Brukmanf905ed52003-11-07 17:45:28 +000067
Misha Brukman6275a042003-11-13 00:22:19 +000068 return true;
Misha Brukmanf905ed52003-11-07 17:45:28 +000069 }
Misha Brukmanf905ed52003-11-07 17:45:28 +000070
Misha Brukman6275a042003-11-13 00:22:19 +000071 /// getAsCString - Return the specified array as a C compatible string, only
72 /// if the predicate isStringCompatible is true.
73 ///
74 std::string getAsCString(const ConstantArray *CVA) {
75 assert(isStringCompatible(CVA) && "Array is not string compatible!");
Misha Brukmanf905ed52003-11-07 17:45:28 +000076
Misha Brukman6275a042003-11-13 00:22:19 +000077 std::string Result;
78 const Type *ETy = cast<ArrayType>(CVA->getType())->getElementType();
79 Result = "\"";
80 for (unsigned i = 0; i < CVA->getNumOperands(); ++i) {
81 unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
Misha Brukmanf905ed52003-11-07 17:45:28 +000082
Misha Brukman6275a042003-11-13 00:22:19 +000083 if (C == '"') {
84 Result += "\\\"";
85 } else if (C == '\\') {
86 Result += "\\\\";
87 } else if (isprint(C)) {
88 Result += C;
89 } else {
90 Result += '\\'; // print all other chars as octal value
91 // Convert C to octal representation
92 Result += ((C >> 6) & 7) + '0';
93 Result += ((C >> 3) & 7) + '0';
94 Result += ((C >> 0) & 7) + '0';
95 }
96 }
97 Result += "\"";
Misha Brukmanf905ed52003-11-07 17:45:28 +000098
Misha Brukman6275a042003-11-13 00:22:19 +000099 return Result;
100 }
101
102 inline bool ArrayTypeIsString(const ArrayType* arrayType) {
103 return (arrayType->getElementType() == Type::UByteTy ||
104 arrayType->getElementType() == Type::SByteTy);
105 }
106
107 inline const std::string
108 TypeToDataDirective(const Type* type) {
109 switch(type->getPrimitiveID())
Misha Brukmanf905ed52003-11-07 17:45:28 +0000110 {
111 case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
112 return ".byte";
113 case Type::UShortTyID: case Type::ShortTyID:
114 return ".half";
115 case Type::UIntTyID: case Type::IntTyID:
116 return ".word";
117 case Type::ULongTyID: case Type::LongTyID: case Type::PointerTyID:
118 return ".xword";
119 case Type::FloatTyID:
120 return ".word";
121 case Type::DoubleTyID:
122 return ".xword";
123 case Type::ArrayTyID:
124 if (ArrayTypeIsString((ArrayType*) type))
125 return ".ascii";
126 else
127 return "<InvaliDataTypeForPrinting>";
128 default:
129 return "<InvaliDataTypeForPrinting>";
130 }
Misha Brukman6275a042003-11-13 00:22:19 +0000131 }
Misha Brukmanf905ed52003-11-07 17:45:28 +0000132
Misha Brukman6275a042003-11-13 00:22:19 +0000133 /// Get the size of the constant for the given target.
134 /// If this is an unsized array, return 0.
135 ///
136 inline unsigned int
137 ConstantToSize(const Constant* CV, const TargetMachine& target) {
138 if (const ConstantArray* CVA = dyn_cast<ConstantArray>(CV)) {
Misha Brukmanf905ed52003-11-07 17:45:28 +0000139 const ArrayType *aty = cast<ArrayType>(CVA->getType());
140 if (ArrayTypeIsString(aty))
141 return 1 + CVA->getNumOperands();
142 }
143
Misha Brukman6275a042003-11-13 00:22:19 +0000144 return target.findOptimalStorageSize(CV->getType());
145 }
Misha Brukmanf905ed52003-11-07 17:45:28 +0000146
Misha Brukman6275a042003-11-13 00:22:19 +0000147 /// Align data larger than one L1 cache line on L1 cache line boundaries.
148 /// Align all smaller data on the next higher 2^x boundary (4, 8, ...).
149 ///
150 inline unsigned int
151 SizeToAlignment(unsigned int size, const TargetMachine& target) {
152 unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1);
153 if (size > (unsigned) cacheLineSize / 2)
154 return cacheLineSize;
155 else
156 for (unsigned sz=1; /*no condition*/; sz *= 2)
157 if (sz >= size)
158 return sz;
159 }
Misha Brukmanf905ed52003-11-07 17:45:28 +0000160
Misha Brukman6275a042003-11-13 00:22:19 +0000161 /// Get the size of the type and then use SizeToAlignment.
162 ///
163 inline unsigned int
164 TypeToAlignment(const Type* type, const TargetMachine& target) {
165 return SizeToAlignment(target.findOptimalStorageSize(type), target);
166 }
Misha Brukmanf905ed52003-11-07 17:45:28 +0000167
Misha Brukman6275a042003-11-13 00:22:19 +0000168 /// Get the size of the constant and then use SizeToAlignment.
169 /// Handles strings as a special case;
170 inline unsigned int
171 ConstantToAlignment(const Constant* CV, const TargetMachine& target) {
172 if (const ConstantArray* CVA = dyn_cast<ConstantArray>(CV))
173 if (ArrayTypeIsString(cast<ArrayType>(CVA->getType())))
174 return SizeToAlignment(1 + CVA->getNumOperands(), target);
Misha Brukmanf905ed52003-11-07 17:45:28 +0000175
Misha Brukman6275a042003-11-13 00:22:19 +0000176 return TypeToAlignment(CV->getType(), target);
177 }
178
179} // End anonymous namespace
180
Misha Brukman6275a042003-11-13 00:22:19 +0000181
182
Vikram S. Adved198c472002-03-18 03:07:26 +0000183//===---------------------------------------------------------------------===//
Misha Brukman6275a042003-11-13 00:22:19 +0000184// Code abstracted away from the AsmPrinter
Vikram S. Adved198c472002-03-18 03:07:26 +0000185//===---------------------------------------------------------------------===//
186
Misha Brukman6275a042003-11-13 00:22:19 +0000187namespace {
Misha Brukman6275a042003-11-13 00:22:19 +0000188 class AsmPrinter {
189 GlobalIdTable* idTable;
190 public:
191 std::ostream &toAsm;
192 const TargetMachine &Target;
Misha Brukmanf905ed52003-11-07 17:45:28 +0000193
Misha Brukman6275a042003-11-13 00:22:19 +0000194 enum Sections {
195 Unknown,
196 Text,
197 ReadOnlyData,
198 InitRWData,
199 ZeroInitRWData,
200 } CurSection;
201
202 AsmPrinter(std::ostream &os, const TargetMachine &T)
203 : idTable(0), toAsm(os), Target(T), CurSection(Unknown) {}
Misha Brukmanf905ed52003-11-07 17:45:28 +0000204
Misha Brukman6275a042003-11-13 00:22:19 +0000205 // (start|end)(Module|Function) - Callback methods invoked by subclasses
206 void startModule(Module &M) {
207 // Create the global id table if it does not already exist
208 idTable = (GlobalIdTable*)M.getAnnotation(GlobalIdTable::AnnotId);
209 if (idTable == NULL) {
Chris Lattner7446dc02004-01-13 21:27:59 +0000210 idTable = new GlobalIdTable();
Misha Brukman6275a042003-11-13 00:22:19 +0000211 M.addAnnotation(idTable);
Misha Brukmanf905ed52003-11-07 17:45:28 +0000212 }
213 }
Misha Brukmanf905ed52003-11-07 17:45:28 +0000214
Misha Brukman6275a042003-11-13 00:22:19 +0000215 void PrintZeroBytesToPad(int numBytes) {
216 for (/* no init */; numBytes >= 8; numBytes -= 8)
217 printSingleConstantValue(Constant::getNullValue(Type::ULongTy));
Misha Brukmanf905ed52003-11-07 17:45:28 +0000218
Misha Brukman6275a042003-11-13 00:22:19 +0000219 if (numBytes >= 4) {
220 printSingleConstantValue(Constant::getNullValue(Type::UIntTy));
221 numBytes -= 4;
Misha Brukmanf905ed52003-11-07 17:45:28 +0000222 }
Misha Brukman6275a042003-11-13 00:22:19 +0000223
224 while (numBytes--)
225 printSingleConstantValue(Constant::getNullValue(Type::UByteTy));
Misha Brukmanf905ed52003-11-07 17:45:28 +0000226 }
Misha Brukmanf905ed52003-11-07 17:45:28 +0000227
Misha Brukman6275a042003-11-13 00:22:19 +0000228 /// Print a single constant value.
229 ///
230 void printSingleConstantValue(const Constant* CV);
Misha Brukmanf905ed52003-11-07 17:45:28 +0000231
Misha Brukman6275a042003-11-13 00:22:19 +0000232 /// Print a constant value or values (it may be an aggregate).
233 /// Uses printSingleConstantValue() to print each individual value.
234 ///
235 void printConstantValueOnly(const Constant* CV, int numPadBytesAfter = 0);
236
237 // Print a constant (which may be an aggregate) prefixed by all the
238 // appropriate directives. Uses printConstantValueOnly() to print the
239 // value or values.
240 void printConstant(const Constant* CV, std::string valID = "") {
241 if (valID.length() == 0)
242 valID = getID(CV);
Misha Brukmanf905ed52003-11-07 17:45:28 +0000243
Misha Brukman6275a042003-11-13 00:22:19 +0000244 toAsm << "\t.align\t" << ConstantToAlignment(CV, Target) << "\n";
Misha Brukmanf905ed52003-11-07 17:45:28 +0000245
Misha Brukman6275a042003-11-13 00:22:19 +0000246 // Print .size and .type only if it is not a string.
247 const ConstantArray *CVA = dyn_cast<ConstantArray>(CV);
248 if (CVA && isStringCompatible(CVA)) {
249 // print it as a string and return
250 toAsm << valID << ":\n";
251 toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n";
252 return;
253 }
254
255 toAsm << "\t.type" << "\t" << valID << ",#object\n";
256
257 unsigned int constSize = ConstantToSize(CV, Target);
258 if (constSize)
259 toAsm << "\t.size" << "\t" << valID << "," << constSize << "\n";
260
Misha Brukmanf905ed52003-11-07 17:45:28 +0000261 toAsm << valID << ":\n";
Misha Brukman6275a042003-11-13 00:22:19 +0000262
263 printConstantValueOnly(CV);
264 }
265
Misha Brukman6275a042003-11-13 00:22:19 +0000266 // enterSection - Use this method to enter a different section of the output
267 // executable. This is used to only output necessary section transitions.
268 //
269 void enterSection(enum Sections S) {
270 if (S == CurSection) return; // Only switch section if necessary
271 CurSection = S;
Misha Brukmanf905ed52003-11-07 17:45:28 +0000272
Misha Brukman6275a042003-11-13 00:22:19 +0000273 toAsm << "\n\t.section ";
274 switch (S)
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000275 {
276 default: assert(0 && "Bad section name!");
277 case Text: toAsm << "\".text\""; break;
278 case ReadOnlyData: toAsm << "\".rodata\",#alloc"; break;
279 case InitRWData: toAsm << "\".data\",#alloc,#write"; break;
280 case ZeroInitRWData: toAsm << "\".bss\",#alloc,#write"; break;
281 }
Misha Brukman6275a042003-11-13 00:22:19 +0000282 toAsm << "\n";
283 }
Chris Lattnere88f78c2001-09-19 13:47:27 +0000284
Misha Brukman6275a042003-11-13 00:22:19 +0000285 static std::string getValidSymbolName(const std::string &S) {
286 std::string Result;
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000287
Misha Brukman6275a042003-11-13 00:22:19 +0000288 // Symbol names in Sparc assembly language have these rules:
289 // (a) Must match { letter | _ | . | $ } { letter | _ | . | $ | digit }*
290 // (b) A name beginning in "." is treated as a local name.
291 //
292 if (isdigit(S[0]))
293 Result = "ll";
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000294
Misha Brukman6275a042003-11-13 00:22:19 +0000295 for (unsigned i = 0; i < S.size(); ++i) {
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000296 char C = S[i];
297 if (C == '_' || C == '.' || C == '$' || isalpha(C) || isdigit(C))
298 Result += C;
Misha Brukman6275a042003-11-13 00:22:19 +0000299 else {
300 Result += '_';
301 Result += char('0' + ((unsigned char)C >> 4));
302 Result += char('0' + (C & 0xF));
303 }
Chris Lattnerc56d7792001-09-28 15:07:24 +0000304 }
Misha Brukman6275a042003-11-13 00:22:19 +0000305 return Result;
Chris Lattnere88f78c2001-09-19 13:47:27 +0000306 }
Vikram S. Adve96918072002-10-30 20:16:38 +0000307
Misha Brukman6275a042003-11-13 00:22:19 +0000308 // getID - Return a valid identifier for the specified value. Base it on
309 // the name of the identifier if possible (qualified by the type), and
310 // use a numbered value based on prefix otherwise.
311 // FPrefix is always prepended to the output identifier.
312 //
313 std::string getID(const Value *V, const char *Prefix,
Chris Lattner7446dc02004-01-13 21:27:59 +0000314 const char *FPrefix = "")
Misha Brukman6275a042003-11-13 00:22:19 +0000315 {
Chris Lattner7446dc02004-01-13 21:27:59 +0000316 std::string Result = FPrefix; // "Forced prefix"
Misha Brukman6275a042003-11-13 00:22:19 +0000317
318 Result += V->hasName() ? V->getName() : std::string(Prefix);
319
320 // Qualify all internal names with a unique id.
Chris Lattner7446dc02004-01-13 21:27:59 +0000321 if (!isa<GlobalValue>(V) || !cast<GlobalValue>(V)->hasExternalLinkage()) {
322 unsigned &ValID = idTable->AnonymousObjectMap[V];
323 if (ValID == 0)
324 ValID = ++idTable->LastAnonIDUsed;
325
326 Result += "_" + utostr(ValID);
Misha Brukman6275a042003-11-13 00:22:19 +0000327
328 // Replace or prefix problem characters in the name
329 Result = getValidSymbolName(Result);
330 }
331
332 return Result;
333 }
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000334
Misha Brukman6275a042003-11-13 00:22:19 +0000335 // getID Wrappers - Ensure consistent usage...
336 std::string getID(const Function *F) {
337 return getID(F, "LLVMFunction_");
338 }
339 std::string getID(const BasicBlock *BB) {
340 return getID(BB, "LL", (".L_"+getID(BB->getParent())+"_").c_str());
341 }
342 std::string getID(const GlobalVariable *GV) {
343 return getID(GV, "LLVMGlobal_");
344 }
345 std::string getID(const Constant *CV) {
346 return getID(CV, "LLVMConst_", ".C_");
347 }
348 std::string getID(const GlobalValue *GV) {
349 if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV))
350 return getID(V);
351 else if (const Function *F = dyn_cast<Function>(GV))
352 return getID(F);
353 assert(0 && "Unexpected type of GlobalValue!");
354 return "";
355 }
Vikram S. Advee99941a2002-08-22 02:58:36 +0000356
Misha Brukman6275a042003-11-13 00:22:19 +0000357 // Combines expressions
358 inline std::string ConstantArithExprToString(const ConstantExpr* CE,
359 const TargetMachine &TM,
360 const std::string &op) {
361 return "(" + valToExprString(CE->getOperand(0), TM) + op
362 + valToExprString(CE->getOperand(1), TM) + ")";
363 }
Misha Brukmanf4de7832003-08-05 16:01:50 +0000364
Misha Brukman6275a042003-11-13 00:22:19 +0000365 /// ConstantExprToString() - Convert a ConstantExpr to an asm expression
366 /// and return this as a string.
367 ///
368 std::string ConstantExprToString(const ConstantExpr* CE,
369 const TargetMachine& target);
370
371 /// valToExprString - Helper function for ConstantExprToString().
372 /// Appends result to argument string S.
373 ///
374 std::string valToExprString(const Value* V, const TargetMachine& target);
375 };
Misha Brukman6275a042003-11-13 00:22:19 +0000376} // End anonymous namespace
377
Misha Brukman6275a042003-11-13 00:22:19 +0000378
379/// Print a single constant value.
380///
381void AsmPrinter::printSingleConstantValue(const Constant* CV) {
382 assert(CV->getType() != Type::VoidTy &&
383 CV->getType() != Type::TypeTy &&
384 CV->getType() != Type::LabelTy &&
385 "Unexpected type for Constant");
386
387 assert((!isa<ConstantArray>(CV) && ! isa<ConstantStruct>(CV))
388 && "Aggregate types should be handled outside this function");
389
390 toAsm << "\t" << TypeToDataDirective(CV->getType()) << "\t";
391
392 if (const ConstantPointerRef* CPR = dyn_cast<ConstantPointerRef>(CV)) {
393 // This is a constant address for a global variable or method.
394 // Use the name of the variable or method as the address value.
395 assert(isa<GlobalValue>(CPR->getValue()) && "Unexpected non-global");
396 toAsm << getID(CPR->getValue()) << "\n";
397 } else if (isa<ConstantPointerNull>(CV)) {
398 // Null pointer value
399 toAsm << "0\n";
400 } else if (const ConstantExpr* CE = dyn_cast<ConstantExpr>(CV)) {
401 // Constant expression built from operators, constants, and symbolic addrs
402 toAsm << ConstantExprToString(CE, Target) << "\n";
403 } else if (CV->getType()->isPrimitiveType()) {
404 // Check primitive types last
405 if (CV->getType()->isFloatingPoint()) {
406 // FP Constants are printed as integer constants to avoid losing
407 // precision...
408 double Val = cast<ConstantFP>(CV)->getValue();
409 if (CV->getType() == Type::FloatTy) {
410 float FVal = (float)Val;
411 char *ProxyPtr = (char*)&FVal; // Abide by C TBAA rules
412 toAsm << *(unsigned int*)ProxyPtr;
413 } else if (CV->getType() == Type::DoubleTy) {
414 char *ProxyPtr = (char*)&Val; // Abide by C TBAA rules
415 toAsm << *(uint64_t*)ProxyPtr;
416 } else {
417 assert(0 && "Unknown floating point type!");
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000418 }
Misha Brukman6275a042003-11-13 00:22:19 +0000419
420 toAsm << "\t! " << CV->getType()->getDescription()
421 << " value: " << Val << "\n";
422 } else {
423 WriteAsOperand(toAsm, CV, false, false) << "\n";
424 }
425 } else {
426 assert(0 && "Unknown elementary type for constant");
427 }
428}
Vikram S. Advee99941a2002-08-22 02:58:36 +0000429
Misha Brukman6275a042003-11-13 00:22:19 +0000430/// Print a constant value or values (it may be an aggregate).
431/// Uses printSingleConstantValue() to print each individual value.
432///
433void AsmPrinter::printConstantValueOnly(const Constant* CV,
434 int numPadBytesAfter)
435{
436 const ConstantArray *CVA = dyn_cast<ConstantArray>(CV);
Vikram S. Adve537a8772002-09-05 18:28:10 +0000437
Misha Brukman6275a042003-11-13 00:22:19 +0000438 if (CVA && isStringCompatible(CVA)) {
439 // print the string alone and return
440 toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n";
441 } else if (CVA) {
442 // Not a string. Print the values in successive locations
443 const std::vector<Use> &constValues = CVA->getValues();
444 for (unsigned i=0; i < constValues.size(); i++)
445 printConstantValueOnly(cast<Constant>(constValues[i].get()));
446 } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
447 // Print the fields in successive locations. Pad to align if needed!
448 const StructLayout *cvsLayout =
449 Target.getTargetData().getStructLayout(CVS->getType());
450 const std::vector<Use>& constValues = CVS->getValues();
451 unsigned sizeSoFar = 0;
452 for (unsigned i=0, N = constValues.size(); i < N; i++) {
453 const Constant* field = cast<Constant>(constValues[i].get());
Vikram S. Adve537a8772002-09-05 18:28:10 +0000454
Misha Brukman6275a042003-11-13 00:22:19 +0000455 // Check if padding is needed and insert one or more 0s.
456 unsigned fieldSize =
457 Target.getTargetData().getTypeSize(field->getType());
458 int padSize = ((i == N-1? cvsLayout->StructSize
459 : cvsLayout->MemberOffsets[i+1])
460 - cvsLayout->MemberOffsets[i]) - fieldSize;
461 sizeSoFar += (fieldSize + padSize);
Vikram S. Adve72666e62003-08-01 15:55:53 +0000462
Misha Brukman6275a042003-11-13 00:22:19 +0000463 // Now print the actual field value
464 printConstantValueOnly(field, padSize);
465 }
466 assert(sizeSoFar == cvsLayout->StructSize &&
467 "Layout of constant struct may be incorrect!");
468 }
469 else
470 printSingleConstantValue(CV);
Vikram S. Adve72666e62003-08-01 15:55:53 +0000471
Misha Brukman6275a042003-11-13 00:22:19 +0000472 if (numPadBytesAfter)
473 PrintZeroBytesToPad(numPadBytesAfter);
474}
Vikram S. Adve72666e62003-08-01 15:55:53 +0000475
Misha Brukman6275a042003-11-13 00:22:19 +0000476/// ConstantExprToString() - Convert a ConstantExpr to an asm expression
477/// and return this as a string.
478///
479std::string AsmPrinter::ConstantExprToString(const ConstantExpr* CE,
480 const TargetMachine& target) {
481 std::string S;
482 switch(CE->getOpcode()) {
483 case Instruction::GetElementPtr:
484 { // generate a symbolic expression for the byte address
485 const Value* ptrVal = CE->getOperand(0);
486 std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
487 const TargetData &TD = target.getTargetData();
488 S += "(" + valToExprString(ptrVal, target) + ") + ("
489 + utostr(TD.getIndexedOffset(ptrVal->getType(),idxVec)) + ")";
Vikram S. Advee99941a2002-08-22 02:58:36 +0000490 break;
491 }
492
Misha Brukman6275a042003-11-13 00:22:19 +0000493 case Instruction::Cast:
494 // Support only non-converting casts for now, i.e., a no-op.
495 // This assertion is not a complete check.
496 assert(target.getTargetData().getTypeSize(CE->getType()) ==
497 target.getTargetData().getTypeSize(CE->getOperand(0)->getType()));
498 S += "(" + valToExprString(CE->getOperand(0), target) + ")";
499 break;
500
501 case Instruction::Add:
502 S += ConstantArithExprToString(CE, target, ") + (");
503 break;
504
505 case Instruction::Sub:
506 S += ConstantArithExprToString(CE, target, ") - (");
507 break;
508
509 case Instruction::Mul:
510 S += ConstantArithExprToString(CE, target, ") * (");
511 break;
512
513 case Instruction::Div:
514 S += ConstantArithExprToString(CE, target, ") / (");
515 break;
516
517 case Instruction::Rem:
518 S += ConstantArithExprToString(CE, target, ") % (");
519 break;
520
521 case Instruction::And:
522 // Logical && for booleans; bitwise & otherwise
523 S += ConstantArithExprToString(CE, target,
524 ((CE->getType() == Type::BoolTy)? ") && (" : ") & ("));
525 break;
526
527 case Instruction::Or:
528 // Logical || for booleans; bitwise | otherwise
529 S += ConstantArithExprToString(CE, target,
530 ((CE->getType() == Type::BoolTy)? ") || (" : ") | ("));
531 break;
532
533 case Instruction::Xor:
534 // Bitwise ^ for all types
535 S += ConstantArithExprToString(CE, target, ") ^ (");
536 break;
537
538 default:
539 assert(0 && "Unsupported operator in ConstantExprToString()");
540 break;
Vikram S. Advee99941a2002-08-22 02:58:36 +0000541 }
542
Misha Brukman6275a042003-11-13 00:22:19 +0000543 return S;
544}
Vikram S. Advee99941a2002-08-22 02:58:36 +0000545
Misha Brukman6275a042003-11-13 00:22:19 +0000546/// valToExprString - Helper function for ConstantExprToString().
547/// Appends result to argument string S.
548///
549std::string AsmPrinter::valToExprString(const Value* V,
550 const TargetMachine& target) {
551 std::string S;
552 bool failed = false;
553 if (const Constant* CV = dyn_cast<Constant>(V)) { // symbolic or known
554 if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV))
555 S += std::string(CB == ConstantBool::True ? "1" : "0");
556 else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
557 S += itostr(CI->getValue());
558 else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
559 S += utostr(CI->getValue());
560 else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))
561 S += ftostr(CFP->getValue());
562 else if (isa<ConstantPointerNull>(CV))
563 S += "0";
564 else if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(CV))
565 S += valToExprString(CPR->getValue(), target);
566 else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV))
567 S += ConstantExprToString(CE, target);
Vikram S. Advee99941a2002-08-22 02:58:36 +0000568 else
569 failed = true;
Misha Brukman6275a042003-11-13 00:22:19 +0000570 } else if (const GlobalValue* GV = dyn_cast<GlobalValue>(V)) {
571 S += getID(GV);
572 } else
573 failed = true;
Vikram S. Advee99941a2002-08-22 02:58:36 +0000574
Misha Brukman6275a042003-11-13 00:22:19 +0000575 if (failed) {
576 assert(0 && "Cannot convert value to string");
577 S += "<illegal-value>";
Vikram S. Advee99941a2002-08-22 02:58:36 +0000578 }
Misha Brukman6275a042003-11-13 00:22:19 +0000579 return S;
580}
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000581
582
583//===----------------------------------------------------------------------===//
Misha Brukman6275a042003-11-13 00:22:19 +0000584// SparcAsmPrinter Code
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000585//===----------------------------------------------------------------------===//
586
Misha Brukman6275a042003-11-13 00:22:19 +0000587namespace {
Misha Brukmanf905ed52003-11-07 17:45:28 +0000588
Misha Brukman6275a042003-11-13 00:22:19 +0000589 struct SparcAsmPrinter : public FunctionPass, public AsmPrinter {
590 inline SparcAsmPrinter(std::ostream &os, const TargetMachine &t)
591 : AsmPrinter(os, t) {}
Chris Lattner96c466b2002-04-29 14:57:45 +0000592
Misha Brukman6275a042003-11-13 00:22:19 +0000593 const Function *currFunction;
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000594
Misha Brukman6275a042003-11-13 00:22:19 +0000595 const char *getPassName() const {
596 return "Output Sparc Assembly for Functions";
Chris Lattnere88f78c2001-09-19 13:47:27 +0000597 }
Misha Brukman6275a042003-11-13 00:22:19 +0000598
599 virtual bool doInitialization(Module &M) {
600 startModule(M);
601 return false;
602 }
603
604 virtual bool runOnFunction(Function &F) {
605 currFunction = &F;
Misha Brukman6275a042003-11-13 00:22:19 +0000606 emitFunction(F);
Misha Brukman6275a042003-11-13 00:22:19 +0000607 return false;
608 }
609
610 virtual bool doFinalization(Module &M) {
611 emitGlobals(M);
612 return false;
613 }
614
615 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
616 AU.setPreservesAll();
617 }
618
619 void emitFunction(const Function &F);
620 private :
621 void emitBasicBlock(const MachineBasicBlock &MBB);
622 void emitMachineInst(const MachineInstr *MI);
623
624 unsigned int printOperands(const MachineInstr *MI, unsigned int opNum);
625 void printOneOperand(const MachineOperand &Op, MachineOpCode opCode);
626
627 bool OpIsBranchTargetLabel(const MachineInstr *MI, unsigned int opNum);
628 bool OpIsMemoryAddressBase(const MachineInstr *MI, unsigned int opNum);
629
630 unsigned getOperandMask(unsigned Opcode) {
631 switch (Opcode) {
632 case V9::SUBccr:
633 case V9::SUBcci: return 1 << 3; // Remove CC argument
634 default: return 0; // By default, don't hack operands...
635 }
636 }
637
638 void emitGlobals(const Module &M);
639 void printGlobalVariable(const GlobalVariable *GV);
640 };
641
642} // End anonymous namespace
Chris Lattnere88f78c2001-09-19 13:47:27 +0000643
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000644inline bool
Misha Brukman6275a042003-11-13 00:22:19 +0000645SparcAsmPrinter::OpIsBranchTargetLabel(const MachineInstr *MI,
646 unsigned int opNum) {
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000647 switch (MI->getOpCode()) {
Misha Brukman71ed1c92003-05-27 22:35:43 +0000648 case V9::JMPLCALLr:
649 case V9::JMPLCALLi:
650 case V9::JMPLRETr:
651 case V9::JMPLRETi:
Misha Brukmana98cd452003-05-20 20:32:24 +0000652 return (opNum == 0);
653 default:
654 return false;
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000655 }
656}
657
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000658inline bool
Misha Brukman6275a042003-11-13 00:22:19 +0000659SparcAsmPrinter::OpIsMemoryAddressBase(const MachineInstr *MI,
660 unsigned int opNum) {
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000661 if (Target.getInstrInfo().isLoad(MI->getOpCode()))
662 return (opNum == 0);
663 else if (Target.getInstrInfo().isStore(MI->getOpCode()))
664 return (opNum == 1);
665 else
666 return false;
667}
668
669
Vikram S. Adve78a4f232003-05-27 00:02:22 +0000670#define PrintOp1PlusOp2(mop1, mop2, opCode) \
671 printOneOperand(mop1, opCode); \
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000672 toAsm << "+"; \
Vikram S. Adve78a4f232003-05-27 00:02:22 +0000673 printOneOperand(mop2, opCode);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000674
675unsigned int
Misha Brukman6275a042003-11-13 00:22:19 +0000676SparcAsmPrinter::printOperands(const MachineInstr *MI,
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000677 unsigned int opNum)
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000678{
Vikram S. Adve195a5d52002-07-10 21:41:21 +0000679 const MachineOperand& mop = MI->getOperand(opNum);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000680
Misha Brukman6275a042003-11-13 00:22:19 +0000681 if (OpIsBranchTargetLabel(MI, opNum)) {
682 PrintOp1PlusOp2(mop, MI->getOperand(opNum+1), MI->getOpCode());
683 return 2;
684 } else if (OpIsMemoryAddressBase(MI, opNum)) {
685 toAsm << "[";
686 PrintOp1PlusOp2(mop, MI->getOperand(opNum+1), MI->getOpCode());
687 toAsm << "]";
688 return 2;
689 } else {
690 printOneOperand(mop, MI->getOpCode());
691 return 1;
692 }
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000693}
694
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000695void
Misha Brukman6275a042003-11-13 00:22:19 +0000696SparcAsmPrinter::printOneOperand(const MachineOperand &mop,
697 MachineOpCode opCode)
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000698{
Vikram S. Adve195a5d52002-07-10 21:41:21 +0000699 bool needBitsFlag = true;
700
Alkis Evlogimenos4d7af652003-12-14 13:24:17 +0000701 if (mop.isHiBits32())
Vikram S. Adve195a5d52002-07-10 21:41:21 +0000702 toAsm << "%lm(";
Alkis Evlogimenos4d7af652003-12-14 13:24:17 +0000703 else if (mop.isLoBits32())
Vikram S. Adve195a5d52002-07-10 21:41:21 +0000704 toAsm << "%lo(";
Alkis Evlogimenos4d7af652003-12-14 13:24:17 +0000705 else if (mop.isHiBits64())
Vikram S. Adve195a5d52002-07-10 21:41:21 +0000706 toAsm << "%hh(";
Alkis Evlogimenos4d7af652003-12-14 13:24:17 +0000707 else if (mop.isLoBits64())
Vikram S. Adve195a5d52002-07-10 21:41:21 +0000708 toAsm << "%hm(";
709 else
710 needBitsFlag = false;
711
Chris Lattner133f0792002-10-28 04:45:29 +0000712 switch (mop.getType())
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000713 {
Vikram S. Adve786833a2003-07-06 20:13:59 +0000714 case MachineOperand::MO_VirtualRegister:
Vikram S. Adveb15f8d42003-07-10 19:42:11 +0000715 case MachineOperand::MO_CCRegister:
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000716 case MachineOperand::MO_MachineRegister:
717 {
718 int regNum = (int)mop.getAllocatedRegNum();
Vikram S. Adveb15f8d42003-07-10 19:42:11 +0000719
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000720 if (regNum == Target.getRegInfo().getInvalidRegNum()) {
721 // better to print code with NULL registers than to die
722 toAsm << "<NULL VALUE>";
723 } else {
724 toAsm << "%" << Target.getRegInfo().getUnifiedRegName(regNum);
725 }
726 break;
727 }
Misha Brukmanb3fabe02003-05-31 06:22:37 +0000728
Misha Brukmanf905ed52003-11-07 17:45:28 +0000729 case MachineOperand::MO_ConstantPoolIndex:
730 {
731 toAsm << ".CPI_" << currFunction->getName()
732 << "_" << mop.getConstantPoolIndex();
733 break;
734 }
735
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000736 case MachineOperand::MO_PCRelativeDisp:
737 {
738 const Value *Val = mop.getVRegValue();
Misha Brukman6275a042003-11-13 00:22:19 +0000739 assert(Val && "\tNULL Value in SparcAsmPrinter");
Misha Brukmanb3fabe02003-05-31 06:22:37 +0000740
Chris Lattner949a3622003-07-23 15:30:06 +0000741 if (const BasicBlock *BB = dyn_cast<BasicBlock>(Val))
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000742 toAsm << getID(BB);
743 else if (const Function *M = dyn_cast<Function>(Val))
744 toAsm << getID(M);
745 else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Val))
746 toAsm << getID(GV);
747 else if (const Constant *CV = dyn_cast<Constant>(Val))
748 toAsm << getID(CV);
749 else
Misha Brukman6275a042003-11-13 00:22:19 +0000750 assert(0 && "Unrecognized value in SparcAsmPrinter");
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000751 break;
752 }
Misha Brukmanb3fabe02003-05-31 06:22:37 +0000753
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000754 case MachineOperand::MO_SignExtendedImmed:
755 toAsm << mop.getImmedValue();
756 break;
Misha Brukmanb3fabe02003-05-31 06:22:37 +0000757
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000758 case MachineOperand::MO_UnextendedImmed:
759 toAsm << (uint64_t) mop.getImmedValue();
760 break;
Misha Brukmanb3fabe02003-05-31 06:22:37 +0000761
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000762 default:
763 toAsm << mop; // use dump field
764 break;
765 }
Vikram S. Adve195a5d52002-07-10 21:41:21 +0000766
767 if (needBitsFlag)
768 toAsm << ")";
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000769}
770
Misha Brukman6275a042003-11-13 00:22:19 +0000771void SparcAsmPrinter::emitMachineInst(const MachineInstr *MI) {
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000772 unsigned Opcode = MI->getOpCode();
773
Vikram S. Advec227a9a2002-11-06 00:34:26 +0000774 if (Target.getInstrInfo().isDummyPhiInstr(Opcode))
Vikram S. Adveaf9fd512003-05-31 07:27:17 +0000775 return; // IGNORE PHI NODES
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000776
Chris Lattnerf44f9052002-10-29 17:35:41 +0000777 toAsm << "\t" << Target.getInstrInfo().getName(Opcode) << "\t";
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000778
779 unsigned Mask = getOperandMask(Opcode);
780
781 bool NeedComma = false;
782 unsigned N = 1;
783 for (unsigned OpNum = 0; OpNum < MI->getNumOperands(); OpNum += N)
784 if (! ((1 << OpNum) & Mask)) { // Ignore this operand?
Misha Brukman8b2fe192003-09-23 17:27:28 +0000785 if (NeedComma) toAsm << ", "; // Handle comma outputting
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000786 NeedComma = true;
787 N = printOperands(MI, OpNum);
Chris Lattnerebdc7f32002-11-17 22:57:23 +0000788 } else
789 N = 1;
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000790
791 toAsm << "\n";
Brian Gaeke2c9b9132003-10-06 15:41:21 +0000792 ++EmittedInsts;
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000793}
794
Misha Brukman6275a042003-11-13 00:22:19 +0000795void SparcAsmPrinter::emitBasicBlock(const MachineBasicBlock &MBB) {
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000796 // Emit a label for the basic block
Misha Brukmane585a7d2002-10-28 20:01:13 +0000797 toAsm << getID(MBB.getBasicBlock()) << ":\n";
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000798
799 // Loop over all of the instructions in the basic block...
Misha Brukmane585a7d2002-10-28 20:01:13 +0000800 for (MachineBasicBlock::const_iterator MII = MBB.begin(), MIE = MBB.end();
Chris Lattner55291ea2002-10-28 01:41:47 +0000801 MII != MIE; ++MII)
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000802 emitMachineInst(*MII);
Misha Brukmanbc0e9982003-07-14 17:20:40 +0000803 toAsm << "\n"; // Separate BB's with newlines
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000804}
805
Misha Brukman6275a042003-11-13 00:22:19 +0000806void SparcAsmPrinter::emitFunction(const Function &F) {
Misha Brukmanf4de7832003-08-05 16:01:50 +0000807 std::string methName = getID(&F);
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000808 toAsm << "!****** Outputing Function: " << methName << " ******\n";
Misha Brukmanf905ed52003-11-07 17:45:28 +0000809
810 // Emit constant pool for this function
811 const MachineConstantPool *MCP = MachineFunction::get(&F).getConstantPool();
812 const std::vector<Constant*> &CP = MCP->getConstants();
813
814 enterSection(AsmPrinter::ReadOnlyData);
815 for (unsigned i = 0, e = CP.size(); i != e; ++i) {
816 std::string cpiName = ".CPI_" + F.getName() + "_" + utostr(i);
817 printConstant(CP[i], cpiName);
818 }
819
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000820 enterSection(AsmPrinter::Text);
821 toAsm << "\t.align\t4\n\t.global\t" << methName << "\n";
822 //toAsm << "\t.type\t" << methName << ",#function\n";
823 toAsm << "\t.type\t" << methName << ", 2\n";
824 toAsm << methName << ":\n";
825
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000826 // Output code for all of the basic blocks in the function...
Misha Brukmane585a7d2002-10-28 20:01:13 +0000827 MachineFunction &MF = MachineFunction::get(&F);
Chris Lattnerd0fe5f52002-12-28 20:15:01 +0000828 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E;++I)
Misha Brukmane585a7d2002-10-28 20:01:13 +0000829 emitBasicBlock(*I);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000830
831 // Output a .size directive so the debugger knows the extents of the function
832 toAsm << ".EndOf_" << methName << ":\n\t.size "
833 << methName << ", .EndOf_"
834 << methName << "-" << methName << "\n";
835
Chris Lattner2fbfdcf2002-04-07 20:49:59 +0000836 // Put some spaces between the functions
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000837 toAsm << "\n\n";
838}
839
Misha Brukman6275a042003-11-13 00:22:19 +0000840void SparcAsmPrinter::printGlobalVariable(const GlobalVariable* GV) {
Vikram S. Adve13f1d712002-09-16 15:54:02 +0000841 if (GV->hasExternalLinkage())
842 toAsm << "\t.global\t" << getID(GV) << "\n";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000843
Misha Brukman6275a042003-11-13 00:22:19 +0000844 if (GV->hasInitializer() && ! GV->getInitializer()->isNullValue()) {
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000845 printConstant(GV->getInitializer(), getID(GV));
Misha Brukman6275a042003-11-13 00:22:19 +0000846 } else {
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000847 toAsm << "\t.align\t" << TypeToAlignment(GV->getType()->getElementType(),
848 Target) << "\n";
Chris Lattner697954c2002-01-20 22:54:45 +0000849 toAsm << "\t.type\t" << getID(GV) << ",#object\n";
Vikram S. Adveffbba0f2001-11-08 14:29:57 +0000850 toAsm << "\t.reserve\t" << getID(GV) << ","
Misha Brukman6275a042003-11-13 00:22:19 +0000851 << Target.findOptimalStorageSize(GV->getType()->getElementType())
Chris Lattner697954c2002-01-20 22:54:45 +0000852 << "\n";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000853 }
854}
855
Misha Brukman6275a042003-11-13 00:22:19 +0000856void SparcAsmPrinter::emitGlobals(const Module &M) {
Chris Lattner637ed862002-08-07 21:39:48 +0000857 // Output global variables...
Vikram S. Advefee76262002-10-13 00:32:18 +0000858 for (Module::const_giterator GI = M.gbegin(), GE = M.gend(); GI != GE; ++GI)
859 if (! GI->isExternal()) {
860 assert(GI->hasInitializer());
861 if (GI->isConstant())
862 enterSection(AsmPrinter::ReadOnlyData); // read-only, initialized data
863 else if (GI->getInitializer()->isNullValue())
864 enterSection(AsmPrinter::ZeroInitRWData); // read-write zero data
865 else
866 enterSection(AsmPrinter::InitRWData); // read-write non-zero data
867
868 printGlobalVariable(GI);
Chris Lattner637ed862002-08-07 21:39:48 +0000869 }
Chris Lattner637ed862002-08-07 21:39:48 +0000870
Chris Lattner697954c2002-01-20 22:54:45 +0000871 toAsm << "\n";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000872}
873
Chris Lattner7446dc02004-01-13 21:27:59 +0000874FunctionPass *llvm::createAsmPrinterPass(std::ostream &Out,
875 const TargetMachine &TM) {
Misha Brukman6275a042003-11-13 00:22:19 +0000876 return new SparcAsmPrinter(Out, TM);
Chris Lattnerc019a172002-02-03 07:48:06 +0000877}