blob: 6159f98e9bcaa35b67548688467b9e3335ffa643 [file] [log] [blame]
Chris Lattnere88f78c2001-09-19 13:47:27 +00001//===-- EmitAssembly.cpp - Emit Sparc Specific .s File ---------------------==//
2//
3// This file implements all of the stuff neccesary to output a .s file from
4// LLVM. The code in this file assumes that the specified module has already
5// been compiled into the internal data structures of the Module.
6//
Chris Lattnerc19b8b12002-02-03 23:41:08 +00007// This code largely consists of two LLVM Pass's: a MethodPass and a Pass. The
8// MethodPass is pipelined together with all of the rest of the code generation
9// stages, and the Pass runs at the end to emit code for global variables and
10// such.
Chris Lattnere88f78c2001-09-19 13:47:27 +000011//
12//===----------------------------------------------------------------------===//
13
14#include "SparcInternals.h"
15#include "llvm/Analysis/SlotCalculator.h"
16#include "llvm/CodeGen/MachineInstr.h"
Chris Lattnerc019a172002-02-03 07:48:06 +000017#include "llvm/CodeGen/MachineCodeForMethod.h"
Vikram S. Adve953c83e2001-10-28 21:38:52 +000018#include "llvm/GlobalVariable.h"
Chris Lattnere9bb2df2001-12-03 22:26:30 +000019#include "llvm/ConstantVals.h"
Vikram S. Adve953c83e2001-10-28 21:38:52 +000020#include "llvm/DerivedTypes.h"
Chris Lattnere88f78c2001-09-19 13:47:27 +000021#include "llvm/BasicBlock.h"
22#include "llvm/Method.h"
23#include "llvm/Module.h"
Chris Lattnercee8f9a2001-11-27 00:03:19 +000024#include "Support/StringExtras.h"
25#include "Support/HashExtras.h"
Chris Lattner697954c2002-01-20 22:54:45 +000026using std::string;
Chris Lattnere88f78c2001-09-19 13:47:27 +000027
28namespace {
29
Chris Lattnerc19b8b12002-02-03 23:41:08 +000030//===----------------------------------------------------------------------===//
31// Code Shared By the two printer passes, as a mixin
32//===----------------------------------------------------------------------===//
Chris Lattnere88f78c2001-09-19 13:47:27 +000033
Chris Lattnerc19b8b12002-02-03 23:41:08 +000034class AsmPrinter {
Chris Lattner697954c2002-01-20 22:54:45 +000035 typedef std::hash_map<const Value*, int> ValIdMap;
Vikram S. Adve953c83e2001-10-28 21:38:52 +000036 typedef ValIdMap:: iterator ValIdMapIterator;
37 typedef ValIdMap::const_iterator ValIdMapConstIterator;
38
Chris Lattnerc19b8b12002-02-03 23:41:08 +000039 SlotCalculator *Table; // map anonymous values to unique integer IDs
40 ValIdMap valToIdMap; // used for values not handled by SlotCalculator
41public:
Chris Lattner697954c2002-01-20 22:54:45 +000042 std::ostream &toAsm;
Vikram S. Adve953c83e2001-10-28 21:38:52 +000043 const UltraSparc &Target;
Chris Lattnerc19b8b12002-02-03 23:41:08 +000044
Chris Lattnere88f78c2001-09-19 13:47:27 +000045 enum Sections {
46 Unknown,
47 Text,
Vikram S. Adve953c83e2001-10-28 21:38:52 +000048 ReadOnlyData,
49 InitRWData,
50 UninitRWData,
Chris Lattnere88f78c2001-09-19 13:47:27 +000051 } CurSection;
Chris Lattnerc19b8b12002-02-03 23:41:08 +000052
53 AsmPrinter(std::ostream &os, const UltraSparc &T)
54 : Table(0), toAsm(os), Target(T), CurSection(Unknown) {}
55
56
57 // (start|end)(Module|Method) - Callback methods to be invoked by subclasses
58 void startModule(Module *M) {
59 Table = new SlotCalculator(M, true);
60 }
61 void startMethod(Method *M) {
62 // Make sure the slot table has information about this method...
63 Table->incorporateMethod(M);
64 }
65 void endMethod(Method *M) {
66 Table->purgeMethod(); // Forget all about M.
67 }
68 void endModule() {
69 delete Table; Table = 0;
70 valToIdMap.clear();
Chris Lattnere88f78c2001-09-19 13:47:27 +000071 }
72
Vikram S. Adve953c83e2001-10-28 21:38:52 +000073
Chris Lattnere88f78c2001-09-19 13:47:27 +000074 // enterSection - Use this method to enter a different section of the output
75 // executable. This is used to only output neccesary section transitions.
76 //
77 void enterSection(enum Sections S) {
78 if (S == CurSection) return; // Only switch section if neccesary
79 CurSection = S;
80
Vikram S. Adve29ff8732001-11-08 05:12:37 +000081 toAsm << "\n\t.section ";
Vikram S. Adve953c83e2001-10-28 21:38:52 +000082 switch (S)
83 {
84 default: assert(0 && "Bad section name!");
Vikram S. Adve29ff8732001-11-08 05:12:37 +000085 case Text: toAsm << "\".text\""; break;
86 case ReadOnlyData: toAsm << "\".rodata\",#alloc"; break;
87 case InitRWData: toAsm << "\".data\",#alloc,#write"; break;
88 case UninitRWData: toAsm << "\".bss\",#alloc,#write\nBbss.bss:"; break;
Vikram S. Adve953c83e2001-10-28 21:38:52 +000089 }
Vikram S. Adve29ff8732001-11-08 05:12:37 +000090 toAsm << "\n";
Chris Lattnere88f78c2001-09-19 13:47:27 +000091 }
92
Chris Lattnerc19b8b12002-02-03 23:41:08 +000093 static std::string getValidSymbolName(const string &S) {
Chris Lattnerc56d7792001-09-28 15:07:24 +000094 string Result;
Vikram S. Adve29ff8732001-11-08 05:12:37 +000095
96 // Symbol names in Sparc assembly language have these rules:
97 // (a) Must match { letter | _ | . | $ } { letter | _ | . | $ | digit }*
98 // (b) A name beginning in "." is treated as a local name.
99 // (c) Names beginning with "_" are reserved by ANSI C and shd not be used.
100 //
101 if (S[0] == '_' || isdigit(S[0]))
102 Result += "ll";
103
104 for (unsigned i = 0; i < S.size(); ++i)
105 {
106 char C = S[i];
107 if (C == '_' || C == '.' || C == '$' || isalpha(C) || isdigit(C))
108 Result += C;
109 else
110 {
111 Result += '_';
112 Result += char('0' + ((unsigned char)C >> 4));
113 Result += char('0' + (C & 0xF));
114 }
Chris Lattnerc56d7792001-09-28 15:07:24 +0000115 }
Chris Lattnerc56d7792001-09-28 15:07:24 +0000116 return Result;
117 }
118
Chris Lattnere88f78c2001-09-19 13:47:27 +0000119 // getID - Return a valid identifier for the specified value. Base it on
120 // the name of the identifier if possible, use a numbered value based on
121 // prefix otherwise. FPrefix is always prepended to the output identifier.
122 //
123 string getID(const Value *V, const char *Prefix, const char *FPrefix = 0) {
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000124 string Result;
Chris Lattnere88f78c2001-09-19 13:47:27 +0000125 string FP(FPrefix ? FPrefix : ""); // "Forced prefix"
126 if (V->hasName()) {
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000127 Result = FP + V->getName();
Chris Lattnere88f78c2001-09-19 13:47:27 +0000128 } else {
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000129 int valId = Table->getValSlot(V);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000130 if (valId == -1) {
131 ValIdMapConstIterator I = valToIdMap.find(V);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000132 if (I == valToIdMap.end())
133 valId = valToIdMap[V] = valToIdMap.size();
134 else
135 valId = I->second;
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000136 }
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000137 Result = FP + string(Prefix) + itostr(valId);
Chris Lattnere88f78c2001-09-19 13:47:27 +0000138 }
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000139 return getValidSymbolName(Result);
Chris Lattnere88f78c2001-09-19 13:47:27 +0000140 }
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000141
Chris Lattnere88f78c2001-09-19 13:47:27 +0000142 // getID Wrappers - Ensure consistent usage...
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000143 string getID(const Module *M) {
144 return getID(M, "LLVMModule_");
Chris Lattnere88f78c2001-09-19 13:47:27 +0000145 }
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000146 string getID(const Method *M) {
147 return getID(M, "LLVMMethod_");
148 }
149 string getID(const BasicBlock *BB) {
150 return getID(BB, "LL", (".L_"+getID(BB->getParent())+"_").c_str());
151 }
152 string getID(const GlobalVariable *GV) {
153 return getID(GV, "LLVMGlobal_", ".G_");
154 }
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000155 string getID(const Constant *CV) {
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000156 return getID(CV, "LLVMConst_", ".C_");
157 }
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000158};
159
160
161
162//===----------------------------------------------------------------------===//
163// SparcMethodAsmPrinter Code
164//===----------------------------------------------------------------------===//
165
166struct SparcMethodAsmPrinter : public MethodPass, public AsmPrinter {
167 inline SparcMethodAsmPrinter(std::ostream &os, const UltraSparc &t)
168 : AsmPrinter(os, t) {}
169
170 virtual bool doInitialization(Module *M) {
171 startModule(M);
172 return false;
173 }
174
175 virtual bool runOnMethod(Method *M) {
176 startMethod(M);
177 emitMethod(M);
178 endMethod(M);
179 return false;
180 }
181
182 virtual bool doFinalization(Module *M) {
183 endModule();
184 return false;
185 }
186
187 void emitMethod(const Method *M);
188private :
189 void emitBasicBlock(const BasicBlock *BB);
190 void emitMachineInst(const MachineInstr *MI);
191
192 unsigned int printOperands(const MachineInstr *MI, unsigned int opNum);
193 void printOneOperand(const MachineOperand &Op);
194
195 bool OpIsBranchTargetLabel(const MachineInstr *MI, unsigned int opNum);
196 bool OpIsMemoryAddressBase(const MachineInstr *MI, unsigned int opNum);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000197
Chris Lattnere88f78c2001-09-19 13:47:27 +0000198 unsigned getOperandMask(unsigned Opcode) {
199 switch (Opcode) {
200 case SUBcc: return 1 << 3; // Remove CC argument
Vikram S. Adve998cf0d2001-11-11 23:11:36 +0000201 case BA: return 1 << 0; // Remove Arg #0, which is always null or xcc
Chris Lattnere88f78c2001-09-19 13:47:27 +0000202 default: return 0; // By default, don't hack operands...
203 }
204 }
205};
206
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000207inline bool
208SparcMethodAsmPrinter::OpIsBranchTargetLabel(const MachineInstr *MI,
209 unsigned int opNum) {
210 switch (MI->getOpCode()) {
211 case JMPLCALL:
212 case JMPLRET: return (opNum == 0);
213 default: return false;
214 }
215}
216
217
218inline bool
219SparcMethodAsmPrinter::OpIsMemoryAddressBase(const MachineInstr *MI,
220 unsigned int opNum) {
221 if (Target.getInstrInfo().isLoad(MI->getOpCode()))
222 return (opNum == 0);
223 else if (Target.getInstrInfo().isStore(MI->getOpCode()))
224 return (opNum == 1);
225 else
226 return false;
227}
228
229
230#define PrintOp1PlusOp2(Op1, Op2) \
231 printOneOperand(Op1); \
232 toAsm << "+"; \
233 printOneOperand(Op2);
234
235unsigned int
236SparcMethodAsmPrinter::printOperands(const MachineInstr *MI,
237 unsigned int opNum)
238{
239 const MachineOperand& Op = MI->getOperand(opNum);
240
241 if (OpIsBranchTargetLabel(MI, opNum))
242 {
243 PrintOp1PlusOp2(Op, MI->getOperand(opNum+1));
244 return 2;
245 }
246 else if (OpIsMemoryAddressBase(MI, opNum))
247 {
248 toAsm << "[";
249 PrintOp1PlusOp2(Op, MI->getOperand(opNum+1));
250 toAsm << "]";
251 return 2;
252 }
253 else
254 {
255 printOneOperand(Op);
256 return 1;
257 }
258}
259
260
261void
262SparcMethodAsmPrinter::printOneOperand(const MachineOperand &op)
263{
264 switch (op.getOperandType())
265 {
266 case MachineOperand::MO_VirtualRegister:
267 case MachineOperand::MO_CCRegister:
268 case MachineOperand::MO_MachineRegister:
269 {
270 int RegNum = (int)op.getAllocatedRegNum();
271
272 // ****this code is temporary till NULL Values are fixed
273 if (RegNum == Target.getRegInfo().getInvalidRegNum()) {
274 toAsm << "<NULL VALUE>";
275 } else {
276 toAsm << "%" << Target.getRegInfo().getUnifiedRegName(RegNum);
277 }
278 break;
279 }
280
281 case MachineOperand::MO_PCRelativeDisp:
282 {
283 const Value *Val = op.getVRegValue();
284 if (!Val)
285 toAsm << "\t<*NULL Value*>";
286 else if (const BasicBlock *BB = dyn_cast<const BasicBlock>(Val))
287 toAsm << getID(BB);
288 else if (const Method *M = dyn_cast<const Method>(Val))
289 toAsm << getID(M);
290 else if (const GlobalVariable *GV=dyn_cast<const GlobalVariable>(Val))
291 toAsm << getID(GV);
292 else if (const Constant *CV = dyn_cast<const Constant>(Val))
293 toAsm << getID(CV);
294 else
295 toAsm << "<unknown value=" << Val << ">";
296 break;
297 }
298
299 case MachineOperand::MO_SignExtendedImmed:
300 case MachineOperand::MO_UnextendedImmed:
301 toAsm << (long)op.getImmedValue();
302 break;
303
304 default:
305 toAsm << op; // use dump field
306 break;
307 }
308}
309
310
311void
312SparcMethodAsmPrinter::emitMachineInst(const MachineInstr *MI)
313{
314 unsigned Opcode = MI->getOpCode();
315
316 if (TargetInstrDescriptors[Opcode].iclass & M_DUMMY_PHI_FLAG)
317 return; // IGNORE PHI NODES
318
319 toAsm << "\t" << TargetInstrDescriptors[Opcode].opCodeString << "\t";
320
321 unsigned Mask = getOperandMask(Opcode);
322
323 bool NeedComma = false;
324 unsigned N = 1;
325 for (unsigned OpNum = 0; OpNum < MI->getNumOperands(); OpNum += N)
326 if (! ((1 << OpNum) & Mask)) { // Ignore this operand?
327 if (NeedComma) toAsm << ", "; // Handle comma outputing
328 NeedComma = true;
329 N = printOperands(MI, OpNum);
330 }
331 else
332 N = 1;
333
334 toAsm << "\n";
335}
336
337void
338SparcMethodAsmPrinter::emitBasicBlock(const BasicBlock *BB)
339{
340 // Emit a label for the basic block
341 toAsm << getID(BB) << ":\n";
342
343 // Get the vector of machine instructions corresponding to this bb.
344 const MachineCodeForBasicBlock &MIs = BB->getMachineInstrVec();
345 MachineCodeForBasicBlock::const_iterator MII = MIs.begin(), MIE = MIs.end();
346
347 // Loop over all of the instructions in the basic block...
348 for (; MII != MIE; ++MII)
349 emitMachineInst(*MII);
350 toAsm << "\n"; // Seperate BB's with newlines
351}
352
353void
354SparcMethodAsmPrinter::emitMethod(const Method *M)
355{
356 string methName = getID(M);
357 toAsm << "!****** Outputing Method: " << methName << " ******\n";
358 enterSection(AsmPrinter::Text);
359 toAsm << "\t.align\t4\n\t.global\t" << methName << "\n";
360 //toAsm << "\t.type\t" << methName << ",#function\n";
361 toAsm << "\t.type\t" << methName << ", 2\n";
362 toAsm << methName << ":\n";
363
364 // Output code for all of the basic blocks in the method...
365 for (Method::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
366 emitBasicBlock(*I);
367
368 // Output a .size directive so the debugger knows the extents of the function
369 toAsm << ".EndOf_" << methName << ":\n\t.size "
370 << methName << ", .EndOf_"
371 << methName << "-" << methName << "\n";
372
373 // Put some spaces between the methods
374 toAsm << "\n\n";
375}
376
377} // End anonymous namespace
378
379Pass *UltraSparc::getMethodAsmPrinterPass(PassManager &PM, std::ostream &Out) {
380 return new SparcMethodAsmPrinter(Out, *this);
381}
382
383
384
385
386
387//===----------------------------------------------------------------------===//
388// SparcMethodAsmPrinter Code
389//===----------------------------------------------------------------------===//
390
391namespace {
392
393class SparcModuleAsmPrinter : public Pass, public AsmPrinter {
394public:
395 SparcModuleAsmPrinter(ostream &os, UltraSparc &t) : AsmPrinter(os, t) {}
396
397 virtual bool run(Module *M) {
398 startModule(M);
399 emitGlobalsAndConstants(M);
400 endModule();
401 return false;
402 }
403
404 void emitGlobalsAndConstants(const Module *M);
405
406 void printGlobalVariable(const GlobalVariable *GV);
407 void printSingleConstant( const Constant* CV);
408 void printConstantValueOnly(const Constant* CV);
409 void printConstant( const Constant* CV, std::string valID = "");
410
411 static void FoldConstants(const Module *M,
412 std::hash_set<const Constant*> &moduleConstants);
413
414};
415
Chris Lattnercee8f9a2001-11-27 00:03:19 +0000416
417// Can we treat the specified array as a string? Only if it is an array of
418// ubytes or non-negative sbytes.
419//
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000420static bool isStringCompatible(ConstantArray *CPA) {
Chris Lattnercee8f9a2001-11-27 00:03:19 +0000421 const Type *ETy = cast<ArrayType>(CPA->getType())->getElementType();
422 if (ETy == Type::UByteTy) return true;
423 if (ETy != Type::SByteTy) return false;
424
425 for (unsigned i = 0; i < CPA->getNumOperands(); ++i)
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000426 if (cast<ConstantSInt>(CPA->getOperand(i))->getValue() < 0)
Chris Lattnercee8f9a2001-11-27 00:03:19 +0000427 return false;
428
429 return true;
430}
431
432// toOctal - Convert the low order bits of X into an octal letter
433static inline char toOctal(int X) {
434 return (X&7)+'0';
435}
436
437// getAsCString - Return the specified array as a C compatible string, only if
438// the predicate isStringCompatible is true.
439//
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000440static string getAsCString(ConstantArray *CPA) {
Chris Lattnercee8f9a2001-11-27 00:03:19 +0000441 if (isStringCompatible(CPA)) {
442 string Result;
443 const Type *ETy = cast<ArrayType>(CPA->getType())->getElementType();
444 Result = "\"";
445 for (unsigned i = 0; i < CPA->getNumOperands(); ++i) {
446 unsigned char C = (ETy == Type::SByteTy) ?
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000447 (unsigned char)cast<ConstantSInt>(CPA->getOperand(i))->getValue() :
448 (unsigned char)cast<ConstantUInt>(CPA->getOperand(i))->getValue();
Chris Lattnercee8f9a2001-11-27 00:03:19 +0000449
450 if (isprint(C)) {
451 Result += C;
452 } else {
453 switch(C) {
454 case '\a': Result += "\\a"; break;
455 case '\b': Result += "\\b"; break;
456 case '\f': Result += "\\f"; break;
457 case '\n': Result += "\\n"; break;
458 case '\r': Result += "\\r"; break;
459 case '\t': Result += "\\t"; break;
460 case '\v': Result += "\\v"; break;
461 default:
462 Result += '\\';
463 Result += toOctal(C >> 6);
464 Result += toOctal(C >> 3);
465 Result += toOctal(C >> 0);
466 break;
467 }
468 }
469 }
470 Result += "\"";
471
472 return Result;
473 } else {
474 return CPA->getStrValue();
475 }
476}
477
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000478inline bool
479ArrayTypeIsString(ArrayType* arrayType)
480{
481 return (arrayType->getElementType() == Type::UByteTy ||
482 arrayType->getElementType() == Type::SByteTy);
483}
Chris Lattnere88f78c2001-09-19 13:47:27 +0000484
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000485inline const string
486TypeToDataDirective(const Type* type)
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000487{
488 switch(type->getPrimitiveID())
489 {
490 case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
491 return ".byte";
492 case Type::UShortTyID: case Type::ShortTyID:
493 return ".half";
494 case Type::UIntTyID: case Type::IntTyID:
495 return ".word";
496 case Type::ULongTyID: case Type::LongTyID: case Type::PointerTyID:
497 return ".xword";
498 case Type::FloatTyID:
499 return ".single";
500 case Type::DoubleTyID:
501 return ".double";
502 case Type::ArrayTyID:
503 if (ArrayTypeIsString((ArrayType*) type))
504 return ".ascii";
505 else
506 return "<InvaliDataTypeForPrinting>";
507 default:
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000508 return "<InvaliDataTypeForPrinting>";
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000509 }
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000510}
511
Vikram S. Adve21447222001-11-10 02:03:06 +0000512// Get the size of the constant for the given target.
513// If this is an unsized array, return 0.
514//
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000515inline unsigned int
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000516ConstantToSize(const Constant* CV, const TargetMachine& target)
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000517{
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000518 if (ConstantArray* CPA = dyn_cast<ConstantArray>(CV))
Vikram S. Adve21447222001-11-10 02:03:06 +0000519 {
520 ArrayType *aty = cast<ArrayType>(CPA->getType());
521 if (ArrayTypeIsString(aty))
522 return 1 + CPA->getNumOperands();
Vikram S. Adve21447222001-11-10 02:03:06 +0000523 }
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000524
525 return target.findOptimalStorageSize(CV->getType());
526}
527
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000528
529
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000530// Align data larger than one L1 cache line on L1 cache line boundaries.
Vikram S. Adve21447222001-11-10 02:03:06 +0000531// Align all smaller data on the next higher 2^x boundary (4, 8, ...).
532//
533inline unsigned int
534SizeToAlignment(unsigned int size, const TargetMachine& target)
535{
536 unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1);
537 if (size > (unsigned) cacheLineSize / 2)
538 return cacheLineSize;
539 else
540 for (unsigned sz=1; /*no condition*/; sz *= 2)
541 if (sz >= size)
542 return sz;
543}
544
545// Get the size of the type and then use SizeToAlignment.
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000546//
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000547inline unsigned int
548TypeToAlignment(const Type* type, const TargetMachine& target)
549{
Vikram S. Adve21447222001-11-10 02:03:06 +0000550 return SizeToAlignment(target.findOptimalStorageSize(type), target);
551}
552
553// Get the size of the constant and then use SizeToAlignment.
554// Handles strings as a special case;
555inline unsigned int
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000556ConstantToAlignment(const Constant* CV, const TargetMachine& target)
Vikram S. Adve21447222001-11-10 02:03:06 +0000557{
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000558 if (ConstantArray* CPA = dyn_cast<ConstantArray>(CV))
Vikram S. Adve21447222001-11-10 02:03:06 +0000559 if (ArrayTypeIsString(cast<ArrayType>(CPA->getType())))
560 return SizeToAlignment(1 + CPA->getNumOperands(), target);
561
562 return TypeToAlignment(CV->getType(), target);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000563}
564
565
Vikram S. Adve21447222001-11-10 02:03:06 +0000566// Print a single constant value.
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000567void
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000568SparcModuleAsmPrinter::printSingleConstant(const Constant* CV)
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000569{
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000570 assert(CV->getType() != Type::VoidTy &&
571 CV->getType() != Type::TypeTy &&
572 CV->getType() != Type::LabelTy &&
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000573 "Unexpected type for Constant");
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000574
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000575 assert((! isa<ConstantArray>( CV) && ! isa<ConstantStruct>(CV))
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000576 && "Collective types should be handled outside this function");
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000577
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000578 toAsm << "\t" << TypeToDataDirective(CV->getType()) << "\t";
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000579
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000580 if (CV->getType()->isPrimitiveType())
581 {
582 if (CV->getType() == Type::FloatTy || CV->getType() == Type::DoubleTy)
583 toAsm << "0r"; // FP constants must have this prefix
Chris Lattner697954c2002-01-20 22:54:45 +0000584 toAsm << CV->getStrValue() << "\n";
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000585 }
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000586 else if (ConstantPointer* CPP = dyn_cast<ConstantPointer>(CV))
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000587 {
Chris Lattner697954c2002-01-20 22:54:45 +0000588 assert(CPP->isNullValue() &&
589 "Cannot yet print non-null pointer constants to assembly");
590 toAsm << "0\n";
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000591 }
Chris Lattner697954c2002-01-20 22:54:45 +0000592 else if (isa<ConstantPointerRef>(CV))
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000593 {
594 assert(0 && "Cannot yet initialize pointer refs in assembly");
595 }
596 else
597 {
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000598 assert(0 && "Unknown elementary type for constant");
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000599 }
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000600}
601
Vikram S. Adve21447222001-11-10 02:03:06 +0000602// Print a constant value or values (it may be an aggregate).
603// Uses printSingleConstant() to print each individual value.
604void
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000605SparcModuleAsmPrinter::printConstantValueOnly(const Constant* CV)
Vikram S. Adve21447222001-11-10 02:03:06 +0000606{
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000607 ConstantArray *CPA = dyn_cast<ConstantArray>(CV);
Vikram S. Adve21447222001-11-10 02:03:06 +0000608
609 if (CPA && isStringCompatible(CPA))
610 { // print the string alone and return
Chris Lattner697954c2002-01-20 22:54:45 +0000611 toAsm << "\t" << ".ascii" << "\t" << getAsCString(CPA) << "\n";
Vikram S. Adve21447222001-11-10 02:03:06 +0000612 }
613 else if (CPA)
614 { // Not a string. Print the values in successive locations
Chris Lattner697954c2002-01-20 22:54:45 +0000615 const std::vector<Use> &constValues = CPA->getValues();
Vikram S. Adve21447222001-11-10 02:03:06 +0000616 for (unsigned i=1; i < constValues.size(); i++)
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000617 this->printConstantValueOnly(cast<Constant>(constValues[i].get()));
Vikram S. Adve21447222001-11-10 02:03:06 +0000618 }
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000619 else if (ConstantStruct *CPS = dyn_cast<ConstantStruct>(CV))
Vikram S. Adve21447222001-11-10 02:03:06 +0000620 { // Print the fields in successive locations
Chris Lattner697954c2002-01-20 22:54:45 +0000621 const std::vector<Use>& constValues = CPS->getValues();
Vikram S. Adve21447222001-11-10 02:03:06 +0000622 for (unsigned i=1; i < constValues.size(); i++)
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000623 this->printConstantValueOnly(cast<Constant>(constValues[i].get()));
Vikram S. Adve21447222001-11-10 02:03:06 +0000624 }
625 else
626 this->printSingleConstant(CV);
627}
628
629// Print a constant (which may be an aggregate) prefixed by all the
630// appropriate directives. Uses printConstantValueOnly() to print the
631// value or values.
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000632void
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000633SparcModuleAsmPrinter::printConstant(const Constant* CV, string valID)
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000634{
635 if (valID.length() == 0)
636 valID = getID(CV);
637
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000638 toAsm << "\t.align\t" << ConstantToAlignment(CV, Target) << "\n";
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000639
640 // Print .size and .type only if it is not a string.
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000641 ConstantArray *CPA = dyn_cast<ConstantArray>(CV);
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000642 if (CPA && isStringCompatible(CPA))
643 { // print it as a string and return
Chris Lattner697954c2002-01-20 22:54:45 +0000644 toAsm << valID << ":\n";
645 toAsm << "\t" << ".ascii" << "\t" << getAsCString(CPA) << "\n";
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000646 return;
647 }
Vikram S. Adve21447222001-11-10 02:03:06 +0000648
Chris Lattner697954c2002-01-20 22:54:45 +0000649 toAsm << "\t.type" << "\t" << valID << ",#object\n";
Vikram S. Adve21447222001-11-10 02:03:06 +0000650
651 unsigned int constSize = ConstantToSize(CV, Target);
652 if (constSize)
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000653 toAsm << "\t.size" << "\t" << valID << "," << constSize << "\n";
Vikram S. Adve21447222001-11-10 02:03:06 +0000654
Chris Lattner697954c2002-01-20 22:54:45 +0000655 toAsm << valID << ":\n";
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000656
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000657 printConstantValueOnly(CV);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000658}
659
660
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000661void SparcModuleAsmPrinter::FoldConstants(const Module *M,
662 std::hash_set<const Constant*> &MC) {
663 for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
664 if (!(*I)->isExternal()) {
665 const std::hash_set<const Constant*> &pool =
666 MachineCodeForMethod::get(*I).getConstantPoolValues();
667 MC.insert(pool.begin(), pool.end());
668 }
669}
670
671void SparcModuleAsmPrinter::printGlobalVariable(const GlobalVariable* GV)
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000672{
Chris Lattner697954c2002-01-20 22:54:45 +0000673 toAsm << "\t.global\t" << getID(GV) << "\n";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000674
675 if (GV->hasInitializer())
676 printConstant(GV->getInitializer(), getID(GV));
677 else {
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000678 toAsm << "\t.align\t" << TypeToAlignment(GV->getType()->getElementType(),
679 Target) << "\n";
Chris Lattner697954c2002-01-20 22:54:45 +0000680 toAsm << "\t.type\t" << getID(GV) << ",#object\n";
Vikram S. Adveffbba0f2001-11-08 14:29:57 +0000681 toAsm << "\t.reserve\t" << getID(GV) << ","
Chris Lattnerc019a172002-02-03 07:48:06 +0000682 << Target.findOptimalStorageSize(GV->getType()->getElementType())
Chris Lattner697954c2002-01-20 22:54:45 +0000683 << "\n";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000684 }
685}
686
687
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000688void SparcModuleAsmPrinter::emitGlobalsAndConstants(const Module *M) {
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000689 // First, get the constants there were marked by the code generator for
690 // inclusion in the assembly code data area and fold them all into a
691 // single constant pool since there may be lots of duplicates. Also,
692 // lets force these constants into the slot table so that we can get
693 // unique names for unnamed constants also.
694 //
Chris Lattner697954c2002-01-20 22:54:45 +0000695 std::hash_set<const Constant*> moduleConstants;
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000696 FoldConstants(M, moduleConstants);
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000697
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000698 // Now, emit the three data sections separately; the cost of I/O should
699 // make up for the cost of extra passes over the globals list!
700 //
701 // Read-only data section (implies initialized)
702 for (Module::const_giterator GI=M->gbegin(), GE=M->gend(); GI != GE; ++GI)
703 {
704 const GlobalVariable* GV = *GI;
705 if (GV->hasInitializer() && GV->isConstant())
706 {
707 if (GI == M->gbegin())
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000708 enterSection(AsmPrinter::ReadOnlyData);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000709 printGlobalVariable(GV);
710 }
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000711 }
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000712
Chris Lattner697954c2002-01-20 22:54:45 +0000713 for (std::hash_set<const Constant*>::const_iterator
714 I = moduleConstants.begin(),
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000715 E = moduleConstants.end(); I != E; ++I)
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000716 printConstant(*I);
717
718 // Initialized read-write data section
719 for (Module::const_giterator GI=M->gbegin(), GE=M->gend(); GI != GE; ++GI)
720 {
721 const GlobalVariable* GV = *GI;
722 if (GV->hasInitializer() && ! GV->isConstant())
723 {
724 if (GI == M->gbegin())
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000725 enterSection(AsmPrinter::InitRWData);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000726 printGlobalVariable(GV);
727 }
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000728 }
729
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000730 // Uninitialized read-write data section
731 for (Module::const_giterator GI=M->gbegin(), GE=M->gend(); GI != GE; ++GI)
732 {
733 const GlobalVariable* GV = *GI;
734 if (! GV->hasInitializer())
735 {
736 if (GI == M->gbegin())
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000737 enterSection(AsmPrinter::UninitRWData);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000738 printGlobalVariable(GV);
739 }
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000740 }
741
Chris Lattner697954c2002-01-20 22:54:45 +0000742 toAsm << "\n";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000743}
744
Chris Lattnere88f78c2001-09-19 13:47:27 +0000745} // End anonymous namespace
746
Chris Lattnerc19b8b12002-02-03 23:41:08 +0000747Pass *UltraSparc::getModuleAsmPrinterPass(PassManager &PM, std::ostream &Out) {
748 return new SparcModuleAsmPrinter(Out, *this);
Chris Lattnerc019a172002-02-03 07:48:06 +0000749}