blob: 42030ff141008d8a978d880bfd4d506facc8ce9b [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"
Chris Lattnera3840792004-08-16 23:25:21 +000027#include "llvm/CodeGen/AsmPrinter.h"
Misha Brukman5dfe3a92004-06-21 16:55:25 +000028#include "llvm/CodeGen/MachineConstantPool.h"
Misha Brukman05794492004-06-24 17:31:42 +000029#include "llvm/CodeGen/MachineFunctionPass.h"
Misha Brukman5dfe3a92004-06-21 16:55:25 +000030#include "llvm/CodeGen/MachineInstr.h"
Chris Lattner7bb424f2004-08-14 23:27:29 +000031#include "llvm/CodeGen/ValueTypes.h"
Misha Brukman5dfe3a92004-06-21 16:55:25 +000032#include "llvm/Target/TargetMachine.h"
33#include "llvm/Support/Mangler.h"
Misha Brukman05794492004-06-24 17:31:42 +000034#include "Support/CommandLine.h"
35#include "Support/Debug.h"
Misha Brukman5dfe3a92004-06-21 16:55:25 +000036#include "Support/Statistic.h"
37#include "Support/StringExtras.h"
Misha Brukman05794492004-06-24 17:31:42 +000038#include <set>
Chris Lattnera3840792004-08-16 23:25:21 +000039using namespace llvm;
Misha Brukman5dfe3a92004-06-21 16:55:25 +000040
41namespace {
42 Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
43
Chris Lattnera3840792004-08-16 23:25:21 +000044 struct PowerPCAsmPrinter : public AsmPrinter {
Misha Brukman97a296f2004-07-21 20:11:11 +000045 std::set<std::string> FnStubs, GVStubs, LinkOnceStubs;
Misha Brukman5dfe3a92004-06-21 16:55:25 +000046 std::set<std::string> Strings;
47
Chris Lattnera3840792004-08-16 23:25:21 +000048 PowerPCAsmPrinter(std::ostream &O, TargetMachine &TM)
Chris Lattner505e7832004-08-17 02:29:00 +000049 : AsmPrinter(O, TM), LabelNumber(0) {
50 UsesUnderscorePrefix = 1;
51 }
Misha Brukman5dfe3a92004-06-21 16:55:25 +000052
Misha Brukmancf8d2442004-07-26 16:28:33 +000053 /// Unique incrementer for label values for referencing Global values.
Misha Brukman218bec72004-06-29 17:13:26 +000054 ///
Misha Brukmancf8d2442004-07-26 16:28:33 +000055 unsigned LabelNumber;
56
Misha Brukman5dfe3a92004-06-21 16:55:25 +000057 virtual const char *getPassName() const {
Nate Begemane59bf592004-08-14 22:09:10 +000058 return "PowerPC Assembly Printer";
Misha Brukman5dfe3a92004-06-21 16:55:25 +000059 }
60
Chris Lattnera3840792004-08-16 23:25:21 +000061 PowerPCTargetMachine &getTM() {
62 return static_cast<PowerPCTargetMachine&>(TM);
63 }
64
Nate Begemane59bf592004-08-14 22:09:10 +000065 /// printInstruction - This method is automatically generated by tablegen
66 /// from the instruction set description. This method returns true if the
67 /// machine instruction was sufficiently described to print it, otherwise it
68 /// returns false.
69 bool printInstruction(const MachineInstr *MI);
70
Misha Brukman5dfe3a92004-06-21 16:55:25 +000071 void printMachineInstruction(const MachineInstr *MI);
Nate Begemanb73a7112004-08-13 09:32:01 +000072 void printOp(const MachineOperand &MO, bool LoadAddrOp = false);
Misha Brukmanaf313fb2004-07-28 00:00:48 +000073 void printImmOp(const MachineOperand &MO, unsigned ArgType);
Chris Lattner7bb424f2004-08-14 23:27:29 +000074
75 void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){
76 const MachineOperand &MO = MI->getOperand(OpNo);
77 if (MO.getType() == MachineOperand::MO_MachineRegister) {
78 assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
79 O << LowercaseString(TM.getRegisterInfo()->get(MO.getReg()).Name);
Chris Lattner0ea31712004-08-15 05:46:14 +000080 } else if (MO.isImmediate()) {
81 O << MO.getImmedValue();
Chris Lattner7bb424f2004-08-14 23:27:29 +000082 } else {
83 printOp(MO);
84 }
85 }
86
Chris Lattner97b2a2e2004-08-15 05:20:16 +000087 void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo,
88 MVT::ValueType VT) {
89 O << (unsigned short)MI->getOperand(OpNo).getImmedValue();
90 }
91
Misha Brukman5dfe3a92004-06-21 16:55:25 +000092 void printConstantPool(MachineConstantPool *MCP);
93 bool runOnMachineFunction(MachineFunction &F);
Misha Brukman5dfe3a92004-06-21 16:55:25 +000094 bool doFinalization(Module &M);
95 void emitGlobalConstant(const Constant* CV);
Misha Brukman5dfe3a92004-06-21 16:55:25 +000096 };
97} // end of anonymous namespace
98
Misha Brukman3d9a6c22004-08-11 00:09:42 +000099/// createPPC32AsmPrinterPass - Returns a pass that prints the PPC
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000100/// assembly code for a MachineFunction to the given output stream,
101/// using the given target machine description. This should work
Misha Brukman7103fba2004-08-09 22:27:45 +0000102/// regardless of whether the function is in SSA form or not.
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000103///
Chris Lattnera3840792004-08-16 23:25:21 +0000104FunctionPass *llvm::createPPCAsmPrinter(std::ostream &o,TargetMachine &tm) {
Nate Begemane59bf592004-08-14 22:09:10 +0000105 return new PowerPCAsmPrinter(o, tm);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000106}
107
Nate Begemane59bf592004-08-14 22:09:10 +0000108// Include the auto-generated portion of the assembly writer
109#include "PowerPCGenAsmWriter.inc"
110
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000111/// toOctal - Convert the low order bits of X into an octal digit.
112///
113static inline char toOctal(int X) {
114 return (X&7)+'0';
115}
116
117/// getAsCString - Return the specified array as a C compatible
Chris Lattner36aacdb2004-08-16 23:30:16 +0000118/// string, only if the predicate isString is true.
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000119///
120static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
Chris Lattner36aacdb2004-08-16 23:30:16 +0000121 assert(CVA->isString() && "Array is not string compatible!");
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000122
123 O << "\"";
Chris Lattner36aacdb2004-08-16 23:30:16 +0000124 for (unsigned i = 0; i != CVA->getNumOperands(); ++i) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000125 unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
126
127 if (C == '"') {
128 O << "\\\"";
129 } else if (C == '\\') {
130 O << "\\\\";
131 } else if (isprint(C)) {
132 O << C;
133 } else {
Chris Lattner36aacdb2004-08-16 23:30:16 +0000134 switch(C) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000135 case '\b': O << "\\b"; break;
136 case '\f': O << "\\f"; break;
137 case '\n': O << "\\n"; break;
138 case '\r': O << "\\r"; break;
139 case '\t': O << "\\t"; break;
140 default:
141 O << '\\';
142 O << toOctal(C >> 6);
143 O << toOctal(C >> 3);
144 O << toOctal(C >> 0);
145 break;
146 }
147 }
148 }
149 O << "\"";
150}
151
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000152// Print a constant value or values, with the appropriate storage class as a
153// prefix.
Nate Begemane59bf592004-08-14 22:09:10 +0000154void PowerPCAsmPrinter::emitGlobalConstant(const Constant *CV) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000155 const TargetData &TD = TM.getTargetData();
156
Chris Lattner416ca332004-08-16 23:38:36 +0000157 if (CV->isNullValue()) {
158 O << "\t.space\t" << TD.getTypeSize(CV->getType()) << "\n";
159 return;
160 } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
161 if (CVA->isString()) {
162 O << "\t.ascii\t";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000163 printAsCString(O, CVA);
164 O << "\n";
165 } else { // Not a string. Print the values in successive locations
Chris Lattner416ca332004-08-16 23:38:36 +0000166 for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
Chris Lattner6173cd92004-08-04 17:29:14 +0000167 emitGlobalConstant(CVA->getOperand(i));
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000168 }
169 return;
170 } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
171 // Print the fields in successive locations. Pad to align if needed!
172 const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000173 unsigned sizeSoFar = 0;
Chris Lattner416ca332004-08-16 23:38:36 +0000174 for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
Chris Lattner6173cd92004-08-04 17:29:14 +0000175 const Constant* field = CVS->getOperand(i);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000176
177 // Check if padding is needed and insert one or more 0s.
178 unsigned fieldSize = TD.getTypeSize(field->getType());
Chris Lattner6173cd92004-08-04 17:29:14 +0000179 unsigned padSize = ((i == e-1? cvsLayout->StructSize
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000180 : cvsLayout->MemberOffsets[i+1])
181 - cvsLayout->MemberOffsets[i]) - fieldSize;
182 sizeSoFar += fieldSize + padSize;
183
184 // Now print the actual field value
185 emitGlobalConstant(field);
186
187 // Insert the field padding unless it's zero bytes...
188 if (padSize)
189 O << "\t.space\t " << padSize << "\n";
190 }
191 assert(sizeSoFar == cvsLayout->StructSize &&
192 "Layout of constant struct may be incorrect!");
193 return;
194 } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
195 // FP Constants are printed as integer constants to avoid losing
196 // precision...
197 double Val = CFP->getValue();
Chris Lattner505e7832004-08-17 02:29:00 +0000198 if (1 || CFP->getType() == Type::DoubleTy) {
199 union DU { // Abide by C TBAA rules
200 double FVal;
201 uint64_t UVal;
202 struct {
203 uint32_t MSWord;
204 uint32_t LSWord;
205 } T;
206 } U;
207 U.FVal = Val;
208
209 O << ".long\t" << U.T.MSWord << "\t; double most significant word "
210 << Val << "\n";
211 O << ".long\t" << U.T.LSWord << "\t; double least significant word "
212 << Val << "\n";
213 return;
214 } else {
215 union FU { // Abide by C TBAA rules
216 float FVal;
217 int32_t UVal;
218 } U;
219 U.FVal = Val;
220
221 O << ".long\t" << U.UVal << "\t; float " << Val << "\n";
222 return;
223 }
Misha Brukmanf63bc192004-07-28 19:12:24 +0000224 } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
Misha Brukman2bf183c2004-06-25 15:42:10 +0000225 if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
226 union DU { // Abide by C TBAA rules
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000227 int64_t UVal;
228 struct {
Misha Brukman46fd00a2004-06-24 23:04:11 +0000229 uint32_t MSWord;
230 uint32_t LSWord;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000231 } T;
232 } U;
233 U.UVal = CI->getRawValue();
234
Misha Brukman218bec72004-06-29 17:13:26 +0000235 O << ".long\t" << U.T.MSWord << "\t; Double-word most significant word "
Misha Brukman46fd00a2004-06-24 23:04:11 +0000236 << U.UVal << "\n";
Misha Brukman29188c62004-07-16 19:01:13 +0000237 O << ".long\t" << U.T.LSWord << "\t; Double-word least significant word "
Misha Brukman46fd00a2004-06-24 23:04:11 +0000238 << U.UVal << "\n";
239 return;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000240 }
241 }
242
243 const Type *type = CV->getType();
244 O << "\t";
Misha Brukmand71bd562004-06-21 17:19:08 +0000245 switch (type->getTypeID()) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000246 case Type::UByteTyID: case Type::SByteTyID:
247 O << ".byte";
248 break;
249 case Type::UShortTyID: case Type::ShortTyID:
250 O << ".short";
251 break;
252 case Type::BoolTyID:
253 case Type::PointerTyID:
254 case Type::UIntTyID: case Type::IntTyID:
255 O << ".long";
256 break;
257 case Type::ULongTyID: case Type::LongTyID:
Misha Brukman46fd00a2004-06-24 23:04:11 +0000258 assert (0 && "Should have already output double-word constant.");
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000259 case Type::FloatTyID: case Type::DoubleTyID:
260 assert (0 && "Should have already output floating point constant.");
261 default:
Chris Lattner416ca332004-08-16 23:38:36 +0000262 assert (0 && "Can't handle printing this type of thing");
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000263 break;
264 }
265 O << "\t";
266 emitConstantValueOnly(CV);
267 O << "\n";
268}
269
270/// printConstantPool - Print to the current output stream assembly
271/// representations of the constants in the constant pool MCP. This is
272/// used to print out constants which have been "spilled to memory" by
273/// the code generator.
274///
Nate Begemane59bf592004-08-14 22:09:10 +0000275void PowerPCAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000276 const std::vector<Constant*> &CP = MCP->getConstants();
277 const TargetData &TD = TM.getTargetData();
278
279 if (CP.empty()) return;
280
281 for (unsigned i = 0, e = CP.size(); i != e; ++i) {
282 O << "\t.const\n";
283 O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType())
284 << "\n";
Misha Brukman218bec72004-06-29 17:13:26 +0000285 O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t;"
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000286 << *CP[i] << "\n";
287 emitGlobalConstant(CP[i]);
288 }
289}
290
291/// runOnMachineFunction - This uses the printMachineInstruction()
292/// method to print assembly for each instruction.
293///
Nate Begemane59bf592004-08-14 22:09:10 +0000294bool PowerPCAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
Chris Lattnera3840792004-08-16 23:25:21 +0000295 setupMachineFunction(MF);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000296 O << "\n\n";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000297
298 // Print out constants referenced by the function
299 printConstantPool(MF.getConstantPool());
300
301 // Print out labels for the function.
302 O << "\t.text\n";
303 O << "\t.globl\t" << CurrentFnName << "\n";
Misha Brukman61297ee2004-06-29 23:40:57 +0000304 O << "\t.align 2\n";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000305 O << CurrentFnName << ":\n";
306
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000307 // Print out code for the function.
308 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
309 I != E; ++I) {
310 // Print a label for the basic block.
Misha Brukman218bec72004-06-29 17:13:26 +0000311 O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t; "
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000312 << I->getBasicBlock()->getName() << "\n";
313 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
Misha Brukman46fd00a2004-06-24 23:04:11 +0000314 II != E; ++II) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000315 // Print the assembly for the instruction.
316 O << "\t";
317 printMachineInstruction(II);
318 }
319 }
Misha Brukmancf8d2442004-07-26 16:28:33 +0000320 ++LabelNumber;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000321
322 // We didn't modify anything.
323 return false;
324}
325
Nate Begemane59bf592004-08-14 22:09:10 +0000326void PowerPCAsmPrinter::printOp(const MachineOperand &MO,
Nate Begemanb73a7112004-08-13 09:32:01 +0000327 bool LoadAddrOp /* = false */) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000328 const MRegisterInfo &RI = *TM.getRegisterInfo();
329 int new_symbol;
330
331 switch (MO.getType()) {
332 case MachineOperand::MO_VirtualRegister:
333 if (Value *V = MO.getVRegValueOrNull()) {
334 O << "<" << V->getName() << ">";
335 return;
336 }
337 // FALLTHROUGH
338 case MachineOperand::MO_MachineRegister:
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000339 case MachineOperand::MO_CCRegister:
Misha Brukman7f484a52004-06-24 23:51:00 +0000340 O << LowercaseString(RI.get(MO.getReg()).Name);
341 return;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000342
343 case MachineOperand::MO_SignExtendedImmed:
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000344 case MachineOperand::MO_UnextendedImmed:
345 std::cerr << "printOp() does not handle immediate values\n";
346 abort();
Misha Brukman97a296f2004-07-21 20:11:11 +0000347 return;
348
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000349 case MachineOperand::MO_PCRelativeDisp:
350 std::cerr << "Shouldn't use addPCDisp() when building PPC MachineInstrs";
351 abort();
352 return;
353
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000354 case MachineOperand::MO_MachineBasicBlock: {
355 MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
356 O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
Misha Brukman218bec72004-06-29 17:13:26 +0000357 << "_" << MBBOp->getNumber() << "\t; "
Misha Brukman2bf183c2004-06-25 15:42:10 +0000358 << MBBOp->getBasicBlock()->getName();
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000359 return;
360 }
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000361
362 case MachineOperand::MO_ConstantPoolIndex:
363 O << ".CPI" << CurrentFnName << "_" << MO.getConstantPoolIndex();
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000364 return;
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000365
366 case MachineOperand::MO_ExternalSymbol:
367 O << MO.getSymbolName();
368 return;
369
Nate Begemanb73a7112004-08-13 09:32:01 +0000370 case MachineOperand::MO_GlobalAddress: {
371 GlobalValue *GV = MO.getGlobal();
372 std::string Name = Mang->getValueName(GV);
Misha Brukmane2eceb52004-07-23 16:08:20 +0000373
Nate Begemanb73a7112004-08-13 09:32:01 +0000374 // Dynamically-resolved functions need a stub for the function. Be
375 // wary however not to output $stub for external functions whose addresses
376 // are taken. Those should be emitted as $non_lazy_ptr below.
377 Function *F = dyn_cast<Function>(GV);
378 if (F && F->isExternal() && !LoadAddrOp &&
Chris Lattnera3840792004-08-16 23:25:21 +0000379 getTM().CalledFunctions.count(F)) {
Nate Begemanb73a7112004-08-13 09:32:01 +0000380 FnStubs.insert(Name);
381 O << "L" << Name << "$stub";
382 return;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000383 }
Nate Begemane59bf592004-08-14 22:09:10 +0000384
Nate Begemanb73a7112004-08-13 09:32:01 +0000385 // External global variables need a non-lazily-resolved stub
Chris Lattnera3840792004-08-16 23:25:21 +0000386 if (GV->isExternal() && getTM().AddressTaken.count(GV)) {
Nate Begemanb73a7112004-08-13 09:32:01 +0000387 GVStubs.insert(Name);
388 O << "L" << Name << "$non_lazy_ptr";
389 return;
390 }
Nate Begemane59bf592004-08-14 22:09:10 +0000391
Chris Lattnera3840792004-08-16 23:25:21 +0000392 if (F && LoadAddrOp && getTM().AddressTaken.count(GV)) {
Nate Begemane59bf592004-08-14 22:09:10 +0000393 LinkOnceStubs.insert(Name);
394 O << "L" << Name << "$non_lazy_ptr";
395 return;
396 }
Nate Begemanb73a7112004-08-13 09:32:01 +0000397
398 O << Mang->getValueName(GV);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000399 return;
Nate Begemanb73a7112004-08-13 09:32:01 +0000400 }
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000401
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000402 default:
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000403 O << "<unknown operand type: " << MO.getType() << ">";
Misha Brukman22e12072004-06-25 15:11:34 +0000404 return;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000405 }
406}
407
Nate Begemane59bf592004-08-14 22:09:10 +0000408void PowerPCAsmPrinter::printImmOp(const MachineOperand &MO, unsigned ArgType) {
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000409 int Imm = MO.getImmedValue();
Misha Brukman5b570812004-08-10 22:47:03 +0000410 if (ArgType == PPCII::Simm16 || ArgType == PPCII::Disimm16) {
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000411 O << (short)Imm;
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000412 } else {
413 O << Imm;
414 }
415}
416
Nate Begemane59bf592004-08-14 22:09:10 +0000417/// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to
418/// the current output stream.
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000419///
Nate Begemane59bf592004-08-14 22:09:10 +0000420void PowerPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
421 ++EmittedInsts;
422 if (printInstruction(MI))
423 return; // Printer was automatically generated
424
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000425 unsigned Opcode = MI->getOpcode();
426 const TargetInstrInfo &TII = *TM.getInstrInfo();
427 const TargetInstrDescriptor &Desc = TII.get(Opcode);
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000428 unsigned i;
Misha Brukmanc6cc10f2004-06-25 19:24:52 +0000429
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000430 unsigned ArgCount = MI->getNumOperands();
431 unsigned ArgType[] = {
Misha Brukman5b570812004-08-10 22:47:03 +0000432 (Desc.TSFlags >> PPCII::Arg0TypeShift) & PPCII::ArgTypeMask,
433 (Desc.TSFlags >> PPCII::Arg1TypeShift) & PPCII::ArgTypeMask,
434 (Desc.TSFlags >> PPCII::Arg2TypeShift) & PPCII::ArgTypeMask,
435 (Desc.TSFlags >> PPCII::Arg3TypeShift) & PPCII::ArgTypeMask,
436 (Desc.TSFlags >> PPCII::Arg4TypeShift) & PPCII::ArgTypeMask
Misha Brukman22e12072004-06-25 15:11:34 +0000437 };
Misha Brukman5b570812004-08-10 22:47:03 +0000438 assert(((Desc.TSFlags & PPCII::VMX) == 0) &&
Misha Brukman46fd00a2004-06-24 23:04:11 +0000439 "Instruction requires VMX support");
Misha Brukman5b570812004-08-10 22:47:03 +0000440 assert(((Desc.TSFlags & PPCII::PPC64) == 0) &&
Misha Brukman46fd00a2004-06-24 23:04:11 +0000441 "Instruction requires 64 bit support");
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000442
Misha Brukman61114612004-07-20 00:42:19 +0000443 // CALLpcrel and CALLindirect are handled specially here to print only the
444 // appropriate number of args that the assembler expects. This is because
445 // may have many arguments appended to record the uses of registers that are
446 // holding arguments to the called function.
Misha Brukman5b570812004-08-10 22:47:03 +0000447 if (Opcode == PPC::COND_BRANCH) {
Misha Brukmanab967902004-07-27 18:40:39 +0000448 std::cerr << "Error: untranslated conditional branch psuedo instruction!\n";
449 abort();
Misha Brukman5b570812004-08-10 22:47:03 +0000450 } else if (Opcode == PPC::IMPLICIT_DEF) {
Misha Brukman29188c62004-07-16 19:01:13 +0000451 O << "; IMPLICIT DEF ";
452 printOp(MI->getOperand(0));
453 O << "\n";
454 return;
Misha Brukman5b570812004-08-10 22:47:03 +0000455 } else if (Opcode == PPC::CALLpcrel) {
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000456 O << TII.getName(Opcode) << " ";
Misha Brukman61114612004-07-20 00:42:19 +0000457 printOp(MI->getOperand(0));
458 O << "\n";
459 return;
Misha Brukman5b570812004-08-10 22:47:03 +0000460 } else if (Opcode == PPC::CALLindirect) {
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000461 O << TII.getName(Opcode) << " ";
462 printImmOp(MI->getOperand(0), ArgType[0]);
Misha Brukman61114612004-07-20 00:42:19 +0000463 O << ", ";
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000464 printImmOp(MI->getOperand(1), ArgType[0]);
Misha Brukman61114612004-07-20 00:42:19 +0000465 O << "\n";
466 return;
Misha Brukman5b570812004-08-10 22:47:03 +0000467 } else if (Opcode == PPC::MovePCtoLR) {
Misha Brukman61114612004-07-20 00:42:19 +0000468 // FIXME: should probably be converted to cout.width and cout.fill
Misha Brukmancf8d2442004-07-26 16:28:33 +0000469 O << "bl \"L0000" << LabelNumber << "$pb\"\n";
470 O << "\"L0000" << LabelNumber << "$pb\":\n";
Misha Brukman218bec72004-06-29 17:13:26 +0000471 O << "\tmflr ";
472 printOp(MI->getOperand(0));
Misha Brukman218bec72004-06-29 17:13:26 +0000473 O << "\n";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000474 return;
475 }
476
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000477 O << TII.getName(Opcode) << " ";
Misha Brukman5b570812004-08-10 22:47:03 +0000478 if (Opcode == PPC::LOADLoDirect || Opcode == PPC::LOADLoIndirect) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000479 printOp(MI->getOperand(0));
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000480 O << ", lo16(";
Nate Begemanb73a7112004-08-13 09:32:01 +0000481 printOp(MI->getOperand(2), true /* LoadAddrOp */);
Misha Brukmancf8d2442004-07-26 16:28:33 +0000482 O << "-\"L0000" << LabelNumber << "$pb\")";
Misha Brukman218bec72004-06-29 17:13:26 +0000483 O << "(";
Misha Brukman5b570812004-08-10 22:47:03 +0000484 if (MI->getOperand(1).getReg() == PPC::R0)
Misha Brukman218bec72004-06-29 17:13:26 +0000485 O << "0";
486 else
487 printOp(MI->getOperand(1));
488 O << ")\n";
Misha Brukman5b570812004-08-10 22:47:03 +0000489 } else if (Opcode == PPC::LOADHiAddr) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000490 printOp(MI->getOperand(0));
491 O << ", ";
Misha Brukman5b570812004-08-10 22:47:03 +0000492 if (MI->getOperand(1).getReg() == PPC::R0)
Misha Brukman218bec72004-06-29 17:13:26 +0000493 O << "0";
494 else
495 printOp(MI->getOperand(1));
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000496 O << ", ha16(" ;
Nate Begemanb73a7112004-08-13 09:32:01 +0000497 printOp(MI->getOperand(2), true /* LoadAddrOp */);
Misha Brukmancf8d2442004-07-26 16:28:33 +0000498 O << "-\"L0000" << LabelNumber << "$pb\")\n";
Misha Brukman5b570812004-08-10 22:47:03 +0000499 } else if (ArgCount == 3 && ArgType[1] == PPCII::Disimm16) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000500 printOp(MI->getOperand(0));
501 O << ", ";
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000502 printImmOp(MI->getOperand(1), ArgType[1]);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000503 O << "(";
Misha Brukmanb9e8f972004-06-30 21:54:12 +0000504 if (MI->getOperand(2).hasAllocatedReg() &&
Misha Brukman5b570812004-08-10 22:47:03 +0000505 MI->getOperand(2).getReg() == PPC::R0)
Misha Brukman46fd00a2004-06-24 23:04:11 +0000506 O << "0";
507 else
508 printOp(MI->getOperand(2));
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000509 O << ")\n";
510 } else {
Misha Brukman7f484a52004-06-24 23:51:00 +0000511 for (i = 0; i < ArgCount; ++i) {
Misha Brukmanab967902004-07-27 18:40:39 +0000512 // addi and friends
Misha Brukman5b570812004-08-10 22:47:03 +0000513 if (i == 1 && ArgCount == 3 && ArgType[2] == PPCII::Simm16 &&
Misha Brukman4363bdb2004-07-01 21:09:12 +0000514 MI->getOperand(1).hasAllocatedReg() &&
Misha Brukman5b570812004-08-10 22:47:03 +0000515 MI->getOperand(1).getReg() == PPC::R0) {
Misha Brukman46fd00a2004-06-24 23:04:11 +0000516 O << "0";
Misha Brukmanab967902004-07-27 18:40:39 +0000517 // for long branch support, bc $+8
518 } else if (i == 1 && ArgCount == 2 && MI->getOperand(1).isImmediate() &&
519 TII.isBranch(MI->getOpcode())) {
520 O << "$+8";
521 assert(8 == MI->getOperand(i).getImmedValue()
522 && "branch off PC not to pc+8?");
523 //printOp(MI->getOperand(i));
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000524 } else if (MI->getOperand(i).isImmediate()) {
525 printImmOp(MI->getOperand(i), ArgType[i]);
Misha Brukman218bec72004-06-29 17:13:26 +0000526 } else {
Misha Brukman46fd00a2004-06-24 23:04:11 +0000527 printOp(MI->getOperand(i));
528 }
Misha Brukman7f484a52004-06-24 23:51:00 +0000529 if (ArgCount - 1 == i)
Misha Brukman46fd00a2004-06-24 23:04:11 +0000530 O << "\n";
531 else
532 O << ", ";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000533 }
534 }
Nate Begemane59bf592004-08-14 22:09:10 +0000535 return;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000536}
537
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000538// SwitchSection - Switch to the specified section of the executable if we are
539// not already in it!
540//
541static void SwitchSection(std::ostream &OS, std::string &CurSection,
542 const char *NewSection) {
543 if (CurSection != NewSection) {
544 CurSection = NewSection;
545 if (!CurSection.empty())
546 OS << "\t" << NewSection << "\n";
547 }
548}
549
Nate Begemane59bf592004-08-14 22:09:10 +0000550bool PowerPCAsmPrinter::doFinalization(Module &M) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000551 const TargetData &TD = TM.getTargetData();
552 std::string CurSection;
553
554 // Print out module-level global variables here.
555 for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
556 if (I->hasInitializer()) { // External global require no code
557 O << "\n\n";
558 std::string name = Mang->getValueName(I);
559 Constant *C = I->getInitializer();
560 unsigned Size = TD.getTypeSize(C->getType());
561 unsigned Align = TD.getTypeAlignment(C->getType());
562
Misha Brukman97a296f2004-07-21 20:11:11 +0000563 if (C->isNullValue() && /* FIXME: Verify correct */
564 (I->hasInternalLinkage() || I->hasWeakLinkage())) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000565 SwitchSection(O, CurSection, ".data");
566 if (I->hasInternalLinkage())
Misha Brukmane2eceb52004-07-23 16:08:20 +0000567 O << ".lcomm " << name << "," << TD.getTypeSize(C->getType())
Misha Brukman218bec72004-06-29 17:13:26 +0000568 << "," << (unsigned)TD.getTypeAlignment(C->getType());
569 else
Misha Brukmane2eceb52004-07-23 16:08:20 +0000570 O << ".comm " << name << "," << TD.getTypeSize(C->getType());
Misha Brukman218bec72004-06-29 17:13:26 +0000571 O << "\t\t; ";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000572 WriteAsOperand(O, I, true, true, &M);
573 O << "\n";
574 } else {
575 switch (I->getLinkage()) {
576 case GlobalValue::LinkOnceLinkage:
Misha Brukman97a296f2004-07-21 20:11:11 +0000577 O << ".section __TEXT,__textcoal_nt,coalesced,no_toc\n"
578 << ".weak_definition " << name << '\n'
579 << ".private_extern " << name << '\n'
580 << ".section __DATA,__datacoal_nt,coalesced,no_toc\n";
581 LinkOnceStubs.insert(name);
582 break;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000583 case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
584 // Nonnull linkonce -> weak
585 O << "\t.weak " << name << "\n";
586 SwitchSection(O, CurSection, "");
587 O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
588 break;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000589 case GlobalValue::AppendingLinkage:
590 // FIXME: appending linkage variables should go into a section of
591 // their name or something. For now, just emit them as external.
592 case GlobalValue::ExternalLinkage:
593 // If external or appending, declare as a global symbol
594 O << "\t.globl " << name << "\n";
595 // FALL THROUGH
596 case GlobalValue::InternalLinkage:
Misha Brukman61297ee2004-06-29 23:40:57 +0000597 SwitchSection(O, CurSection, ".data");
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000598 break;
599 }
600
601 O << "\t.align " << Align << "\n";
Misha Brukman218bec72004-06-29 17:13:26 +0000602 O << name << ":\t\t\t\t; ";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000603 WriteAsOperand(O, I, true, true, &M);
604 O << " = ";
605 WriteAsOperand(O, C, false, false, &M);
606 O << "\n";
607 emitGlobalConstant(C);
608 }
609 }
Misha Brukmanda2b13f2004-07-16 20:29:04 +0000610
611 // Output stubs for dynamically-linked functions
612 for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
613 i != e; ++i)
Misha Brukman46fd00a2004-06-24 23:04:11 +0000614 {
Misha Brukmane2eceb52004-07-23 16:08:20 +0000615 O << ".data\n";
616 O << ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n";
617 O << "\t.align 2\n";
Misha Brukman46fd00a2004-06-24 23:04:11 +0000618 O << "L" << *i << "$stub:\n";
619 O << "\t.indirect_symbol " << *i << "\n";
620 O << "\tmflr r0\n";
Misha Brukmane2eceb52004-07-23 16:08:20 +0000621 O << "\tbcl 20,31,L0$" << *i << "\n";
Misha Brukman46fd00a2004-06-24 23:04:11 +0000622 O << "L0$" << *i << ":\n";
623 O << "\tmflr r11\n";
624 O << "\taddis r11,r11,ha16(L" << *i << "$lazy_ptr-L0$" << *i << ")\n";
625 O << "\tmtlr r0\n";
Misha Brukmane2eceb52004-07-23 16:08:20 +0000626 O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n";
Misha Brukman46fd00a2004-06-24 23:04:11 +0000627 O << "\tmtctr r12\n";
628 O << "\tbctr\n";
629 O << ".data\n";
630 O << ".lazy_symbol_pointer\n";
631 O << "L" << *i << "$lazy_ptr:\n";
Misha Brukmane2eceb52004-07-23 16:08:20 +0000632 O << "\t.indirect_symbol " << *i << "\n";
633 O << "\t.long dyld_stub_binding_helper\n";
Misha Brukman46fd00a2004-06-24 23:04:11 +0000634 }
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000635
Misha Brukmanda2b13f2004-07-16 20:29:04 +0000636 O << "\n";
637
638 // Output stubs for external global variables
639 if (GVStubs.begin() != GVStubs.end())
Misha Brukmane2eceb52004-07-23 16:08:20 +0000640 O << ".data\n.non_lazy_symbol_pointer\n";
Misha Brukmanda2b13f2004-07-16 20:29:04 +0000641 for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
642 i != e; ++i) {
643 O << "L" << *i << "$non_lazy_ptr:\n";
644 O << "\t.indirect_symbol " << *i << "\n";
645 O << "\t.long\t0\n";
646 }
647
Nate Begemane59bf592004-08-14 22:09:10 +0000648 // Output stubs for link-once variables
649 if (LinkOnceStubs.begin() != LinkOnceStubs.end())
650 O << ".data\n.align 2\n";
651 for (std::set<std::string>::iterator i = LinkOnceStubs.begin(),
652 e = LinkOnceStubs.end(); i != e; ++i) {
653 O << "L" << *i << "$non_lazy_ptr:\n"
654 << "\t.long\t" << *i << '\n';
655 }
656
Chris Lattnera3840792004-08-16 23:25:21 +0000657 AsmPrinter::doFinalization(M);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000658 return false; // success
659}