blob: afe7c35470ba757a2c45605d19d88d4b0fa582ab [file] [log] [blame]
Misha Brukman3d9a6c22004-08-11 00:09:42 +00001//===-- PPC32AsmPrinter.cpp - Print machine instrs to PowerPC assembly ----===//
Misha Brukman5dfe3a92004-06-21 16:55:25 +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//===----------------------------------------------------------------------===//
9//
Misha Brukman05fcd0c2004-07-08 17:58:04 +000010// This file contains a printer that converts from our internal representation
11// of machine-dependent LLVM code to PowerPC assembly language. This printer is
Chris Lattner83660c52004-07-28 20:18:53 +000012// the output mechanism used by `llc'.
Misha Brukman5dfe3a92004-06-21 16:55:25 +000013//
Misha Brukman05fcd0c2004-07-08 17:58:04 +000014// Documentation at http://developer.apple.com/documentation/DeveloperTools/
15// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html
Misha Brukman218bec72004-06-29 17:13:26 +000016//
Misha Brukman5dfe3a92004-06-21 16:55:25 +000017//===----------------------------------------------------------------------===//
18
Misha Brukman05794492004-06-24 17:31:42 +000019#define DEBUG_TYPE "asmprinter"
Misha Brukman5dfe3a92004-06-21 16:55:25 +000020#include "PowerPC.h"
21#include "PowerPCInstrInfo.h"
Nate Begemane59bf592004-08-14 22:09:10 +000022#include "PowerPCTargetMachine.h"
Misha Brukman5dfe3a92004-06-21 16:55:25 +000023#include "llvm/Constants.h"
24#include "llvm/DerivedTypes.h"
25#include "llvm/Module.h"
26#include "llvm/Assembly/Writer.h"
Misha Brukman5dfe3a92004-06-21 16:55:25 +000027#include "llvm/CodeGen/MachineConstantPool.h"
Misha Brukman05794492004-06-24 17:31:42 +000028#include "llvm/CodeGen/MachineFunctionPass.h"
Misha Brukman5dfe3a92004-06-21 16:55:25 +000029#include "llvm/CodeGen/MachineInstr.h"
30#include "llvm/Target/TargetMachine.h"
31#include "llvm/Support/Mangler.h"
Misha Brukman05794492004-06-24 17:31:42 +000032#include "Support/CommandLine.h"
33#include "Support/Debug.h"
Misha Brukman5dfe3a92004-06-21 16:55:25 +000034#include "Support/Statistic.h"
35#include "Support/StringExtras.h"
Misha Brukman05794492004-06-24 17:31:42 +000036#include <set>
Misha Brukman5dfe3a92004-06-21 16:55:25 +000037
38namespace llvm {
39
40namespace {
41 Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
42
Nate Begemane59bf592004-08-14 22:09:10 +000043 struct PowerPCAsmPrinter : public MachineFunctionPass {
Misha Brukman5dfe3a92004-06-21 16:55:25 +000044 /// Output stream on which we're printing assembly code.
45 ///
46 std::ostream &O;
47
48 /// Target machine description which we query for reg. names, data
49 /// layout, etc.
50 ///
Nate Begemane59bf592004-08-14 22:09:10 +000051 PowerPCTargetMachine &TM;
Misha Brukman5dfe3a92004-06-21 16:55:25 +000052
53 /// Name-mangler for global names.
54 ///
55 Mangler *Mang;
Misha Brukman97a296f2004-07-21 20:11:11 +000056 std::set<std::string> FnStubs, GVStubs, LinkOnceStubs;
Misha Brukman5dfe3a92004-06-21 16:55:25 +000057 std::set<std::string> Strings;
58
Nate Begemane59bf592004-08-14 22:09:10 +000059 PowerPCAsmPrinter(std::ostream &o, TargetMachine &tm) : O(o),
60 TM(reinterpret_cast<PowerPCTargetMachine&>(tm)), LabelNumber(0) {}
Misha Brukman5dfe3a92004-06-21 16:55:25 +000061
Misha Brukman5dfe3a92004-06-21 16:55:25 +000062 /// Cache of mangled name for current function. This is
63 /// recalculated at the beginning of each call to
64 /// runOnMachineFunction().
65 ///
66 std::string CurrentFnName;
67
Misha Brukmancf8d2442004-07-26 16:28:33 +000068 /// Unique incrementer for label values for referencing Global values.
Misha Brukman218bec72004-06-29 17:13:26 +000069 ///
Misha Brukmancf8d2442004-07-26 16:28:33 +000070 unsigned LabelNumber;
71
Misha Brukman5dfe3a92004-06-21 16:55:25 +000072 virtual const char *getPassName() const {
Nate Begemane59bf592004-08-14 22:09:10 +000073 return "PowerPC Assembly Printer";
Misha Brukman5dfe3a92004-06-21 16:55:25 +000074 }
75
Nate Begemane59bf592004-08-14 22:09:10 +000076 /// printInstruction - This method is automatically generated by tablegen
77 /// from the instruction set description. This method returns true if the
78 /// machine instruction was sufficiently described to print it, otherwise it
79 /// returns false.
80 bool printInstruction(const MachineInstr *MI);
81
Misha Brukman5dfe3a92004-06-21 16:55:25 +000082 void printMachineInstruction(const MachineInstr *MI);
Nate Begemanb73a7112004-08-13 09:32:01 +000083 void printOp(const MachineOperand &MO, bool LoadAddrOp = false);
Misha Brukmanaf313fb2004-07-28 00:00:48 +000084 void printImmOp(const MachineOperand &MO, unsigned ArgType);
Misha Brukman5dfe3a92004-06-21 16:55:25 +000085 void printConstantPool(MachineConstantPool *MCP);
86 bool runOnMachineFunction(MachineFunction &F);
87 bool doInitialization(Module &M);
88 bool doFinalization(Module &M);
89 void emitGlobalConstant(const Constant* CV);
90 void emitConstantValueOnly(const Constant *CV);
91 };
92} // end of anonymous namespace
93
Misha Brukman3d9a6c22004-08-11 00:09:42 +000094/// createPPC32AsmPrinterPass - Returns a pass that prints the PPC
Misha Brukman5dfe3a92004-06-21 16:55:25 +000095/// assembly code for a MachineFunction to the given output stream,
96/// using the given target machine description. This should work
Misha Brukman7103fba2004-08-09 22:27:45 +000097/// regardless of whether the function is in SSA form or not.
Misha Brukman5dfe3a92004-06-21 16:55:25 +000098///
Nate Begemane59bf592004-08-14 22:09:10 +000099FunctionPass *createPPCAsmPrinter(std::ostream &o,TargetMachine &tm) {
100 return new PowerPCAsmPrinter(o, tm);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000101}
102
Nate Begemane59bf592004-08-14 22:09:10 +0000103// Include the auto-generated portion of the assembly writer
104#include "PowerPCGenAsmWriter.inc"
105
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000106/// isStringCompatible - Can we treat the specified array as a string?
107/// Only if it is an array of ubytes or non-negative sbytes.
108///
109static bool isStringCompatible(const ConstantArray *CVA) {
110 const Type *ETy = cast<ArrayType>(CVA->getType())->getElementType();
111 if (ETy == Type::UByteTy) return true;
112 if (ETy != Type::SByteTy) return false;
113
114 for (unsigned i = 0; i < CVA->getNumOperands(); ++i)
115 if (cast<ConstantSInt>(CVA->getOperand(i))->getValue() < 0)
116 return false;
117
118 return true;
119}
120
121/// toOctal - Convert the low order bits of X into an octal digit.
122///
123static inline char toOctal(int X) {
124 return (X&7)+'0';
125}
126
127/// getAsCString - Return the specified array as a C compatible
128/// string, only if the predicate isStringCompatible is true.
129///
130static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
131 assert(isStringCompatible(CVA) && "Array is not string compatible!");
132
133 O << "\"";
134 for (unsigned i = 0; i < CVA->getNumOperands(); ++i) {
135 unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
136
137 if (C == '"') {
138 O << "\\\"";
139 } else if (C == '\\') {
140 O << "\\\\";
141 } else if (isprint(C)) {
142 O << C;
143 } else {
Misha Brukmane2eceb52004-07-23 16:08:20 +0000144 switch (C) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000145 case '\b': O << "\\b"; break;
146 case '\f': O << "\\f"; break;
147 case '\n': O << "\\n"; break;
148 case '\r': O << "\\r"; break;
149 case '\t': O << "\\t"; break;
150 default:
151 O << '\\';
152 O << toOctal(C >> 6);
153 O << toOctal(C >> 3);
154 O << toOctal(C >> 0);
155 break;
156 }
157 }
158 }
159 O << "\"";
160}
161
162// Print out the specified constant, without a storage class. Only the
163// constants valid in constant expressions can occur here.
Nate Begemane59bf592004-08-14 22:09:10 +0000164void PowerPCAsmPrinter::emitConstantValueOnly(const Constant *CV) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000165 if (CV->isNullValue())
166 O << "0";
167 else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
168 assert(CB == ConstantBool::True);
169 O << "1";
170 } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
171 O << CI->getValue();
172 else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
173 O << CI->getValue();
Chris Lattner67910e12004-07-18 07:29:35 +0000174 else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000175 // This is a constant address for a global variable or function. Use the
176 // name of the variable or function as the address value.
Chris Lattner67910e12004-07-18 07:29:35 +0000177 O << Mang->getValueName(GV);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000178 else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
179 const TargetData &TD = TM.getTargetData();
Misha Brukmane2eceb52004-07-23 16:08:20 +0000180 switch (CE->getOpcode()) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000181 case Instruction::GetElementPtr: {
182 // generate a symbolic expression for the byte address
183 const Constant *ptrVal = CE->getOperand(0);
184 std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
185 if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
186 O << "(";
187 emitConstantValueOnly(ptrVal);
188 O << ") + " << Offset;
189 } else {
190 emitConstantValueOnly(ptrVal);
191 }
192 break;
193 }
194 case Instruction::Cast: {
195 // Support only non-converting or widening casts for now, that is, ones
196 // that do not involve a change in value. This assertion is really gross,
197 // and may not even be a complete check.
198 Constant *Op = CE->getOperand(0);
199 const Type *OpTy = Op->getType(), *Ty = CE->getType();
200
201 // Remember, kids, pointers on x86 can be losslessly converted back and
202 // forth into 32-bit or wider integers, regardless of signedness. :-P
203 assert(((isa<PointerType>(OpTy)
204 && (Ty == Type::LongTy || Ty == Type::ULongTy
205 || Ty == Type::IntTy || Ty == Type::UIntTy))
206 || (isa<PointerType>(Ty)
207 && (OpTy == Type::LongTy || OpTy == Type::ULongTy
208 || OpTy == Type::IntTy || OpTy == Type::UIntTy))
209 || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
210 && OpTy->isLosslesslyConvertibleTo(Ty))))
211 && "FIXME: Don't yet support this kind of constant cast expr");
212 O << "(";
213 emitConstantValueOnly(Op);
214 O << ")";
215 break;
216 }
217 case Instruction::Add:
218 O << "(";
219 emitConstantValueOnly(CE->getOperand(0));
220 O << ") + (";
221 emitConstantValueOnly(CE->getOperand(1));
222 O << ")";
223 break;
224 default:
225 assert(0 && "Unsupported operator!");
226 }
227 } else {
228 assert(0 && "Unknown constant value!");
229 }
230}
231
232// Print a constant value or values, with the appropriate storage class as a
233// prefix.
Nate Begemane59bf592004-08-14 22:09:10 +0000234void PowerPCAsmPrinter::emitGlobalConstant(const Constant *CV) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000235 const TargetData &TD = TM.getTargetData();
236
Misha Brukmane48178e2004-07-20 15:45:27 +0000237 if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000238 if (isStringCompatible(CVA)) {
Misha Brukman218bec72004-06-29 17:13:26 +0000239 O << "\t.ascii ";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000240 printAsCString(O, CVA);
241 O << "\n";
242 } else { // Not a string. Print the values in successive locations
Chris Lattner6173cd92004-08-04 17:29:14 +0000243 for (unsigned i=0, e = CVA->getNumOperands(); i != e; i++)
244 emitGlobalConstant(CVA->getOperand(i));
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000245 }
246 return;
247 } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
248 // Print the fields in successive locations. Pad to align if needed!
249 const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000250 unsigned sizeSoFar = 0;
Chris Lattner6173cd92004-08-04 17:29:14 +0000251 for (unsigned i = 0, e = CVS->getNumOperands(); i != e; i++) {
252 const Constant* field = CVS->getOperand(i);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000253
254 // Check if padding is needed and insert one or more 0s.
255 unsigned fieldSize = TD.getTypeSize(field->getType());
Chris Lattner6173cd92004-08-04 17:29:14 +0000256 unsigned padSize = ((i == e-1? cvsLayout->StructSize
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000257 : cvsLayout->MemberOffsets[i+1])
258 - cvsLayout->MemberOffsets[i]) - fieldSize;
259 sizeSoFar += fieldSize + padSize;
260
261 // Now print the actual field value
262 emitGlobalConstant(field);
263
264 // Insert the field padding unless it's zero bytes...
265 if (padSize)
266 O << "\t.space\t " << padSize << "\n";
267 }
268 assert(sizeSoFar == cvsLayout->StructSize &&
269 "Layout of constant struct may be incorrect!");
270 return;
271 } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
272 // FP Constants are printed as integer constants to avoid losing
273 // precision...
274 double Val = CFP->getValue();
Nate Begemane59bf592004-08-14 22:09:10 +0000275 union DU { // Abide by C TBAA rules
276 double FVal;
277 uint64_t UVal;
278 struct {
279 uint32_t MSWord;
280 uint32_t LSWord;
281 } T;
282 } U;
283 U.FVal = Val;
284
285 O << ".long\t" << U.T.MSWord << "\t; double most significant word "
286 << Val << "\n";
287 O << ".long\t" << U.T.LSWord << "\t; double least significant word "
288 << Val << "\n";
289 return;
Misha Brukmanf63bc192004-07-28 19:12:24 +0000290 } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
Misha Brukman2bf183c2004-06-25 15:42:10 +0000291 if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
292 union DU { // Abide by C TBAA rules
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000293 int64_t UVal;
294 struct {
Misha Brukman46fd00a2004-06-24 23:04:11 +0000295 uint32_t MSWord;
296 uint32_t LSWord;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000297 } T;
298 } U;
299 U.UVal = CI->getRawValue();
300
Misha Brukman218bec72004-06-29 17:13:26 +0000301 O << ".long\t" << U.T.MSWord << "\t; Double-word most significant word "
Misha Brukman46fd00a2004-06-24 23:04:11 +0000302 << U.UVal << "\n";
Misha Brukman29188c62004-07-16 19:01:13 +0000303 O << ".long\t" << U.T.LSWord << "\t; Double-word least significant word "
Misha Brukman46fd00a2004-06-24 23:04:11 +0000304 << U.UVal << "\n";
305 return;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000306 }
307 }
308
309 const Type *type = CV->getType();
310 O << "\t";
Misha Brukmand71bd562004-06-21 17:19:08 +0000311 switch (type->getTypeID()) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000312 case Type::UByteTyID: case Type::SByteTyID:
313 O << ".byte";
314 break;
315 case Type::UShortTyID: case Type::ShortTyID:
316 O << ".short";
317 break;
318 case Type::BoolTyID:
319 case Type::PointerTyID:
320 case Type::UIntTyID: case Type::IntTyID:
321 O << ".long";
322 break;
323 case Type::ULongTyID: case Type::LongTyID:
Misha Brukman46fd00a2004-06-24 23:04:11 +0000324 assert (0 && "Should have already output double-word constant.");
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000325 case Type::FloatTyID: case Type::DoubleTyID:
326 assert (0 && "Should have already output floating point constant.");
327 default:
Misha Brukman97a296f2004-07-21 20:11:11 +0000328 if (CV == Constant::getNullValue(type)) { // Zero initializer?
329 O << ".space\t" << TD.getTypeSize(type) << "\n";
330 return;
331 }
332 std::cerr << "Can't handle printing: " << *CV;
333 abort();
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000334 break;
335 }
336 O << "\t";
337 emitConstantValueOnly(CV);
338 O << "\n";
339}
340
341/// printConstantPool - Print to the current output stream assembly
342/// representations of the constants in the constant pool MCP. This is
343/// used to print out constants which have been "spilled to memory" by
344/// the code generator.
345///
Nate Begemane59bf592004-08-14 22:09:10 +0000346void PowerPCAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000347 const std::vector<Constant*> &CP = MCP->getConstants();
348 const TargetData &TD = TM.getTargetData();
349
350 if (CP.empty()) return;
351
352 for (unsigned i = 0, e = CP.size(); i != e; ++i) {
353 O << "\t.const\n";
354 O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType())
355 << "\n";
Misha Brukman218bec72004-06-29 17:13:26 +0000356 O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t;"
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000357 << *CP[i] << "\n";
358 emitGlobalConstant(CP[i]);
359 }
360}
361
362/// runOnMachineFunction - This uses the printMachineInstruction()
363/// method to print assembly for each instruction.
364///
Nate Begemane59bf592004-08-14 22:09:10 +0000365bool PowerPCAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000366 O << "\n\n";
367 // What's my mangled name?
368 CurrentFnName = Mang->getValueName(MF.getFunction());
369
370 // Print out constants referenced by the function
371 printConstantPool(MF.getConstantPool());
372
373 // Print out labels for the function.
374 O << "\t.text\n";
375 O << "\t.globl\t" << CurrentFnName << "\n";
Misha Brukman61297ee2004-06-29 23:40:57 +0000376 O << "\t.align 2\n";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000377 O << CurrentFnName << ":\n";
378
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000379 // Print out code for the function.
380 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
381 I != E; ++I) {
382 // Print a label for the basic block.
Misha Brukman218bec72004-06-29 17:13:26 +0000383 O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t; "
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000384 << I->getBasicBlock()->getName() << "\n";
385 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
Misha Brukman46fd00a2004-06-24 23:04:11 +0000386 II != E; ++II) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000387 // Print the assembly for the instruction.
388 O << "\t";
389 printMachineInstruction(II);
390 }
391 }
Misha Brukmancf8d2442004-07-26 16:28:33 +0000392 ++LabelNumber;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000393
394 // We didn't modify anything.
395 return false;
396}
397
Nate Begemane59bf592004-08-14 22:09:10 +0000398void PowerPCAsmPrinter::printOp(const MachineOperand &MO,
Nate Begemanb73a7112004-08-13 09:32:01 +0000399 bool LoadAddrOp /* = false */) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000400 const MRegisterInfo &RI = *TM.getRegisterInfo();
401 int new_symbol;
402
403 switch (MO.getType()) {
404 case MachineOperand::MO_VirtualRegister:
405 if (Value *V = MO.getVRegValueOrNull()) {
406 O << "<" << V->getName() << ">";
407 return;
408 }
409 // FALLTHROUGH
410 case MachineOperand::MO_MachineRegister:
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000411 case MachineOperand::MO_CCRegister:
Misha Brukman7f484a52004-06-24 23:51:00 +0000412 O << LowercaseString(RI.get(MO.getReg()).Name);
413 return;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000414
415 case MachineOperand::MO_SignExtendedImmed:
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000416 case MachineOperand::MO_UnextendedImmed:
417 std::cerr << "printOp() does not handle immediate values\n";
418 abort();
Misha Brukman97a296f2004-07-21 20:11:11 +0000419 return;
420
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000421 case MachineOperand::MO_PCRelativeDisp:
422 std::cerr << "Shouldn't use addPCDisp() when building PPC MachineInstrs";
423 abort();
424 return;
425
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000426 case MachineOperand::MO_MachineBasicBlock: {
427 MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
428 O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
Misha Brukman218bec72004-06-29 17:13:26 +0000429 << "_" << MBBOp->getNumber() << "\t; "
Misha Brukman2bf183c2004-06-25 15:42:10 +0000430 << MBBOp->getBasicBlock()->getName();
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000431 return;
432 }
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000433
434 case MachineOperand::MO_ConstantPoolIndex:
435 O << ".CPI" << CurrentFnName << "_" << MO.getConstantPoolIndex();
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000436 return;
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000437
438 case MachineOperand::MO_ExternalSymbol:
439 O << MO.getSymbolName();
440 return;
441
Nate Begemanb73a7112004-08-13 09:32:01 +0000442 case MachineOperand::MO_GlobalAddress: {
443 GlobalValue *GV = MO.getGlobal();
444 std::string Name = Mang->getValueName(GV);
Misha Brukmane2eceb52004-07-23 16:08:20 +0000445
Nate Begemanb73a7112004-08-13 09:32:01 +0000446 // Dynamically-resolved functions need a stub for the function. Be
447 // wary however not to output $stub for external functions whose addresses
448 // are taken. Those should be emitted as $non_lazy_ptr below.
449 Function *F = dyn_cast<Function>(GV);
450 if (F && F->isExternal() && !LoadAddrOp &&
451 TM.CalledFunctions.find(F) != TM.CalledFunctions.end()) {
452 FnStubs.insert(Name);
453 O << "L" << Name << "$stub";
454 return;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000455 }
Nate Begemane59bf592004-08-14 22:09:10 +0000456
Nate Begemanb73a7112004-08-13 09:32:01 +0000457 // External global variables need a non-lazily-resolved stub
Nate Begemane59bf592004-08-14 22:09:10 +0000458 if (GV->isExternal() && TM.AddressTaken.find(GV) != TM.AddressTaken.end()) {
Nate Begemanb73a7112004-08-13 09:32:01 +0000459 GVStubs.insert(Name);
460 O << "L" << Name << "$non_lazy_ptr";
461 return;
462 }
Nate Begemane59bf592004-08-14 22:09:10 +0000463
464 if (F && LoadAddrOp && TM.AddressTaken.find(GV) != TM.AddressTaken.end()) {
465 LinkOnceStubs.insert(Name);
466 O << "L" << Name << "$non_lazy_ptr";
467 return;
468 }
Nate Begemanb73a7112004-08-13 09:32:01 +0000469
470 O << Mang->getValueName(GV);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000471 return;
Nate Begemanb73a7112004-08-13 09:32:01 +0000472 }
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000473
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000474 default:
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000475 O << "<unknown operand type: " << MO.getType() << ">";
Misha Brukman22e12072004-06-25 15:11:34 +0000476 return;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000477 }
478}
479
Nate Begemane59bf592004-08-14 22:09:10 +0000480void PowerPCAsmPrinter::printImmOp(const MachineOperand &MO, unsigned ArgType) {
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000481 int Imm = MO.getImmedValue();
Misha Brukman5b570812004-08-10 22:47:03 +0000482 if (ArgType == PPCII::Simm16 || ArgType == PPCII::Disimm16) {
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000483 O << (short)Imm;
Misha Brukman5b570812004-08-10 22:47:03 +0000484 } else if (ArgType == PPCII::Zimm16) {
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000485 O << (unsigned short)Imm;
486 } else {
487 O << Imm;
488 }
489}
490
Nate Begemane59bf592004-08-14 22:09:10 +0000491/// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to
492/// the current output stream.
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000493///
Nate Begemane59bf592004-08-14 22:09:10 +0000494void PowerPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
495 ++EmittedInsts;
496 if (printInstruction(MI))
497 return; // Printer was automatically generated
498
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000499 unsigned Opcode = MI->getOpcode();
500 const TargetInstrInfo &TII = *TM.getInstrInfo();
501 const TargetInstrDescriptor &Desc = TII.get(Opcode);
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000502 unsigned i;
Misha Brukmanc6cc10f2004-06-25 19:24:52 +0000503
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000504 unsigned ArgCount = MI->getNumOperands();
505 unsigned ArgType[] = {
Misha Brukman5b570812004-08-10 22:47:03 +0000506 (Desc.TSFlags >> PPCII::Arg0TypeShift) & PPCII::ArgTypeMask,
507 (Desc.TSFlags >> PPCII::Arg1TypeShift) & PPCII::ArgTypeMask,
508 (Desc.TSFlags >> PPCII::Arg2TypeShift) & PPCII::ArgTypeMask,
509 (Desc.TSFlags >> PPCII::Arg3TypeShift) & PPCII::ArgTypeMask,
510 (Desc.TSFlags >> PPCII::Arg4TypeShift) & PPCII::ArgTypeMask
Misha Brukman22e12072004-06-25 15:11:34 +0000511 };
Misha Brukman5b570812004-08-10 22:47:03 +0000512 assert(((Desc.TSFlags & PPCII::VMX) == 0) &&
Misha Brukman46fd00a2004-06-24 23:04:11 +0000513 "Instruction requires VMX support");
Misha Brukman5b570812004-08-10 22:47:03 +0000514 assert(((Desc.TSFlags & PPCII::PPC64) == 0) &&
Misha Brukman46fd00a2004-06-24 23:04:11 +0000515 "Instruction requires 64 bit support");
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000516
Misha Brukman61114612004-07-20 00:42:19 +0000517 // CALLpcrel and CALLindirect are handled specially here to print only the
518 // appropriate number of args that the assembler expects. This is because
519 // may have many arguments appended to record the uses of registers that are
520 // holding arguments to the called function.
Misha Brukman5b570812004-08-10 22:47:03 +0000521 if (Opcode == PPC::COND_BRANCH) {
Misha Brukmanab967902004-07-27 18:40:39 +0000522 std::cerr << "Error: untranslated conditional branch psuedo instruction!\n";
523 abort();
Misha Brukman5b570812004-08-10 22:47:03 +0000524 } else if (Opcode == PPC::IMPLICIT_DEF) {
Misha Brukman29188c62004-07-16 19:01:13 +0000525 O << "; IMPLICIT DEF ";
526 printOp(MI->getOperand(0));
527 O << "\n";
528 return;
Misha Brukman5b570812004-08-10 22:47:03 +0000529 } else if (Opcode == PPC::CALLpcrel) {
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000530 O << TII.getName(Opcode) << " ";
Misha Brukman61114612004-07-20 00:42:19 +0000531 printOp(MI->getOperand(0));
532 O << "\n";
533 return;
Misha Brukman5b570812004-08-10 22:47:03 +0000534 } else if (Opcode == PPC::CALLindirect) {
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000535 O << TII.getName(Opcode) << " ";
536 printImmOp(MI->getOperand(0), ArgType[0]);
Misha Brukman61114612004-07-20 00:42:19 +0000537 O << ", ";
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000538 printImmOp(MI->getOperand(1), ArgType[0]);
Misha Brukman61114612004-07-20 00:42:19 +0000539 O << "\n";
540 return;
Misha Brukman5b570812004-08-10 22:47:03 +0000541 } else if (Opcode == PPC::MovePCtoLR) {
Misha Brukman61114612004-07-20 00:42:19 +0000542 // FIXME: should probably be converted to cout.width and cout.fill
Misha Brukmancf8d2442004-07-26 16:28:33 +0000543 O << "bl \"L0000" << LabelNumber << "$pb\"\n";
544 O << "\"L0000" << LabelNumber << "$pb\":\n";
Misha Brukman218bec72004-06-29 17:13:26 +0000545 O << "\tmflr ";
546 printOp(MI->getOperand(0));
Misha Brukman218bec72004-06-29 17:13:26 +0000547 O << "\n";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000548 return;
549 }
550
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000551 O << TII.getName(Opcode) << " ";
Misha Brukman5b570812004-08-10 22:47:03 +0000552 if (Opcode == PPC::LOADLoDirect || Opcode == PPC::LOADLoIndirect) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000553 printOp(MI->getOperand(0));
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000554 O << ", lo16(";
Nate Begemanb73a7112004-08-13 09:32:01 +0000555 printOp(MI->getOperand(2), true /* LoadAddrOp */);
Misha Brukmancf8d2442004-07-26 16:28:33 +0000556 O << "-\"L0000" << LabelNumber << "$pb\")";
Misha Brukman218bec72004-06-29 17:13:26 +0000557 O << "(";
Misha Brukman5b570812004-08-10 22:47:03 +0000558 if (MI->getOperand(1).getReg() == PPC::R0)
Misha Brukman218bec72004-06-29 17:13:26 +0000559 O << "0";
560 else
561 printOp(MI->getOperand(1));
562 O << ")\n";
Misha Brukman5b570812004-08-10 22:47:03 +0000563 } else if (Opcode == PPC::LOADHiAddr) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000564 printOp(MI->getOperand(0));
565 O << ", ";
Misha Brukman5b570812004-08-10 22:47:03 +0000566 if (MI->getOperand(1).getReg() == PPC::R0)
Misha Brukman218bec72004-06-29 17:13:26 +0000567 O << "0";
568 else
569 printOp(MI->getOperand(1));
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000570 O << ", ha16(" ;
Nate Begemanb73a7112004-08-13 09:32:01 +0000571 printOp(MI->getOperand(2), true /* LoadAddrOp */);
Misha Brukmancf8d2442004-07-26 16:28:33 +0000572 O << "-\"L0000" << LabelNumber << "$pb\")\n";
Misha Brukman5b570812004-08-10 22:47:03 +0000573 } else if (ArgCount == 3 && ArgType[1] == PPCII::Disimm16) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000574 printOp(MI->getOperand(0));
575 O << ", ";
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000576 printImmOp(MI->getOperand(1), ArgType[1]);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000577 O << "(";
Misha Brukmanb9e8f972004-06-30 21:54:12 +0000578 if (MI->getOperand(2).hasAllocatedReg() &&
Misha Brukman5b570812004-08-10 22:47:03 +0000579 MI->getOperand(2).getReg() == PPC::R0)
Misha Brukman46fd00a2004-06-24 23:04:11 +0000580 O << "0";
581 else
582 printOp(MI->getOperand(2));
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000583 O << ")\n";
584 } else {
Misha Brukman7f484a52004-06-24 23:51:00 +0000585 for (i = 0; i < ArgCount; ++i) {
Misha Brukmanab967902004-07-27 18:40:39 +0000586 // addi and friends
Misha Brukman5b570812004-08-10 22:47:03 +0000587 if (i == 1 && ArgCount == 3 && ArgType[2] == PPCII::Simm16 &&
Misha Brukman4363bdb2004-07-01 21:09:12 +0000588 MI->getOperand(1).hasAllocatedReg() &&
Misha Brukman5b570812004-08-10 22:47:03 +0000589 MI->getOperand(1).getReg() == PPC::R0) {
Misha Brukman46fd00a2004-06-24 23:04:11 +0000590 O << "0";
Misha Brukmanab967902004-07-27 18:40:39 +0000591 // for long branch support, bc $+8
592 } else if (i == 1 && ArgCount == 2 && MI->getOperand(1).isImmediate() &&
593 TII.isBranch(MI->getOpcode())) {
594 O << "$+8";
595 assert(8 == MI->getOperand(i).getImmedValue()
596 && "branch off PC not to pc+8?");
597 //printOp(MI->getOperand(i));
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000598 } else if (MI->getOperand(i).isImmediate()) {
599 printImmOp(MI->getOperand(i), ArgType[i]);
Misha Brukman218bec72004-06-29 17:13:26 +0000600 } else {
Misha Brukman46fd00a2004-06-24 23:04:11 +0000601 printOp(MI->getOperand(i));
602 }
Misha Brukman7f484a52004-06-24 23:51:00 +0000603 if (ArgCount - 1 == i)
Misha Brukman46fd00a2004-06-24 23:04:11 +0000604 O << "\n";
605 else
606 O << ", ";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000607 }
608 }
Nate Begemane59bf592004-08-14 22:09:10 +0000609 return;
610
611 // Call the autogenerated instruction printer routines.
612 bool Handled = printInstruction(MI);
613 if (!Handled) {
614 MI->dump();
615 assert(0 && "Do not know how to print this instruction!");
616 abort();
617 }
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000618}
619
Nate Begemane59bf592004-08-14 22:09:10 +0000620bool PowerPCAsmPrinter::doInitialization(Module &M) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000621 Mang = new Mangler(M, true);
622 return false; // success
623}
624
625// SwitchSection - Switch to the specified section of the executable if we are
626// not already in it!
627//
628static void SwitchSection(std::ostream &OS, std::string &CurSection,
629 const char *NewSection) {
630 if (CurSection != NewSection) {
631 CurSection = NewSection;
632 if (!CurSection.empty())
633 OS << "\t" << NewSection << "\n";
634 }
635}
636
Nate Begemane59bf592004-08-14 22:09:10 +0000637bool PowerPCAsmPrinter::doFinalization(Module &M) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000638 const TargetData &TD = TM.getTargetData();
639 std::string CurSection;
640
641 // Print out module-level global variables here.
642 for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
643 if (I->hasInitializer()) { // External global require no code
644 O << "\n\n";
645 std::string name = Mang->getValueName(I);
646 Constant *C = I->getInitializer();
647 unsigned Size = TD.getTypeSize(C->getType());
648 unsigned Align = TD.getTypeAlignment(C->getType());
649
Misha Brukman97a296f2004-07-21 20:11:11 +0000650 if (C->isNullValue() && /* FIXME: Verify correct */
651 (I->hasInternalLinkage() || I->hasWeakLinkage())) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000652 SwitchSection(O, CurSection, ".data");
653 if (I->hasInternalLinkage())
Misha Brukmane2eceb52004-07-23 16:08:20 +0000654 O << ".lcomm " << name << "," << TD.getTypeSize(C->getType())
Misha Brukman218bec72004-06-29 17:13:26 +0000655 << "," << (unsigned)TD.getTypeAlignment(C->getType());
656 else
Misha Brukmane2eceb52004-07-23 16:08:20 +0000657 O << ".comm " << name << "," << TD.getTypeSize(C->getType());
Misha Brukman218bec72004-06-29 17:13:26 +0000658 O << "\t\t; ";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000659 WriteAsOperand(O, I, true, true, &M);
660 O << "\n";
661 } else {
662 switch (I->getLinkage()) {
663 case GlobalValue::LinkOnceLinkage:
Misha Brukman97a296f2004-07-21 20:11:11 +0000664 O << ".section __TEXT,__textcoal_nt,coalesced,no_toc\n"
665 << ".weak_definition " << name << '\n'
666 << ".private_extern " << name << '\n'
667 << ".section __DATA,__datacoal_nt,coalesced,no_toc\n";
668 LinkOnceStubs.insert(name);
669 break;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000670 case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
671 // Nonnull linkonce -> weak
672 O << "\t.weak " << name << "\n";
673 SwitchSection(O, CurSection, "");
674 O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
675 break;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000676 case GlobalValue::AppendingLinkage:
677 // FIXME: appending linkage variables should go into a section of
678 // their name or something. For now, just emit them as external.
679 case GlobalValue::ExternalLinkage:
680 // If external or appending, declare as a global symbol
681 O << "\t.globl " << name << "\n";
682 // FALL THROUGH
683 case GlobalValue::InternalLinkage:
Misha Brukman61297ee2004-06-29 23:40:57 +0000684 SwitchSection(O, CurSection, ".data");
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000685 break;
686 }
687
688 O << "\t.align " << Align << "\n";
Misha Brukman218bec72004-06-29 17:13:26 +0000689 O << name << ":\t\t\t\t; ";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000690 WriteAsOperand(O, I, true, true, &M);
691 O << " = ";
692 WriteAsOperand(O, C, false, false, &M);
693 O << "\n";
694 emitGlobalConstant(C);
695 }
696 }
Misha Brukmanda2b13f2004-07-16 20:29:04 +0000697
698 // Output stubs for dynamically-linked functions
699 for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
700 i != e; ++i)
Misha Brukman46fd00a2004-06-24 23:04:11 +0000701 {
Misha Brukmane2eceb52004-07-23 16:08:20 +0000702 O << ".data\n";
703 O << ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n";
704 O << "\t.align 2\n";
Misha Brukman46fd00a2004-06-24 23:04:11 +0000705 O << "L" << *i << "$stub:\n";
706 O << "\t.indirect_symbol " << *i << "\n";
707 O << "\tmflr r0\n";
Misha Brukmane2eceb52004-07-23 16:08:20 +0000708 O << "\tbcl 20,31,L0$" << *i << "\n";
Misha Brukman46fd00a2004-06-24 23:04:11 +0000709 O << "L0$" << *i << ":\n";
710 O << "\tmflr r11\n";
711 O << "\taddis r11,r11,ha16(L" << *i << "$lazy_ptr-L0$" << *i << ")\n";
712 O << "\tmtlr r0\n";
Misha Brukmane2eceb52004-07-23 16:08:20 +0000713 O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n";
Misha Brukman46fd00a2004-06-24 23:04:11 +0000714 O << "\tmtctr r12\n";
715 O << "\tbctr\n";
716 O << ".data\n";
717 O << ".lazy_symbol_pointer\n";
718 O << "L" << *i << "$lazy_ptr:\n";
Misha Brukmane2eceb52004-07-23 16:08:20 +0000719 O << "\t.indirect_symbol " << *i << "\n";
720 O << "\t.long dyld_stub_binding_helper\n";
Misha Brukman46fd00a2004-06-24 23:04:11 +0000721 }
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000722
Misha Brukmanda2b13f2004-07-16 20:29:04 +0000723 O << "\n";
724
725 // Output stubs for external global variables
726 if (GVStubs.begin() != GVStubs.end())
Misha Brukmane2eceb52004-07-23 16:08:20 +0000727 O << ".data\n.non_lazy_symbol_pointer\n";
Misha Brukmanda2b13f2004-07-16 20:29:04 +0000728 for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
729 i != e; ++i) {
730 O << "L" << *i << "$non_lazy_ptr:\n";
731 O << "\t.indirect_symbol " << *i << "\n";
732 O << "\t.long\t0\n";
733 }
734
Nate Begemane59bf592004-08-14 22:09:10 +0000735 // Output stubs for link-once variables
736 if (LinkOnceStubs.begin() != LinkOnceStubs.end())
737 O << ".data\n.align 2\n";
738 for (std::set<std::string>::iterator i = LinkOnceStubs.begin(),
739 e = LinkOnceStubs.end(); i != e; ++i) {
740 O << "L" << *i << "$non_lazy_ptr:\n"
741 << "\t.long\t" << *i << '\n';
742 }
743
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000744 delete Mang;
745 return false; // success
746}
747
748} // End llvm namespace