blob: 8473c1556fb473d923873b1bb073ea658bf4ca61 [file] [log] [blame]
Brian Gaeke4acfd032004-03-04 06:00:41 +00001//===-- SparcV8AsmPrinter.cpp - SparcV8 LLVM assembly writer --------------===//
Misha Brukmanb5f662f2005-04-21 23:30:14 +00002//
Brian Gaeke4acfd032004-03-04 06:00:41 +00003// 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.
Misha Brukmanb5f662f2005-04-21 23:30:14 +00007//
Brian Gaeke4acfd032004-03-04 06:00:41 +00008//===----------------------------------------------------------------------===//
9//
10// This file contains a printer that converts from our internal representation
11// of machine-dependent LLVM code to GAS-format Sparc V8 assembly language.
12//
13//===----------------------------------------------------------------------===//
14
15#include "SparcV8.h"
16#include "SparcV8InstrInfo.h"
17#include "llvm/Constants.h"
18#include "llvm/DerivedTypes.h"
19#include "llvm/Module.h"
20#include "llvm/Assembly/Writer.h"
Chris Lattner1dbed162005-12-17 07:04:29 +000021#include "llvm/CodeGen/AsmPrinter.h"
Brian Gaeke4acfd032004-03-04 06:00:41 +000022#include "llvm/CodeGen/MachineFunctionPass.h"
23#include "llvm/CodeGen/MachineConstantPool.h"
24#include "llvm/CodeGen/MachineInstr.h"
25#include "llvm/Target/TargetMachine.h"
26#include "llvm/Support/Mangler.h"
Brian Gaeke74dfcf12004-09-02 02:37:43 +000027#include "llvm/ADT/Statistic.h"
28#include "llvm/ADT/StringExtras.h"
29#include "llvm/Support/CommandLine.h"
Jim Laskeyb8df7c22005-08-17 20:04:34 +000030#include "llvm/Support/MathExtras.h"
Brian Gaekea8b00ca2004-03-06 05:30:21 +000031#include <cctype>
Brian Gaeke4acfd032004-03-04 06:00:41 +000032using namespace llvm;
33
34namespace {
35 Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
36
Chris Lattner1dbed162005-12-17 07:04:29 +000037 struct SparcV8AsmPrinter : public AsmPrinter {
38 SparcV8AsmPrinter(std::ostream &O, TargetMachine &TM) : AsmPrinter(O, TM) {}
Brian Gaeke4acfd032004-03-04 06:00:41 +000039
40 /// We name each basic block in a Function with a unique number, so
41 /// that we can consistently refer to them later. This is cleared
42 /// at the beginning of each call to runOnMachineFunction().
43 ///
44 typedef std::map<const Value *, unsigned> ValueMapTy;
45 ValueMapTy NumberForBB;
46
Brian Gaeke4acfd032004-03-04 06:00:41 +000047 virtual const char *getPassName() const {
48 return "SparcV8 Assembly Printer";
49 }
50
51 void emitConstantValueOnly(const Constant *CV);
52 void emitGlobalConstant(const Constant *CV);
53 void printConstantPool(MachineConstantPool *MCP);
Brian Gaeke446ae112004-06-15 19:52:59 +000054 void printOperand(const MachineInstr *MI, int opNum);
Chris Lattner994b7352005-12-16 06:34:17 +000055 bool printInstruction(const MachineInstr *MI); // autogenerated.
Misha Brukmanb5f662f2005-04-21 23:30:14 +000056 bool runOnMachineFunction(MachineFunction &F);
Brian Gaeke4acfd032004-03-04 06:00:41 +000057 bool doInitialization(Module &M);
58 bool doFinalization(Module &M);
59 };
60} // end of anonymous namespace
61
Chris Lattner994b7352005-12-16 06:34:17 +000062#include "SparcV8GenAsmWriter.inc"
63
Brian Gaeke4acfd032004-03-04 06:00:41 +000064/// createSparcV8CodePrinterPass - Returns a pass that prints the SparcV8
65/// assembly code for a MachineFunction to the given output stream,
66/// using the given target machine description. This should work
67/// regardless of whether the function is in SSA form.
68///
69FunctionPass *llvm::createSparcV8CodePrinterPass (std::ostream &o,
70 TargetMachine &tm) {
Chris Lattner994b7352005-12-16 06:34:17 +000071 return new SparcV8AsmPrinter(o, tm);
Brian Gaeke4acfd032004-03-04 06:00:41 +000072}
73
74/// toOctal - Convert the low order bits of X into an octal digit.
75///
76static inline char toOctal(int X) {
77 return (X&7)+'0';
78}
79
80/// getAsCString - Return the specified array as a C compatible
81/// string, only if the predicate isStringCompatible is true.
82///
83static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
84 assert(CVA->isString() && "Array is not string compatible!");
85
86 O << "\"";
87 for (unsigned i = 0; i != CVA->getNumOperands(); ++i) {
88 unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
89
90 if (C == '"') {
91 O << "\\\"";
92 } else if (C == '\\') {
93 O << "\\\\";
94 } else if (isprint(C)) {
95 O << C;
96 } else {
97 switch(C) {
98 case '\b': O << "\\b"; break;
99 case '\f': O << "\\f"; break;
100 case '\n': O << "\\n"; break;
101 case '\r': O << "\\r"; break;
102 case '\t': O << "\\t"; break;
103 default:
104 O << '\\';
105 O << toOctal(C >> 6);
106 O << toOctal(C >> 3);
107 O << toOctal(C >> 0);
108 break;
109 }
110 }
111 }
112 O << "\"";
113}
114
115// Print out the specified constant, without a storage class. Only the
116// constants valid in constant expressions can occur here.
Chris Lattner994b7352005-12-16 06:34:17 +0000117void SparcV8AsmPrinter::emitConstantValueOnly(const Constant *CV) {
Brian Gaeke54799c22004-11-14 03:22:05 +0000118 if (CV->isNullValue() || isa<UndefValue> (CV))
Brian Gaeke4acfd032004-03-04 06:00:41 +0000119 O << "0";
120 else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
121 assert(CB == ConstantBool::True);
122 O << "1";
123 } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
124 if (((CI->getValue() << 32) >> 32) == CI->getValue())
125 O << CI->getValue();
126 else
127 O << (unsigned long long)CI->getValue();
128 else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
129 O << CI->getValue();
Chris Lattner73302482004-07-18 07:26:17 +0000130 else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
Brian Gaeke4acfd032004-03-04 06:00:41 +0000131 // This is a constant address for a global variable or function. Use the
132 // name of the variable or function as the address value.
Chris Lattner73302482004-07-18 07:26:17 +0000133 O << Mang->getValueName(GV);
Brian Gaeke4acfd032004-03-04 06:00:41 +0000134 else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
135 const TargetData &TD = TM.getTargetData();
136 switch(CE->getOpcode()) {
137 case Instruction::GetElementPtr: {
138 // generate a symbolic expression for the byte address
139 const Constant *ptrVal = CE->getOperand(0);
140 std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
141 if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
142 O << "(";
143 emitConstantValueOnly(ptrVal);
144 O << ") + " << Offset;
145 } else {
146 emitConstantValueOnly(ptrVal);
147 }
148 break;
149 }
150 case Instruction::Cast: {
151 // Support only non-converting or widening casts for now, that is, ones
152 // that do not involve a change in value. This assertion is really gross,
153 // and may not even be a complete check.
154 Constant *Op = CE->getOperand(0);
155 const Type *OpTy = Op->getType(), *Ty = CE->getType();
156
157 // Pointers on ILP32 machines can be losslessly converted back and
158 // forth into 32-bit or wider integers, regardless of signedness.
159 assert(((isa<PointerType>(OpTy)
160 && (Ty == Type::LongTy || Ty == Type::ULongTy
161 || Ty == Type::IntTy || Ty == Type::UIntTy))
162 || (isa<PointerType>(Ty)
163 && (OpTy == Type::LongTy || OpTy == Type::ULongTy
164 || OpTy == Type::IntTy || OpTy == Type::UIntTy))
165 || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
166 && OpTy->isLosslesslyConvertibleTo(Ty))))
167 && "FIXME: Don't yet support this kind of constant cast expr");
168 O << "(";
169 emitConstantValueOnly(Op);
170 O << ")";
171 break;
172 }
173 case Instruction::Add:
174 O << "(";
175 emitConstantValueOnly(CE->getOperand(0));
176 O << ") + (";
177 emitConstantValueOnly(CE->getOperand(1));
178 O << ")";
179 break;
180 default:
181 assert(0 && "Unsupported operator!");
182 }
183 } else {
184 assert(0 && "Unknown constant value!");
185 }
186}
187
188// Print a constant value or values, with the appropriate storage class as a
189// prefix.
Chris Lattner994b7352005-12-16 06:34:17 +0000190void SparcV8AsmPrinter::emitGlobalConstant(const Constant *CV) {
Brian Gaeke4acfd032004-03-04 06:00:41 +0000191 const TargetData &TD = TM.getTargetData();
192
Brian Gaeke9d2427c2004-06-18 08:59:16 +0000193 if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
Brian Gaeke4acfd032004-03-04 06:00:41 +0000194 if (CVA->isString()) {
195 O << "\t.ascii\t";
196 printAsCString(O, CVA);
197 O << "\n";
198 } else { // Not a string. Print the values in successive locations
Chris Lattnercdf70122004-08-04 17:27:27 +0000199 for (unsigned i = 0, e = CVA->getNumOperands(); i != e; i++)
200 emitGlobalConstant(CVA->getOperand(i));
Brian Gaeke4acfd032004-03-04 06:00:41 +0000201 }
202 return;
203 } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
204 // Print the fields in successive locations. Pad to align if needed!
205 const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
Brian Gaeke4acfd032004-03-04 06:00:41 +0000206 unsigned sizeSoFar = 0;
Chris Lattnercdf70122004-08-04 17:27:27 +0000207 for (unsigned i = 0, e = CVS->getNumOperands(); i != e; i++) {
208 const Constant* field = CVS->getOperand(i);
Brian Gaeke4acfd032004-03-04 06:00:41 +0000209
210 // Check if padding is needed and insert one or more 0s.
211 unsigned fieldSize = TD.getTypeSize(field->getType());
Chris Lattnercdf70122004-08-04 17:27:27 +0000212 unsigned padSize = ((i == e-1? cvsLayout->StructSize
Brian Gaeke4acfd032004-03-04 06:00:41 +0000213 : cvsLayout->MemberOffsets[i+1])
214 - cvsLayout->MemberOffsets[i]) - fieldSize;
215 sizeSoFar += fieldSize + padSize;
216
217 // Now print the actual field value
218 emitGlobalConstant(field);
219
220 // Insert the field padding unless it's zero bytes...
221 if (padSize)
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000222 O << "\t.skip\t " << padSize << "\n";
Brian Gaeke4acfd032004-03-04 06:00:41 +0000223 }
224 assert(sizeSoFar == cvsLayout->StructSize &&
225 "Layout of constant struct may be incorrect!");
226 return;
227 } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
228 // FP Constants are printed as integer constants to avoid losing
229 // precision...
230 double Val = CFP->getValue();
Chris Lattnerf70c22b2004-06-17 18:19:28 +0000231 switch (CFP->getType()->getTypeID()) {
Brian Gaeke4acfd032004-03-04 06:00:41 +0000232 default: assert(0 && "Unknown floating point type!");
233 case Type::FloatTyID: {
Jim Laskeycb6682f2005-08-17 19:34:49 +0000234 O << ".long\t" << FloatToBits(Val) << "\t! float " << Val << "\n";
Brian Gaeke4acfd032004-03-04 06:00:41 +0000235 return;
236 }
237 case Type::DoubleTyID: {
Jim Laskeycb6682f2005-08-17 19:34:49 +0000238 O << ".word\t0x" << std::hex << (DoubleToBits(Val) >> 32) << std::dec << "\t! double " << Val << "\n";
239 O << ".word\t0x" << std::hex << (DoubleToBits(Val) & 0xffffffffUL) << std::dec << "\t! double " << Val << "\n";
Brian Gaeke4acfd032004-03-04 06:00:41 +0000240 return;
241 }
242 }
Brian Gaeke54799c22004-11-14 03:22:05 +0000243 } else if (isa<UndefValue> (CV)) {
244 unsigned size = TD.getTypeSize (CV->getType ());
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000245 O << "\t.skip\t " << size << "\n";
Brian Gaeke54799c22004-11-14 03:22:05 +0000246 return;
Brian Gaeke4dd043f2004-11-23 21:10:49 +0000247 } else if (isa<ConstantAggregateZero> (CV)) {
248 unsigned size = TD.getTypeSize (CV->getType ());
249 for (unsigned i = 0; i < size; ++i)
Misha Brukman27177f82005-04-22 18:06:01 +0000250 O << "\t.byte 0\n";
Brian Gaeke4dd043f2004-11-23 21:10:49 +0000251 return;
Brian Gaeke4acfd032004-03-04 06:00:41 +0000252 }
253
254 const Type *type = CV->getType();
255 O << "\t";
Chris Lattnerf70c22b2004-06-17 18:19:28 +0000256 switch (type->getTypeID()) {
Brian Gaeke4acfd032004-03-04 06:00:41 +0000257 case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
258 O << ".byte";
259 break;
260 case Type::UShortTyID: case Type::ShortTyID:
Brian Gaeke3bf960c2004-12-09 18:51:01 +0000261 O << ".half";
Brian Gaeke4acfd032004-03-04 06:00:41 +0000262 break;
263 case Type::FloatTyID: case Type::PointerTyID:
264 case Type::UIntTyID: case Type::IntTyID:
Brian Gaeke3bf960c2004-12-09 18:51:01 +0000265 O << ".word";
Brian Gaeke4acfd032004-03-04 06:00:41 +0000266 break;
267 case Type::DoubleTyID:
268 case Type::ULongTyID: case Type::LongTyID:
Brian Gaeke3bf960c2004-12-09 18:51:01 +0000269 O << ".xword";
Brian Gaeke4acfd032004-03-04 06:00:41 +0000270 break;
271 default:
272 assert (0 && "Can't handle printing this type of thing");
273 break;
274 }
275 O << "\t";
276 emitConstantValueOnly(CV);
277 O << "\n";
278}
279
280/// printConstantPool - Print to the current output stream assembly
281/// representations of the constants in the constant pool MCP. This is
282/// used to print out constants which have been "spilled to memory" by
283/// the code generator.
284///
Chris Lattner994b7352005-12-16 06:34:17 +0000285void SparcV8AsmPrinter::printConstantPool(MachineConstantPool *MCP) {
Brian Gaeke4acfd032004-03-04 06:00:41 +0000286 const std::vector<Constant*> &CP = MCP->getConstants();
287 const TargetData &TD = TM.getTargetData();
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000288
Brian Gaeke4acfd032004-03-04 06:00:41 +0000289 if (CP.empty()) return;
290
Chris Lattner1dbed162005-12-17 07:04:29 +0000291 SwitchSection(".section \".rodata\"\n", 0);
Brian Gaeke4acfd032004-03-04 06:00:41 +0000292 for (unsigned i = 0, e = CP.size(); i != e; ++i) {
Brian Gaeke4acfd032004-03-04 06:00:41 +0000293 O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType())
294 << "\n";
Brian Gaeke79db7402004-03-16 22:37:12 +0000295 O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t!"
Brian Gaeke4acfd032004-03-04 06:00:41 +0000296 << *CP[i] << "\n";
297 emitGlobalConstant(CP[i]);
298 }
299}
300
301/// runOnMachineFunction - This uses the printMachineInstruction()
302/// method to print assembly for each instruction.
303///
Chris Lattner994b7352005-12-16 06:34:17 +0000304bool SparcV8AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
Chris Lattner1dbed162005-12-17 07:04:29 +0000305 SetupMachineFunction(MF);
306
Brian Gaeke4acfd032004-03-04 06:00:41 +0000307 // BBNumber is used here so that a given Printer will never give two
308 // BBs the same name. (If you have a better way, please let me know!)
309 static unsigned BBNumber = 0;
310
311 O << "\n\n";
312 // What's my mangled name?
313 CurrentFnName = Mang->getValueName(MF.getFunction());
314
315 // Print out constants referenced by the function
316 printConstantPool(MF.getConstantPool());
317
318 // Print out labels for the function.
319 O << "\t.text\n";
320 O << "\t.align 16\n";
321 O << "\t.globl\t" << CurrentFnName << "\n";
Brian Gaeke54cc3c22004-03-16 22:52:04 +0000322 O << "\t.type\t" << CurrentFnName << ", #function\n";
Brian Gaeke4acfd032004-03-04 06:00:41 +0000323 O << CurrentFnName << ":\n";
324
325 // Number each basic block so that we can consistently refer to them
326 // in PC-relative references.
327 NumberForBB.clear();
328 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
329 I != E; ++I) {
330 NumberForBB[I->getBasicBlock()] = BBNumber++;
331 }
332
333 // Print out code for the function.
334 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
335 I != E; ++I) {
336 // Print a label for the basic block.
Brian Gaeke09c13092004-06-17 19:39:23 +0000337 O << ".LBB" << Mang->getValueName(MF.getFunction ())
338 << "_" << I->getNumber () << ":\t! "
339 << I->getBasicBlock ()->getName () << "\n";
Brian Gaeke4acfd032004-03-04 06:00:41 +0000340 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
Misha Brukman27177f82005-04-22 18:06:01 +0000341 II != E; ++II) {
Brian Gaeke4acfd032004-03-04 06:00:41 +0000342 // Print the assembly for the instruction.
Chris Lattner0d8fcd32005-12-17 06:54:41 +0000343 O << "\t";
344 printInstruction(II);
Chris Lattner1dbed162005-12-17 07:04:29 +0000345 ++EmittedInsts;
Brian Gaeke4acfd032004-03-04 06:00:41 +0000346 }
347 }
348
349 // We didn't modify anything.
350 return false;
351}
352
Chris Lattner994b7352005-12-16 06:34:17 +0000353void SparcV8AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
Brian Gaeke446ae112004-06-15 19:52:59 +0000354 const MachineOperand &MO = MI->getOperand (opNum);
Brian Gaeke62aa28a2004-03-05 08:39:09 +0000355 const MRegisterInfo &RI = *TM.getRegisterInfo();
Brian Gaeke446ae112004-06-15 19:52:59 +0000356 bool CloseParen = false;
357 if (MI->getOpcode() == V8::SETHIi && !MO.isRegister() && !MO.isImmediate()) {
358 O << "%hi(";
359 CloseParen = true;
Misha Brukmanf54ef972004-06-24 23:38:20 +0000360 } else if (MI->getOpcode() ==V8::ORri &&!MO.isRegister() &&!MO.isImmediate())
361 {
Brian Gaeke446ae112004-06-15 19:52:59 +0000362 O << "%lo(";
363 CloseParen = true;
364 }
Brian Gaeke62aa28a2004-03-05 08:39:09 +0000365 switch (MO.getType()) {
366 case MachineOperand::MO_VirtualRegister:
367 if (Value *V = MO.getVRegValueOrNull()) {
368 O << "<" << V->getName() << ">";
Brian Gaeke446ae112004-06-15 19:52:59 +0000369 break;
Brian Gaeke62aa28a2004-03-05 08:39:09 +0000370 }
371 // FALLTHROUGH
372 case MachineOperand::MO_MachineRegister:
373 if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
Brian Gaekea8b00ca2004-03-06 05:30:21 +0000374 O << "%" << LowercaseString (RI.get(MO.getReg()).Name);
Brian Gaeke62aa28a2004-03-05 08:39:09 +0000375 else
376 O << "%reg" << MO.getReg();
Brian Gaeke446ae112004-06-15 19:52:59 +0000377 break;
Brian Gaeke62aa28a2004-03-05 08:39:09 +0000378
379 case MachineOperand::MO_SignExtendedImmed:
380 case MachineOperand::MO_UnextendedImmed:
381 O << (int)MO.getImmedValue();
Brian Gaeke446ae112004-06-15 19:52:59 +0000382 break;
Brian Gaeke09c13092004-06-17 19:39:23 +0000383 case MachineOperand::MO_MachineBasicBlock: {
384 MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
385 O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
386 << "_" << MBBOp->getNumber () << "\t! "
387 << MBBOp->getBasicBlock ()->getName ();
388 return;
Brian Gaeke62aa28a2004-03-05 08:39:09 +0000389 }
Brian Gaeke09c13092004-06-17 19:39:23 +0000390 case MachineOperand::MO_PCRelativeDisp:
391 std::cerr << "Shouldn't use addPCDisp() when building SparcV8 MachineInstrs";
392 abort ();
393 return;
Brian Gaeke62aa28a2004-03-05 08:39:09 +0000394 case MachineOperand::MO_GlobalAddress:
395 O << Mang->getValueName(MO.getGlobal());
Brian Gaeke446ae112004-06-15 19:52:59 +0000396 break;
Brian Gaeke62aa28a2004-03-05 08:39:09 +0000397 case MachineOperand::MO_ExternalSymbol:
398 O << MO.getSymbolName();
Brian Gaeke446ae112004-06-15 19:52:59 +0000399 break;
Brian Gaeke8a0ae9e2004-06-27 22:50:44 +0000400 case MachineOperand::MO_ConstantPoolIndex:
401 O << ".CPI" << CurrentFnName << "_" << MO.getConstantPoolIndex();
402 break;
Brian Gaeke62aa28a2004-03-05 08:39:09 +0000403 default:
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000404 O << "<unknown operand type>"; abort (); break;
Brian Gaeke62aa28a2004-03-05 08:39:09 +0000405 }
Brian Gaeke446ae112004-06-15 19:52:59 +0000406 if (CloseParen) O << ")";
Brian Gaeke62aa28a2004-03-05 08:39:09 +0000407}
408
Chris Lattner994b7352005-12-16 06:34:17 +0000409bool SparcV8AsmPrinter::doInitialization(Module &M) {
Brian Gaeke4acfd032004-03-04 06:00:41 +0000410 Mang = new Mangler(M);
411 return false; // success
412}
413
Chris Lattner994b7352005-12-16 06:34:17 +0000414bool SparcV8AsmPrinter::doFinalization(Module &M) {
Brian Gaeke4acfd032004-03-04 06:00:41 +0000415 const TargetData &TD = TM.getTargetData();
Brian Gaeke4acfd032004-03-04 06:00:41 +0000416
417 // Print out module-level global variables here.
Chris Lattnere4d5c442005-03-15 04:54:21 +0000418 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
Brian Gaeke4acfd032004-03-04 06:00:41 +0000419 if (I->hasInitializer()) { // External global require no code
420 O << "\n\n";
421 std::string name = Mang->getValueName(I);
422 Constant *C = I->getInitializer();
423 unsigned Size = TD.getTypeSize(C->getType());
424 unsigned Align = TD.getTypeAlignment(C->getType());
425
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000426 if (C->isNullValue() &&
Brian Gaeke4acfd032004-03-04 06:00:41 +0000427 (I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
428 I->hasWeakLinkage() /* FIXME: Verify correct */)) {
Chris Lattner1dbed162005-12-17 07:04:29 +0000429 SwitchSection(".data", I);
Brian Gaeke4acfd032004-03-04 06:00:41 +0000430 if (I->hasInternalLinkage())
431 O << "\t.local " << name << "\n";
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000432
Brian Gaeke4acfd032004-03-04 06:00:41 +0000433 O << "\t.comm " << name << "," << TD.getTypeSize(C->getType())
434 << "," << (unsigned)TD.getTypeAlignment(C->getType());
Brian Gaeke79db7402004-03-16 22:37:12 +0000435 O << "\t\t! ";
Brian Gaeke4acfd032004-03-04 06:00:41 +0000436 WriteAsOperand(O, I, true, true, &M);
437 O << "\n";
438 } else {
439 switch (I->getLinkage()) {
440 case GlobalValue::LinkOnceLinkage:
441 case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
442 // Nonnull linkonce -> weak
443 O << "\t.weak " << name << "\n";
Chris Lattner1dbed162005-12-17 07:04:29 +0000444 SwitchSection("", I);
445 O << "\t.section\t\".llvm.linkonce.d." << name
446 << "\",\"aw\",@progbits\n";
Brian Gaeke4acfd032004-03-04 06:00:41 +0000447 break;
Misha Brukmanb5f662f2005-04-21 23:30:14 +0000448
Brian Gaeke4acfd032004-03-04 06:00:41 +0000449 case GlobalValue::AppendingLinkage:
450 // FIXME: appending linkage variables should go into a section of
451 // their name or something. For now, just emit them as external.
452 case GlobalValue::ExternalLinkage:
453 // If external or appending, declare as a global symbol
454 O << "\t.globl " << name << "\n";
455 // FALL THROUGH
456 case GlobalValue::InternalLinkage:
457 if (C->isNullValue())
Chris Lattner1dbed162005-12-17 07:04:29 +0000458 SwitchSection(".bss", I);
Brian Gaeke4acfd032004-03-04 06:00:41 +0000459 else
Chris Lattner1dbed162005-12-17 07:04:29 +0000460 SwitchSection(".data", I);
Brian Gaeke4acfd032004-03-04 06:00:41 +0000461 break;
Misha Brukmanc11c44f2004-11-19 21:49:19 +0000462 case GlobalValue::GhostLinkage:
463 std::cerr << "Should not have any unmaterialized functions!\n";
464 abort();
Brian Gaeke4acfd032004-03-04 06:00:41 +0000465 }
466
467 O << "\t.align " << Align << "\n";
Brian Gaeke54cc3c22004-03-16 22:52:04 +0000468 O << "\t.type " << name << ",#object\n";
Brian Gaeke4acfd032004-03-04 06:00:41 +0000469 O << "\t.size " << name << "," << Size << "\n";
Brian Gaeke79db7402004-03-16 22:37:12 +0000470 O << name << ":\t\t\t\t! ";
Brian Gaeke4acfd032004-03-04 06:00:41 +0000471 WriteAsOperand(O, I, true, true, &M);
472 O << " = ";
473 WriteAsOperand(O, C, false, false, &M);
474 O << "\n";
475 emitGlobalConstant(C);
476 }
477 }
478
Chris Lattner1dbed162005-12-17 07:04:29 +0000479 AsmPrinter::doFinalization(M);
Brian Gaeke4acfd032004-03-04 06:00:41 +0000480 return false; // success
481}