blob: 74b1f44f9126880e719b152310828a6a11b9ef53 [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//
7// The entry point of this file is the UltraSparc::emitAssembly method.
8//
9//===----------------------------------------------------------------------===//
10
11#include "SparcInternals.h"
12#include "llvm/Analysis/SlotCalculator.h"
13#include "llvm/CodeGen/MachineInstr.h"
Chris Lattnerc019a172002-02-03 07:48:06 +000014#include "llvm/CodeGen/MachineCodeForMethod.h"
Vikram S. Adve953c83e2001-10-28 21:38:52 +000015#include "llvm/GlobalVariable.h"
Chris Lattnere9bb2df2001-12-03 22:26:30 +000016#include "llvm/ConstantVals.h"
Vikram S. Adve953c83e2001-10-28 21:38:52 +000017#include "llvm/DerivedTypes.h"
Chris Lattnere88f78c2001-09-19 13:47:27 +000018#include "llvm/BasicBlock.h"
19#include "llvm/Method.h"
20#include "llvm/Module.h"
Chris Lattnercee8f9a2001-11-27 00:03:19 +000021#include "Support/StringExtras.h"
22#include "Support/HashExtras.h"
Chris Lattner697954c2002-01-20 22:54:45 +000023using std::string;
Chris Lattnere88f78c2001-09-19 13:47:27 +000024
25namespace {
26
Chris Lattnere88f78c2001-09-19 13:47:27 +000027
Vikram S. Adve953c83e2001-10-28 21:38:52 +000028class SparcAsmPrinter {
Chris Lattner697954c2002-01-20 22:54:45 +000029 typedef std::hash_map<const Value*, int> ValIdMap;
Vikram S. Adve953c83e2001-10-28 21:38:52 +000030 typedef ValIdMap:: iterator ValIdMapIterator;
31 typedef ValIdMap::const_iterator ValIdMapConstIterator;
32
Chris Lattner697954c2002-01-20 22:54:45 +000033 std::ostream &toAsm;
Vikram S. Adve953c83e2001-10-28 21:38:52 +000034 SlotCalculator Table; // map anonymous values to unique integer IDs
35 ValIdMap valToIdMap; // used for values not handled by SlotCalculator
36 const UltraSparc &Target;
37
Chris Lattnere88f78c2001-09-19 13:47:27 +000038 enum Sections {
39 Unknown,
40 Text,
Vikram S. Adve953c83e2001-10-28 21:38:52 +000041 ReadOnlyData,
42 InitRWData,
43 UninitRWData,
Chris Lattnere88f78c2001-09-19 13:47:27 +000044 } CurSection;
Vikram S. Adve953c83e2001-10-28 21:38:52 +000045
Chris Lattnere88f78c2001-09-19 13:47:27 +000046public:
Chris Lattner697954c2002-01-20 22:54:45 +000047 inline SparcAsmPrinter(std::ostream &o, const Module *M, const UltraSparc &t)
Vikram S. Adve29ff8732001-11-08 05:12:37 +000048 : toAsm(o), Table(SlotCalculator(M, true)), Target(t), CurSection(Unknown) {
Chris Lattnere88f78c2001-09-19 13:47:27 +000049 }
50
Chris Lattnere88f78c2001-09-19 13:47:27 +000051 void emitMethod(const Method *M);
Chris Lattnerc019a172002-02-03 07:48:06 +000052 void emitGlobalsAndConstants(const Module *M);
53private :
Chris Lattnere88f78c2001-09-19 13:47:27 +000054 void emitBasicBlock(const BasicBlock *BB);
55 void emitMachineInst(const MachineInstr *MI);
Chris Lattnere88f78c2001-09-19 13:47:27 +000056
Vikram S. Adve21447222001-11-10 02:03:06 +000057 void printGlobalVariable( const GlobalVariable* GV);
Chris Lattnere9bb2df2001-12-03 22:26:30 +000058 void printSingleConstant( const Constant* CV);
59 void printConstantValueOnly(const Constant* CV);
Chris Lattner697954c2002-01-20 22:54:45 +000060 void printConstant( const Constant* CV, std::string valID = "");
Vikram S. Adve953c83e2001-10-28 21:38:52 +000061
62 unsigned int printOperands(const MachineInstr *MI, unsigned int opNum);
63 void printOneOperand(const MachineOperand &Op);
Chris Lattnere88f78c2001-09-19 13:47:27 +000064
Vikram S. Adve953c83e2001-10-28 21:38:52 +000065 bool OpIsBranchTargetLabel(const MachineInstr *MI, unsigned int opNum);
66 bool OpIsMemoryAddressBase(const MachineInstr *MI, unsigned int opNum);
67
Chris Lattnere88f78c2001-09-19 13:47:27 +000068 // enterSection - Use this method to enter a different section of the output
69 // executable. This is used to only output neccesary section transitions.
70 //
71 void enterSection(enum Sections S) {
72 if (S == CurSection) return; // Only switch section if neccesary
73 CurSection = S;
74
Vikram S. Adve29ff8732001-11-08 05:12:37 +000075 toAsm << "\n\t.section ";
Vikram S. Adve953c83e2001-10-28 21:38:52 +000076 switch (S)
77 {
78 default: assert(0 && "Bad section name!");
Vikram S. Adve29ff8732001-11-08 05:12:37 +000079 case Text: toAsm << "\".text\""; break;
80 case ReadOnlyData: toAsm << "\".rodata\",#alloc"; break;
81 case InitRWData: toAsm << "\".data\",#alloc,#write"; break;
82 case UninitRWData: toAsm << "\".bss\",#alloc,#write\nBbss.bss:"; break;
Vikram S. Adve953c83e2001-10-28 21:38:52 +000083 }
Vikram S. Adve29ff8732001-11-08 05:12:37 +000084 toAsm << "\n";
Chris Lattnere88f78c2001-09-19 13:47:27 +000085 }
86
Chris Lattner697954c2002-01-20 22:54:45 +000087 std::string getValidSymbolName(const string &S) {
Chris Lattnerc56d7792001-09-28 15:07:24 +000088 string Result;
Vikram S. Adve29ff8732001-11-08 05:12:37 +000089
90 // Symbol names in Sparc assembly language have these rules:
91 // (a) Must match { letter | _ | . | $ } { letter | _ | . | $ | digit }*
92 // (b) A name beginning in "." is treated as a local name.
93 // (c) Names beginning with "_" are reserved by ANSI C and shd not be used.
94 //
95 if (S[0] == '_' || isdigit(S[0]))
96 Result += "ll";
97
98 for (unsigned i = 0; i < S.size(); ++i)
99 {
100 char C = S[i];
101 if (C == '_' || C == '.' || C == '$' || isalpha(C) || isdigit(C))
102 Result += C;
103 else
104 {
105 Result += '_';
106 Result += char('0' + ((unsigned char)C >> 4));
107 Result += char('0' + (C & 0xF));
108 }
Chris Lattnerc56d7792001-09-28 15:07:24 +0000109 }
Chris Lattnerc56d7792001-09-28 15:07:24 +0000110 return Result;
111 }
112
Chris Lattnere88f78c2001-09-19 13:47:27 +0000113 // getID - Return a valid identifier for the specified value. Base it on
114 // the name of the identifier if possible, use a numbered value based on
115 // prefix otherwise. FPrefix is always prepended to the output identifier.
116 //
117 string getID(const Value *V, const char *Prefix, const char *FPrefix = 0) {
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000118 string Result;
Chris Lattnere88f78c2001-09-19 13:47:27 +0000119 string FP(FPrefix ? FPrefix : ""); // "Forced prefix"
120 if (V->hasName()) {
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000121 Result = FP + V->getName();
Chris Lattnere88f78c2001-09-19 13:47:27 +0000122 } else {
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000123 int valId = Table.getValSlot(V);
124 if (valId == -1) {
125 ValIdMapConstIterator I = valToIdMap.find(V);
126 valId = (I == valToIdMap.end())? (valToIdMap[V] = valToIdMap.size())
127 : (*I).second;
128 }
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000129 Result = FP + string(Prefix) + itostr(valId);
Chris Lattnere88f78c2001-09-19 13:47:27 +0000130 }
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000131 return getValidSymbolName(Result);
Chris Lattnere88f78c2001-09-19 13:47:27 +0000132 }
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000133
Chris Lattnere88f78c2001-09-19 13:47:27 +0000134 // getID Wrappers - Ensure consistent usage...
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000135 string getID(const Module *M) {
136 return getID(M, "LLVMModule_");
Chris Lattnere88f78c2001-09-19 13:47:27 +0000137 }
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000138 string getID(const Method *M) {
139 return getID(M, "LLVMMethod_");
140 }
141 string getID(const BasicBlock *BB) {
142 return getID(BB, "LL", (".L_"+getID(BB->getParent())+"_").c_str());
143 }
144 string getID(const GlobalVariable *GV) {
145 return getID(GV, "LLVMGlobal_", ".G_");
146 }
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000147 string getID(const Constant *CV) {
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000148 return getID(CV, "LLVMConst_", ".C_");
149 }
150
Chris Lattnere88f78c2001-09-19 13:47:27 +0000151 unsigned getOperandMask(unsigned Opcode) {
152 switch (Opcode) {
153 case SUBcc: return 1 << 3; // Remove CC argument
Vikram S. Adve998cf0d2001-11-11 23:11:36 +0000154 case BA: return 1 << 0; // Remove Arg #0, which is always null or xcc
Chris Lattnere88f78c2001-09-19 13:47:27 +0000155 default: return 0; // By default, don't hack operands...
156 }
157 }
158};
159
Chris Lattnercee8f9a2001-11-27 00:03:19 +0000160
161// Can we treat the specified array as a string? Only if it is an array of
162// ubytes or non-negative sbytes.
163//
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000164static bool isStringCompatible(ConstantArray *CPA) {
Chris Lattnercee8f9a2001-11-27 00:03:19 +0000165 const Type *ETy = cast<ArrayType>(CPA->getType())->getElementType();
166 if (ETy == Type::UByteTy) return true;
167 if (ETy != Type::SByteTy) return false;
168
169 for (unsigned i = 0; i < CPA->getNumOperands(); ++i)
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000170 if (cast<ConstantSInt>(CPA->getOperand(i))->getValue() < 0)
Chris Lattnercee8f9a2001-11-27 00:03:19 +0000171 return false;
172
173 return true;
174}
175
176// toOctal - Convert the low order bits of X into an octal letter
177static inline char toOctal(int X) {
178 return (X&7)+'0';
179}
180
181// getAsCString - Return the specified array as a C compatible string, only if
182// the predicate isStringCompatible is true.
183//
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000184static string getAsCString(ConstantArray *CPA) {
Chris Lattnercee8f9a2001-11-27 00:03:19 +0000185 if (isStringCompatible(CPA)) {
186 string Result;
187 const Type *ETy = cast<ArrayType>(CPA->getType())->getElementType();
188 Result = "\"";
189 for (unsigned i = 0; i < CPA->getNumOperands(); ++i) {
190 unsigned char C = (ETy == Type::SByteTy) ?
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000191 (unsigned char)cast<ConstantSInt>(CPA->getOperand(i))->getValue() :
192 (unsigned char)cast<ConstantUInt>(CPA->getOperand(i))->getValue();
Chris Lattnercee8f9a2001-11-27 00:03:19 +0000193
194 if (isprint(C)) {
195 Result += C;
196 } else {
197 switch(C) {
198 case '\a': Result += "\\a"; break;
199 case '\b': Result += "\\b"; break;
200 case '\f': Result += "\\f"; break;
201 case '\n': Result += "\\n"; break;
202 case '\r': Result += "\\r"; break;
203 case '\t': Result += "\\t"; break;
204 case '\v': Result += "\\v"; break;
205 default:
206 Result += '\\';
207 Result += toOctal(C >> 6);
208 Result += toOctal(C >> 3);
209 Result += toOctal(C >> 0);
210 break;
211 }
212 }
213 }
214 Result += "\"";
215
216 return Result;
217 } else {
218 return CPA->getStrValue();
219 }
220}
221
222
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000223inline bool
224SparcAsmPrinter::OpIsBranchTargetLabel(const MachineInstr *MI,
225 unsigned int opNum) {
226 switch (MI->getOpCode()) {
227 case JMPLCALL:
228 case JMPLRET: return (opNum == 0);
229 default: return false;
Chris Lattnerc28f6d62001-10-15 19:21:31 +0000230 }
231}
232
233
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000234inline bool
235SparcAsmPrinter::OpIsMemoryAddressBase(const MachineInstr *MI,
236 unsigned int opNum) {
237 if (Target.getInstrInfo().isLoad(MI->getOpCode()))
238 return (opNum == 0);
239 else if (Target.getInstrInfo().isStore(MI->getOpCode()))
240 return (opNum == 1);
241 else
242 return false;
243}
244
245
246#define PrintOp1PlusOp2(Op1, Op2) \
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000247 printOneOperand(Op1); \
248 toAsm << "+"; \
249 printOneOperand(Op2);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000250
251unsigned int
252SparcAsmPrinter::printOperands(const MachineInstr *MI,
253 unsigned int opNum)
254{
255 const MachineOperand& Op = MI->getOperand(opNum);
256
257 if (OpIsBranchTargetLabel(MI, opNum))
258 {
259 PrintOp1PlusOp2(Op, MI->getOperand(opNum+1));
260 return 2;
261 }
262 else if (OpIsMemoryAddressBase(MI, opNum))
263 {
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000264 toAsm << "[";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000265 PrintOp1PlusOp2(Op, MI->getOperand(opNum+1));
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000266 toAsm << "]";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000267 return 2;
268 }
269 else
270 {
271 printOneOperand(Op);
272 return 1;
273 }
274}
275
276
277void
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000278SparcAsmPrinter::printOneOperand(const MachineOperand &op)
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000279{
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000280 switch (op.getOperandType())
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000281 {
282 case MachineOperand::MO_VirtualRegister:
283 case MachineOperand::MO_CCRegister:
284 case MachineOperand::MO_MachineRegister:
285 {
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000286 int RegNum = (int)op.getAllocatedRegNum();
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000287
288 // ****this code is temporary till NULL Values are fixed
Ruchira Sasanka5f98aca2001-11-13 23:08:19 +0000289 if (RegNum == Target.getRegInfo().getInvalidRegNum()) {
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000290 toAsm << "<NULL VALUE>";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000291 } else {
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000292 toAsm << "%" << Target.getRegInfo().getUnifiedRegName(RegNum);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000293 }
294 break;
295 }
296
297 case MachineOperand::MO_PCRelativeDisp:
298 {
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000299 const Value *Val = op.getVRegValue();
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000300 if (!Val)
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000301 toAsm << "\t<*NULL Value*>";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000302 else if (const BasicBlock *BB = dyn_cast<const BasicBlock>(Val))
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000303 toAsm << getID(BB);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000304 else if (const Method *M = dyn_cast<const Method>(Val))
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000305 toAsm << getID(M);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000306 else if (const GlobalVariable *GV=dyn_cast<const GlobalVariable>(Val))
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000307 toAsm << getID(GV);
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000308 else if (const Constant *CV = dyn_cast<const Constant>(Val))
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000309 toAsm << getID(CV);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000310 else
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000311 toAsm << "<unknown value=" << Val << ">";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000312 break;
313 }
314
315 case MachineOperand::MO_SignExtendedImmed:
316 case MachineOperand::MO_UnextendedImmed:
Chris Lattner697954c2002-01-20 22:54:45 +0000317 toAsm << (long)op.getImmedValue();
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000318 break;
319
320 default:
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000321 toAsm << op; // use dump field
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000322 break;
323 }
324}
325
326
327void
328SparcAsmPrinter::emitMachineInst(const MachineInstr *MI)
329{
Chris Lattnere88f78c2001-09-19 13:47:27 +0000330 unsigned Opcode = MI->getOpCode();
331
332 if (TargetInstrDescriptors[Opcode].iclass & M_DUMMY_PHI_FLAG)
333 return; // IGNORE PHI NODES
334
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000335 toAsm << "\t" << TargetInstrDescriptors[Opcode].opCodeString << "\t";
Chris Lattnere88f78c2001-09-19 13:47:27 +0000336
337 unsigned Mask = getOperandMask(Opcode);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000338
Chris Lattnere88f78c2001-09-19 13:47:27 +0000339 bool NeedComma = false;
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000340 unsigned N = 1;
341 for (unsigned OpNum = 0; OpNum < MI->getNumOperands(); OpNum += N)
342 if (! ((1 << OpNum) & Mask)) { // Ignore this operand?
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000343 if (NeedComma) toAsm << ", "; // Handle comma outputing
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000344 NeedComma = true;
345 N = printOperands(MI, OpNum);
346 }
347 else
348 N = 1;
349
Chris Lattner697954c2002-01-20 22:54:45 +0000350 toAsm << "\n";
Chris Lattnere88f78c2001-09-19 13:47:27 +0000351}
352
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000353void
354SparcAsmPrinter::emitBasicBlock(const BasicBlock *BB)
355{
Chris Lattnere88f78c2001-09-19 13:47:27 +0000356 // Emit a label for the basic block
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000357 toAsm << getID(BB) << ":\n";
Chris Lattnere88f78c2001-09-19 13:47:27 +0000358
359 // Get the vector of machine instructions corresponding to this bb.
360 const MachineCodeForBasicBlock &MIs = BB->getMachineInstrVec();
361 MachineCodeForBasicBlock::const_iterator MII = MIs.begin(), MIE = MIs.end();
362
363 // Loop over all of the instructions in the basic block...
364 for (; MII != MIE; ++MII)
365 emitMachineInst(*MII);
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000366 toAsm << "\n"; // Seperate BB's with newlines
Chris Lattnere88f78c2001-09-19 13:47:27 +0000367}
368
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000369void
370SparcAsmPrinter::emitMethod(const Method *M)
371{
Chris Lattnere88f78c2001-09-19 13:47:27 +0000372 if (M->isExternal()) return;
373
374 // Make sure the slot table has information about this method...
375 Table.incorporateMethod(M);
376
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000377 string methName = getID(M);
378 toAsm << "!****** Outputing Method: " << methName << " ******\n";
Chris Lattnere88f78c2001-09-19 13:47:27 +0000379 enterSection(Text);
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000380 toAsm << "\t.align\t4\n\t.global\t" << methName << "\n";
381 //toAsm << "\t.type\t" << methName << ",#function\n";
382 toAsm << "\t.type\t" << methName << ", 2\n";
383 toAsm << methName << ":\n";
Chris Lattnere88f78c2001-09-19 13:47:27 +0000384
385 // Output code for all of the basic blocks in the method...
386 for (Method::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
387 emitBasicBlock(*I);
388
389 // Output a .size directive so the debugger knows the extents of the function
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000390 toAsm << ".EndOf_" << methName << ":\n\t.size "
391 << methName << ", .EndOf_"
Chris Lattner697954c2002-01-20 22:54:45 +0000392 << methName << "-" << methName << "\n";
Chris Lattnere88f78c2001-09-19 13:47:27 +0000393
394 // Put some spaces between the methods
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000395 toAsm << "\n\n";
Chris Lattnere88f78c2001-09-19 13:47:27 +0000396
397 // Forget all about M.
398 Table.purgeMethod();
399}
400
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000401inline bool
402ArrayTypeIsString(ArrayType* arrayType)
403{
404 return (arrayType->getElementType() == Type::UByteTy ||
405 arrayType->getElementType() == Type::SByteTy);
406}
Chris Lattnere88f78c2001-09-19 13:47:27 +0000407
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000408inline const string
409TypeToDataDirective(const Type* type)
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000410{
411 switch(type->getPrimitiveID())
412 {
413 case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
414 return ".byte";
415 case Type::UShortTyID: case Type::ShortTyID:
416 return ".half";
417 case Type::UIntTyID: case Type::IntTyID:
418 return ".word";
419 case Type::ULongTyID: case Type::LongTyID: case Type::PointerTyID:
420 return ".xword";
421 case Type::FloatTyID:
422 return ".single";
423 case Type::DoubleTyID:
424 return ".double";
425 case Type::ArrayTyID:
426 if (ArrayTypeIsString((ArrayType*) type))
427 return ".ascii";
428 else
429 return "<InvaliDataTypeForPrinting>";
430 default:
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000431 return "<InvaliDataTypeForPrinting>";
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000432 }
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000433}
434
Vikram S. Adve21447222001-11-10 02:03:06 +0000435// Get the size of the constant for the given target.
436// If this is an unsized array, return 0.
437//
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000438inline unsigned int
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000439ConstantToSize(const Constant* CV, const TargetMachine& target)
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000440{
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000441 if (ConstantArray* CPA = dyn_cast<ConstantArray>(CV))
Vikram S. Adve21447222001-11-10 02:03:06 +0000442 {
443 ArrayType *aty = cast<ArrayType>(CPA->getType());
444 if (ArrayTypeIsString(aty))
445 return 1 + CPA->getNumOperands();
Vikram S. Adve21447222001-11-10 02:03:06 +0000446 }
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000447
448 return target.findOptimalStorageSize(CV->getType());
449}
450
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000451
452
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000453// Align data larger than one L1 cache line on L1 cache line boundaries.
Vikram S. Adve21447222001-11-10 02:03:06 +0000454// Align all smaller data on the next higher 2^x boundary (4, 8, ...).
455//
456inline unsigned int
457SizeToAlignment(unsigned int size, const TargetMachine& target)
458{
459 unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1);
460 if (size > (unsigned) cacheLineSize / 2)
461 return cacheLineSize;
462 else
463 for (unsigned sz=1; /*no condition*/; sz *= 2)
464 if (sz >= size)
465 return sz;
466}
467
468// Get the size of the type and then use SizeToAlignment.
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000469//
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000470inline unsigned int
471TypeToAlignment(const Type* type, const TargetMachine& target)
472{
Vikram S. Adve21447222001-11-10 02:03:06 +0000473 return SizeToAlignment(target.findOptimalStorageSize(type), target);
474}
475
476// Get the size of the constant and then use SizeToAlignment.
477// Handles strings as a special case;
478inline unsigned int
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000479ConstantToAlignment(const Constant* CV, const TargetMachine& target)
Vikram S. Adve21447222001-11-10 02:03:06 +0000480{
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000481 if (ConstantArray* CPA = dyn_cast<ConstantArray>(CV))
Vikram S. Adve21447222001-11-10 02:03:06 +0000482 if (ArrayTypeIsString(cast<ArrayType>(CPA->getType())))
483 return SizeToAlignment(1 + CPA->getNumOperands(), target);
484
485 return TypeToAlignment(CV->getType(), target);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000486}
487
488
Vikram S. Adve21447222001-11-10 02:03:06 +0000489// Print a single constant value.
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000490void
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000491SparcAsmPrinter::printSingleConstant(const Constant* CV)
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000492{
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000493 assert(CV->getType() != Type::VoidTy &&
494 CV->getType() != Type::TypeTy &&
495 CV->getType() != Type::LabelTy &&
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000496 "Unexpected type for Constant");
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000497
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000498 assert((! isa<ConstantArray>( CV) && ! isa<ConstantStruct>(CV))
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000499 && "Collective types should be handled outside this function");
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000500
501 toAsm << "\t"
502 << TypeToDataDirective(CV->getType()) << "\t";
503
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000504 if (CV->getType()->isPrimitiveType())
505 {
506 if (CV->getType() == Type::FloatTy || CV->getType() == Type::DoubleTy)
507 toAsm << "0r"; // FP constants must have this prefix
Chris Lattner697954c2002-01-20 22:54:45 +0000508 toAsm << CV->getStrValue() << "\n";
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000509 }
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000510 else if (ConstantPointer* CPP = dyn_cast<ConstantPointer>(CV))
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000511 {
Chris Lattner697954c2002-01-20 22:54:45 +0000512 assert(CPP->isNullValue() &&
513 "Cannot yet print non-null pointer constants to assembly");
514 toAsm << "0\n";
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000515 }
Chris Lattner697954c2002-01-20 22:54:45 +0000516 else if (isa<ConstantPointerRef>(CV))
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000517 {
518 assert(0 && "Cannot yet initialize pointer refs in assembly");
519 }
520 else
521 {
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000522 assert(0 && "Unknown elementary type for constant");
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000523 }
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000524}
525
Vikram S. Adve21447222001-11-10 02:03:06 +0000526// Print a constant value or values (it may be an aggregate).
527// Uses printSingleConstant() to print each individual value.
528void
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000529SparcAsmPrinter::printConstantValueOnly(const Constant* CV)
Vikram S. Adve21447222001-11-10 02:03:06 +0000530{
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000531 ConstantArray *CPA = dyn_cast<ConstantArray>(CV);
Vikram S. Adve21447222001-11-10 02:03:06 +0000532
533 if (CPA && isStringCompatible(CPA))
534 { // print the string alone and return
Chris Lattner697954c2002-01-20 22:54:45 +0000535 toAsm << "\t" << ".ascii" << "\t" << getAsCString(CPA) << "\n";
Vikram S. Adve21447222001-11-10 02:03:06 +0000536 }
537 else if (CPA)
538 { // Not a string. Print the values in successive locations
Chris Lattner697954c2002-01-20 22:54:45 +0000539 const std::vector<Use> &constValues = CPA->getValues();
Vikram S. Adve21447222001-11-10 02:03:06 +0000540 for (unsigned i=1; i < constValues.size(); i++)
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000541 this->printConstantValueOnly(cast<Constant>(constValues[i].get()));
Vikram S. Adve21447222001-11-10 02:03:06 +0000542 }
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000543 else if (ConstantStruct *CPS = dyn_cast<ConstantStruct>(CV))
Vikram S. Adve21447222001-11-10 02:03:06 +0000544 { // Print the fields in successive locations
Chris Lattner697954c2002-01-20 22:54:45 +0000545 const std::vector<Use>& constValues = CPS->getValues();
Vikram S. Adve21447222001-11-10 02:03:06 +0000546 for (unsigned i=1; i < constValues.size(); i++)
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000547 this->printConstantValueOnly(cast<Constant>(constValues[i].get()));
Vikram S. Adve21447222001-11-10 02:03:06 +0000548 }
549 else
550 this->printSingleConstant(CV);
551}
552
553// Print a constant (which may be an aggregate) prefixed by all the
554// appropriate directives. Uses printConstantValueOnly() to print the
555// value or values.
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000556void
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000557SparcAsmPrinter::printConstant(const Constant* CV, string valID)
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000558{
559 if (valID.length() == 0)
560 valID = getID(CV);
561
Vikram S. Adve21447222001-11-10 02:03:06 +0000562 toAsm << "\t.align\t" << ConstantToAlignment(CV, Target)
Chris Lattner697954c2002-01-20 22:54:45 +0000563 << "\n";
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000564
565 // Print .size and .type only if it is not a string.
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000566 ConstantArray *CPA = dyn_cast<ConstantArray>(CV);
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000567 if (CPA && isStringCompatible(CPA))
568 { // print it as a string and return
Chris Lattner697954c2002-01-20 22:54:45 +0000569 toAsm << valID << ":\n";
570 toAsm << "\t" << ".ascii" << "\t" << getAsCString(CPA) << "\n";
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000571 return;
572 }
Vikram S. Adve21447222001-11-10 02:03:06 +0000573
Chris Lattner697954c2002-01-20 22:54:45 +0000574 toAsm << "\t.type" << "\t" << valID << ",#object\n";
Vikram S. Adve21447222001-11-10 02:03:06 +0000575
576 unsigned int constSize = ConstantToSize(CV, Target);
577 if (constSize)
578 toAsm << "\t.size" << "\t" << valID << ","
Chris Lattner697954c2002-01-20 22:54:45 +0000579 << constSize << "\n";
Vikram S. Adve21447222001-11-10 02:03:06 +0000580
Chris Lattner697954c2002-01-20 22:54:45 +0000581 toAsm << valID << ":\n";
Vikram S. Adve915b58d2001-11-09 02:19:29 +0000582
Vikram S. Adve21447222001-11-10 02:03:06 +0000583 this->printConstantValueOnly(CV);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000584}
585
586
587void
588SparcAsmPrinter::printGlobalVariable(const GlobalVariable* GV)
589{
Chris Lattner697954c2002-01-20 22:54:45 +0000590 toAsm << "\t.global\t" << getID(GV) << "\n";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000591
592 if (GV->hasInitializer())
593 printConstant(GV->getInitializer(), getID(GV));
594 else {
Vikram S. Adveffbba0f2001-11-08 14:29:57 +0000595 toAsm << "\t.align\t"
Chris Lattner697954c2002-01-20 22:54:45 +0000596 << TypeToAlignment(GV->getType()->getElementType(), Target) << "\n";
597 toAsm << "\t.type\t" << getID(GV) << ",#object\n";
Vikram S. Adveffbba0f2001-11-08 14:29:57 +0000598 toAsm << "\t.reserve\t" << getID(GV) << ","
Chris Lattnerc019a172002-02-03 07:48:06 +0000599 << Target.findOptimalStorageSize(GV->getType()->getElementType())
Chris Lattner697954c2002-01-20 22:54:45 +0000600 << "\n";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000601 }
602}
603
604
605static void
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000606FoldConstants(const Module *M,
Chris Lattner697954c2002-01-20 22:54:45 +0000607 std::hash_set<const Constant*>& moduleConstants)
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000608{
609 for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
610 if (! (*I)->isExternal())
611 {
Chris Lattner697954c2002-01-20 22:54:45 +0000612 const std::hash_set<const Constant*>& pool =
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000613 MachineCodeForMethod::get(*I).getConstantPoolValues();
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000614 moduleConstants.insert(pool.begin(), pool.end());
Vikram S. Adve29ff8732001-11-08 05:12:37 +0000615 }
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000616}
617
618
619void
620SparcAsmPrinter::emitGlobalsAndConstants(const Module *M)
621{
622 // First, get the constants there were marked by the code generator for
623 // inclusion in the assembly code data area and fold them all into a
624 // single constant pool since there may be lots of duplicates. Also,
625 // lets force these constants into the slot table so that we can get
626 // unique names for unnamed constants also.
627 //
Chris Lattner697954c2002-01-20 22:54:45 +0000628 std::hash_set<const Constant*> moduleConstants;
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000629 FoldConstants(M, moduleConstants);
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000630
631 // Now, emit the three data sections separately; the cost of I/O should
632 // make up for the cost of extra passes over the globals list!
633 //
634 // Read-only data section (implies initialized)
635 for (Module::const_giterator GI=M->gbegin(), GE=M->gend(); GI != GE; ++GI)
636 {
637 const GlobalVariable* GV = *GI;
638 if (GV->hasInitializer() && GV->isConstant())
639 {
640 if (GI == M->gbegin())
641 enterSection(ReadOnlyData);
642 printGlobalVariable(GV);
643 }
644 }
645
Chris Lattner697954c2002-01-20 22:54:45 +0000646 for (std::hash_set<const Constant*>::const_iterator
647 I = moduleConstants.begin(),
Chris Lattnere9bb2df2001-12-03 22:26:30 +0000648 E = moduleConstants.end(); I != E; ++I)
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000649 printConstant(*I);
650
651 // Initialized read-write data section
652 for (Module::const_giterator GI=M->gbegin(), GE=M->gend(); GI != GE; ++GI)
653 {
654 const GlobalVariable* GV = *GI;
655 if (GV->hasInitializer() && ! GV->isConstant())
656 {
657 if (GI == M->gbegin())
658 enterSection(InitRWData);
659 printGlobalVariable(GV);
660 }
661 }
662
663 // Uninitialized read-write data section
664 for (Module::const_giterator GI=M->gbegin(), GE=M->gend(); GI != GE; ++GI)
665 {
666 const GlobalVariable* GV = *GI;
667 if (! GV->hasInitializer())
668 {
669 if (GI == M->gbegin())
670 enterSection(UninitRWData);
671 printGlobalVariable(GV);
672 }
673 }
674
Chris Lattner697954c2002-01-20 22:54:45 +0000675 toAsm << "\n";
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000676}
677
Chris Lattnere88f78c2001-09-19 13:47:27 +0000678} // End anonymous namespace
679
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000680
Chris Lattnere88f78c2001-09-19 13:47:27 +0000681//
Chris Lattnerc019a172002-02-03 07:48:06 +0000682// emitAssembly - Output assembly language code (a .s file) for global
683// components of the specified module. This assumes that methods have been
684// previously output.
685//
686void
687UltraSparc::emitAssembly(const Method *M, std::ostream &OutStr) const
688{
689 SparcAsmPrinter Print(OutStr, M->getParent(), *this);
690 Print.emitMethod(M);
691}
692
693//
Chris Lattnere88f78c2001-09-19 13:47:27 +0000694// emitAssembly - Output assembly language code (a .s file) for the specified
695// method. The specified method must have been compiled before this may be
696// used.
697//
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000698void
Chris Lattnerc019a172002-02-03 07:48:06 +0000699UltraSparc::emitAssembly(const Module *M, std::ostream &OutStr) const
Vikram S. Adve953c83e2001-10-28 21:38:52 +0000700{
Chris Lattnerc019a172002-02-03 07:48:06 +0000701 SparcAsmPrinter Print(OutStr, M, *this);
702 Print.emitGlobalsAndConstants(M);
Chris Lattnere88f78c2001-09-19 13:47:27 +0000703}
Chris Lattnerc019a172002-02-03 07:48:06 +0000704