blob: 151580c8d26894c23e4c79167f45a0e7f92622de [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)
49 : AsmPrinter(O, TM), LabelNumber(0) {}
Misha Brukman5dfe3a92004-06-21 16:55:25 +000050
Misha Brukmancf8d2442004-07-26 16:28:33 +000051 /// Unique incrementer for label values for referencing Global values.
Misha Brukman218bec72004-06-29 17:13:26 +000052 ///
Misha Brukmancf8d2442004-07-26 16:28:33 +000053 unsigned LabelNumber;
54
Misha Brukman5dfe3a92004-06-21 16:55:25 +000055 virtual const char *getPassName() const {
Nate Begemane59bf592004-08-14 22:09:10 +000056 return "PowerPC Assembly Printer";
Misha Brukman5dfe3a92004-06-21 16:55:25 +000057 }
58
Chris Lattnera3840792004-08-16 23:25:21 +000059 PowerPCTargetMachine &getTM() {
60 return static_cast<PowerPCTargetMachine&>(TM);
61 }
62
Nate Begemane59bf592004-08-14 22:09:10 +000063 /// printInstruction - This method is automatically generated by tablegen
64 /// from the instruction set description. This method returns true if the
65 /// machine instruction was sufficiently described to print it, otherwise it
66 /// returns false.
67 bool printInstruction(const MachineInstr *MI);
68
Misha Brukman5dfe3a92004-06-21 16:55:25 +000069 void printMachineInstruction(const MachineInstr *MI);
Nate Begemanb73a7112004-08-13 09:32:01 +000070 void printOp(const MachineOperand &MO, bool LoadAddrOp = false);
Misha Brukmanaf313fb2004-07-28 00:00:48 +000071 void printImmOp(const MachineOperand &MO, unsigned ArgType);
Chris Lattner7bb424f2004-08-14 23:27:29 +000072
73 void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){
74 const MachineOperand &MO = MI->getOperand(OpNo);
75 if (MO.getType() == MachineOperand::MO_MachineRegister) {
76 assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
77 O << LowercaseString(TM.getRegisterInfo()->get(MO.getReg()).Name);
Chris Lattner0ea31712004-08-15 05:46:14 +000078 } else if (MO.isImmediate()) {
79 O << MO.getImmedValue();
Chris Lattner7bb424f2004-08-14 23:27:29 +000080 } else {
81 printOp(MO);
82 }
83 }
84
Chris Lattner97b2a2e2004-08-15 05:20:16 +000085 void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo,
86 MVT::ValueType VT) {
87 O << (unsigned short)MI->getOperand(OpNo).getImmedValue();
88 }
89
Misha Brukman5dfe3a92004-06-21 16:55:25 +000090 void printConstantPool(MachineConstantPool *MCP);
91 bool runOnMachineFunction(MachineFunction &F);
Misha Brukman5dfe3a92004-06-21 16:55:25 +000092 bool doFinalization(Module &M);
93 void emitGlobalConstant(const Constant* CV);
Misha Brukman5dfe3a92004-06-21 16:55:25 +000094 };
95} // end of anonymous namespace
96
Misha Brukman3d9a6c22004-08-11 00:09:42 +000097/// createPPC32AsmPrinterPass - Returns a pass that prints the PPC
Misha Brukman5dfe3a92004-06-21 16:55:25 +000098/// assembly code for a MachineFunction to the given output stream,
99/// using the given target machine description. This should work
Misha Brukman7103fba2004-08-09 22:27:45 +0000100/// regardless of whether the function is in SSA form or not.
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000101///
Chris Lattnera3840792004-08-16 23:25:21 +0000102FunctionPass *llvm::createPPCAsmPrinter(std::ostream &o,TargetMachine &tm) {
Nate Begemane59bf592004-08-14 22:09:10 +0000103 return new PowerPCAsmPrinter(o, tm);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000104}
105
Nate Begemane59bf592004-08-14 22:09:10 +0000106// Include the auto-generated portion of the assembly writer
107#include "PowerPCGenAsmWriter.inc"
108
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000109/// toOctal - Convert the low order bits of X into an octal digit.
110///
111static inline char toOctal(int X) {
112 return (X&7)+'0';
113}
114
115/// getAsCString - Return the specified array as a C compatible
Chris Lattner36aacdb2004-08-16 23:30:16 +0000116/// string, only if the predicate isString is true.
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000117///
118static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
Chris Lattner36aacdb2004-08-16 23:30:16 +0000119 assert(CVA->isString() && "Array is not string compatible!");
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000120
121 O << "\"";
Chris Lattner36aacdb2004-08-16 23:30:16 +0000122 for (unsigned i = 0; i != CVA->getNumOperands(); ++i) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000123 unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
124
125 if (C == '"') {
126 O << "\\\"";
127 } else if (C == '\\') {
128 O << "\\\\";
129 } else if (isprint(C)) {
130 O << C;
131 } else {
Chris Lattner36aacdb2004-08-16 23:30:16 +0000132 switch(C) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000133 case '\b': O << "\\b"; break;
134 case '\f': O << "\\f"; break;
135 case '\n': O << "\\n"; break;
136 case '\r': O << "\\r"; break;
137 case '\t': O << "\\t"; break;
138 default:
139 O << '\\';
140 O << toOctal(C >> 6);
141 O << toOctal(C >> 3);
142 O << toOctal(C >> 0);
143 break;
144 }
145 }
146 }
147 O << "\"";
148}
149
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000150// Print a constant value or values, with the appropriate storage class as a
151// prefix.
Nate Begemane59bf592004-08-14 22:09:10 +0000152void PowerPCAsmPrinter::emitGlobalConstant(const Constant *CV) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000153 const TargetData &TD = TM.getTargetData();
154
Chris Lattner416ca332004-08-16 23:38:36 +0000155 if (CV->isNullValue()) {
156 O << "\t.space\t" << TD.getTypeSize(CV->getType()) << "\n";
157 return;
158 } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
159 if (CVA->isString()) {
160 O << "\t.ascii\t";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000161 printAsCString(O, CVA);
162 O << "\n";
163 } else { // Not a string. Print the values in successive locations
Chris Lattner416ca332004-08-16 23:38:36 +0000164 for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
Chris Lattner6173cd92004-08-04 17:29:14 +0000165 emitGlobalConstant(CVA->getOperand(i));
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000166 }
167 return;
168 } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
169 // Print the fields in successive locations. Pad to align if needed!
170 const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000171 unsigned sizeSoFar = 0;
Chris Lattner416ca332004-08-16 23:38:36 +0000172 for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
Chris Lattner6173cd92004-08-04 17:29:14 +0000173 const Constant* field = CVS->getOperand(i);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000174
175 // Check if padding is needed and insert one or more 0s.
176 unsigned fieldSize = TD.getTypeSize(field->getType());
Chris Lattner6173cd92004-08-04 17:29:14 +0000177 unsigned padSize = ((i == e-1? cvsLayout->StructSize
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000178 : cvsLayout->MemberOffsets[i+1])
179 - cvsLayout->MemberOffsets[i]) - fieldSize;
180 sizeSoFar += fieldSize + padSize;
181
182 // Now print the actual field value
183 emitGlobalConstant(field);
184
185 // Insert the field padding unless it's zero bytes...
186 if (padSize)
187 O << "\t.space\t " << padSize << "\n";
188 }
189 assert(sizeSoFar == cvsLayout->StructSize &&
190 "Layout of constant struct may be incorrect!");
191 return;
192 } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
193 // FP Constants are printed as integer constants to avoid losing
194 // precision...
195 double Val = CFP->getValue();
Nate Begemane59bf592004-08-14 22:09:10 +0000196 union DU { // Abide by C TBAA rules
197 double FVal;
198 uint64_t UVal;
199 struct {
200 uint32_t MSWord;
201 uint32_t LSWord;
202 } T;
203 } U;
204 U.FVal = Val;
205
206 O << ".long\t" << U.T.MSWord << "\t; double most significant word "
207 << Val << "\n";
208 O << ".long\t" << U.T.LSWord << "\t; double least significant word "
209 << Val << "\n";
210 return;
Misha Brukmanf63bc192004-07-28 19:12:24 +0000211 } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
Misha Brukman2bf183c2004-06-25 15:42:10 +0000212 if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
213 union DU { // Abide by C TBAA rules
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000214 int64_t UVal;
215 struct {
Misha Brukman46fd00a2004-06-24 23:04:11 +0000216 uint32_t MSWord;
217 uint32_t LSWord;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000218 } T;
219 } U;
220 U.UVal = CI->getRawValue();
221
Misha Brukman218bec72004-06-29 17:13:26 +0000222 O << ".long\t" << U.T.MSWord << "\t; Double-word most significant word "
Misha Brukman46fd00a2004-06-24 23:04:11 +0000223 << U.UVal << "\n";
Misha Brukman29188c62004-07-16 19:01:13 +0000224 O << ".long\t" << U.T.LSWord << "\t; Double-word least significant word "
Misha Brukman46fd00a2004-06-24 23:04:11 +0000225 << U.UVal << "\n";
226 return;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000227 }
228 }
229
230 const Type *type = CV->getType();
231 O << "\t";
Misha Brukmand71bd562004-06-21 17:19:08 +0000232 switch (type->getTypeID()) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000233 case Type::UByteTyID: case Type::SByteTyID:
234 O << ".byte";
235 break;
236 case Type::UShortTyID: case Type::ShortTyID:
237 O << ".short";
238 break;
239 case Type::BoolTyID:
240 case Type::PointerTyID:
241 case Type::UIntTyID: case Type::IntTyID:
242 O << ".long";
243 break;
244 case Type::ULongTyID: case Type::LongTyID:
Misha Brukman46fd00a2004-06-24 23:04:11 +0000245 assert (0 && "Should have already output double-word constant.");
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000246 case Type::FloatTyID: case Type::DoubleTyID:
247 assert (0 && "Should have already output floating point constant.");
248 default:
Chris Lattner416ca332004-08-16 23:38:36 +0000249 assert (0 && "Can't handle printing this type of thing");
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000250 break;
251 }
252 O << "\t";
253 emitConstantValueOnly(CV);
254 O << "\n";
255}
256
257/// printConstantPool - Print to the current output stream assembly
258/// representations of the constants in the constant pool MCP. This is
259/// used to print out constants which have been "spilled to memory" by
260/// the code generator.
261///
Nate Begemane59bf592004-08-14 22:09:10 +0000262void PowerPCAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000263 const std::vector<Constant*> &CP = MCP->getConstants();
264 const TargetData &TD = TM.getTargetData();
265
266 if (CP.empty()) return;
267
268 for (unsigned i = 0, e = CP.size(); i != e; ++i) {
269 O << "\t.const\n";
270 O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType())
271 << "\n";
Misha Brukman218bec72004-06-29 17:13:26 +0000272 O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t;"
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000273 << *CP[i] << "\n";
274 emitGlobalConstant(CP[i]);
275 }
276}
277
278/// runOnMachineFunction - This uses the printMachineInstruction()
279/// method to print assembly for each instruction.
280///
Nate Begemane59bf592004-08-14 22:09:10 +0000281bool PowerPCAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
Chris Lattnera3840792004-08-16 23:25:21 +0000282 setupMachineFunction(MF);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000283 O << "\n\n";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000284
285 // Print out constants referenced by the function
286 printConstantPool(MF.getConstantPool());
287
288 // Print out labels for the function.
289 O << "\t.text\n";
290 O << "\t.globl\t" << CurrentFnName << "\n";
Misha Brukman61297ee2004-06-29 23:40:57 +0000291 O << "\t.align 2\n";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000292 O << CurrentFnName << ":\n";
293
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000294 // Print out code for the function.
295 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
296 I != E; ++I) {
297 // Print a label for the basic block.
Misha Brukman218bec72004-06-29 17:13:26 +0000298 O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t; "
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000299 << I->getBasicBlock()->getName() << "\n";
300 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
Misha Brukman46fd00a2004-06-24 23:04:11 +0000301 II != E; ++II) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000302 // Print the assembly for the instruction.
303 O << "\t";
304 printMachineInstruction(II);
305 }
306 }
Misha Brukmancf8d2442004-07-26 16:28:33 +0000307 ++LabelNumber;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000308
309 // We didn't modify anything.
310 return false;
311}
312
Nate Begemane59bf592004-08-14 22:09:10 +0000313void PowerPCAsmPrinter::printOp(const MachineOperand &MO,
Nate Begemanb73a7112004-08-13 09:32:01 +0000314 bool LoadAddrOp /* = false */) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000315 const MRegisterInfo &RI = *TM.getRegisterInfo();
316 int new_symbol;
317
318 switch (MO.getType()) {
319 case MachineOperand::MO_VirtualRegister:
320 if (Value *V = MO.getVRegValueOrNull()) {
321 O << "<" << V->getName() << ">";
322 return;
323 }
324 // FALLTHROUGH
325 case MachineOperand::MO_MachineRegister:
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000326 case MachineOperand::MO_CCRegister:
Misha Brukman7f484a52004-06-24 23:51:00 +0000327 O << LowercaseString(RI.get(MO.getReg()).Name);
328 return;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000329
330 case MachineOperand::MO_SignExtendedImmed:
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000331 case MachineOperand::MO_UnextendedImmed:
332 std::cerr << "printOp() does not handle immediate values\n";
333 abort();
Misha Brukman97a296f2004-07-21 20:11:11 +0000334 return;
335
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000336 case MachineOperand::MO_PCRelativeDisp:
337 std::cerr << "Shouldn't use addPCDisp() when building PPC MachineInstrs";
338 abort();
339 return;
340
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000341 case MachineOperand::MO_MachineBasicBlock: {
342 MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
343 O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
Misha Brukman218bec72004-06-29 17:13:26 +0000344 << "_" << MBBOp->getNumber() << "\t; "
Misha Brukman2bf183c2004-06-25 15:42:10 +0000345 << MBBOp->getBasicBlock()->getName();
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000346 return;
347 }
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000348
349 case MachineOperand::MO_ConstantPoolIndex:
350 O << ".CPI" << CurrentFnName << "_" << MO.getConstantPoolIndex();
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000351 return;
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000352
353 case MachineOperand::MO_ExternalSymbol:
354 O << MO.getSymbolName();
355 return;
356
Nate Begemanb73a7112004-08-13 09:32:01 +0000357 case MachineOperand::MO_GlobalAddress: {
358 GlobalValue *GV = MO.getGlobal();
359 std::string Name = Mang->getValueName(GV);
Misha Brukmane2eceb52004-07-23 16:08:20 +0000360
Nate Begemanb73a7112004-08-13 09:32:01 +0000361 // Dynamically-resolved functions need a stub for the function. Be
362 // wary however not to output $stub for external functions whose addresses
363 // are taken. Those should be emitted as $non_lazy_ptr below.
364 Function *F = dyn_cast<Function>(GV);
365 if (F && F->isExternal() && !LoadAddrOp &&
Chris Lattnera3840792004-08-16 23:25:21 +0000366 getTM().CalledFunctions.count(F)) {
Nate Begemanb73a7112004-08-13 09:32:01 +0000367 FnStubs.insert(Name);
368 O << "L" << Name << "$stub";
369 return;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000370 }
Nate Begemane59bf592004-08-14 22:09:10 +0000371
Nate Begemanb73a7112004-08-13 09:32:01 +0000372 // External global variables need a non-lazily-resolved stub
Chris Lattnera3840792004-08-16 23:25:21 +0000373 if (GV->isExternal() && getTM().AddressTaken.count(GV)) {
Nate Begemanb73a7112004-08-13 09:32:01 +0000374 GVStubs.insert(Name);
375 O << "L" << Name << "$non_lazy_ptr";
376 return;
377 }
Nate Begemane59bf592004-08-14 22:09:10 +0000378
Chris Lattnera3840792004-08-16 23:25:21 +0000379 if (F && LoadAddrOp && getTM().AddressTaken.count(GV)) {
Nate Begemane59bf592004-08-14 22:09:10 +0000380 LinkOnceStubs.insert(Name);
381 O << "L" << Name << "$non_lazy_ptr";
382 return;
383 }
Nate Begemanb73a7112004-08-13 09:32:01 +0000384
385 O << Mang->getValueName(GV);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000386 return;
Nate Begemanb73a7112004-08-13 09:32:01 +0000387 }
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000388
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000389 default:
Misha Brukman05fcd0c2004-07-08 17:58:04 +0000390 O << "<unknown operand type: " << MO.getType() << ">";
Misha Brukman22e12072004-06-25 15:11:34 +0000391 return;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000392 }
393}
394
Nate Begemane59bf592004-08-14 22:09:10 +0000395void PowerPCAsmPrinter::printImmOp(const MachineOperand &MO, unsigned ArgType) {
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000396 int Imm = MO.getImmedValue();
Misha Brukman5b570812004-08-10 22:47:03 +0000397 if (ArgType == PPCII::Simm16 || ArgType == PPCII::Disimm16) {
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000398 O << (short)Imm;
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000399 } else {
400 O << Imm;
401 }
402}
403
Nate Begemane59bf592004-08-14 22:09:10 +0000404/// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to
405/// the current output stream.
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000406///
Nate Begemane59bf592004-08-14 22:09:10 +0000407void PowerPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
408 ++EmittedInsts;
409 if (printInstruction(MI))
410 return; // Printer was automatically generated
411
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000412 unsigned Opcode = MI->getOpcode();
413 const TargetInstrInfo &TII = *TM.getInstrInfo();
414 const TargetInstrDescriptor &Desc = TII.get(Opcode);
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000415 unsigned i;
Misha Brukmanc6cc10f2004-06-25 19:24:52 +0000416
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000417 unsigned ArgCount = MI->getNumOperands();
418 unsigned ArgType[] = {
Misha Brukman5b570812004-08-10 22:47:03 +0000419 (Desc.TSFlags >> PPCII::Arg0TypeShift) & PPCII::ArgTypeMask,
420 (Desc.TSFlags >> PPCII::Arg1TypeShift) & PPCII::ArgTypeMask,
421 (Desc.TSFlags >> PPCII::Arg2TypeShift) & PPCII::ArgTypeMask,
422 (Desc.TSFlags >> PPCII::Arg3TypeShift) & PPCII::ArgTypeMask,
423 (Desc.TSFlags >> PPCII::Arg4TypeShift) & PPCII::ArgTypeMask
Misha Brukman22e12072004-06-25 15:11:34 +0000424 };
Misha Brukman5b570812004-08-10 22:47:03 +0000425 assert(((Desc.TSFlags & PPCII::VMX) == 0) &&
Misha Brukman46fd00a2004-06-24 23:04:11 +0000426 "Instruction requires VMX support");
Misha Brukman5b570812004-08-10 22:47:03 +0000427 assert(((Desc.TSFlags & PPCII::PPC64) == 0) &&
Misha Brukman46fd00a2004-06-24 23:04:11 +0000428 "Instruction requires 64 bit support");
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000429
Misha Brukman61114612004-07-20 00:42:19 +0000430 // CALLpcrel and CALLindirect are handled specially here to print only the
431 // appropriate number of args that the assembler expects. This is because
432 // may have many arguments appended to record the uses of registers that are
433 // holding arguments to the called function.
Misha Brukman5b570812004-08-10 22:47:03 +0000434 if (Opcode == PPC::COND_BRANCH) {
Misha Brukmanab967902004-07-27 18:40:39 +0000435 std::cerr << "Error: untranslated conditional branch psuedo instruction!\n";
436 abort();
Misha Brukman5b570812004-08-10 22:47:03 +0000437 } else if (Opcode == PPC::IMPLICIT_DEF) {
Misha Brukman29188c62004-07-16 19:01:13 +0000438 O << "; IMPLICIT DEF ";
439 printOp(MI->getOperand(0));
440 O << "\n";
441 return;
Misha Brukman5b570812004-08-10 22:47:03 +0000442 } else if (Opcode == PPC::CALLpcrel) {
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000443 O << TII.getName(Opcode) << " ";
Misha Brukman61114612004-07-20 00:42:19 +0000444 printOp(MI->getOperand(0));
445 O << "\n";
446 return;
Misha Brukman5b570812004-08-10 22:47:03 +0000447 } else if (Opcode == PPC::CALLindirect) {
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000448 O << TII.getName(Opcode) << " ";
449 printImmOp(MI->getOperand(0), ArgType[0]);
Misha Brukman61114612004-07-20 00:42:19 +0000450 O << ", ";
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000451 printImmOp(MI->getOperand(1), ArgType[0]);
Misha Brukman61114612004-07-20 00:42:19 +0000452 O << "\n";
453 return;
Misha Brukman5b570812004-08-10 22:47:03 +0000454 } else if (Opcode == PPC::MovePCtoLR) {
Misha Brukman61114612004-07-20 00:42:19 +0000455 // FIXME: should probably be converted to cout.width and cout.fill
Misha Brukmancf8d2442004-07-26 16:28:33 +0000456 O << "bl \"L0000" << LabelNumber << "$pb\"\n";
457 O << "\"L0000" << LabelNumber << "$pb\":\n";
Misha Brukman218bec72004-06-29 17:13:26 +0000458 O << "\tmflr ";
459 printOp(MI->getOperand(0));
Misha Brukman218bec72004-06-29 17:13:26 +0000460 O << "\n";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000461 return;
462 }
463
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000464 O << TII.getName(Opcode) << " ";
Misha Brukman5b570812004-08-10 22:47:03 +0000465 if (Opcode == PPC::LOADLoDirect || Opcode == PPC::LOADLoIndirect) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000466 printOp(MI->getOperand(0));
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000467 O << ", lo16(";
Nate Begemanb73a7112004-08-13 09:32:01 +0000468 printOp(MI->getOperand(2), true /* LoadAddrOp */);
Misha Brukmancf8d2442004-07-26 16:28:33 +0000469 O << "-\"L0000" << LabelNumber << "$pb\")";
Misha Brukman218bec72004-06-29 17:13:26 +0000470 O << "(";
Misha Brukman5b570812004-08-10 22:47:03 +0000471 if (MI->getOperand(1).getReg() == PPC::R0)
Misha Brukman218bec72004-06-29 17:13:26 +0000472 O << "0";
473 else
474 printOp(MI->getOperand(1));
475 O << ")\n";
Misha Brukman5b570812004-08-10 22:47:03 +0000476 } else if (Opcode == PPC::LOADHiAddr) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000477 printOp(MI->getOperand(0));
478 O << ", ";
Misha Brukman5b570812004-08-10 22:47:03 +0000479 if (MI->getOperand(1).getReg() == PPC::R0)
Misha Brukman218bec72004-06-29 17:13:26 +0000480 O << "0";
481 else
482 printOp(MI->getOperand(1));
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000483 O << ", ha16(" ;
Nate Begemanb73a7112004-08-13 09:32:01 +0000484 printOp(MI->getOperand(2), true /* LoadAddrOp */);
Misha Brukmancf8d2442004-07-26 16:28:33 +0000485 O << "-\"L0000" << LabelNumber << "$pb\")\n";
Misha Brukman5b570812004-08-10 22:47:03 +0000486 } else if (ArgCount == 3 && ArgType[1] == PPCII::Disimm16) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000487 printOp(MI->getOperand(0));
488 O << ", ";
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000489 printImmOp(MI->getOperand(1), ArgType[1]);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000490 O << "(";
Misha Brukmanb9e8f972004-06-30 21:54:12 +0000491 if (MI->getOperand(2).hasAllocatedReg() &&
Misha Brukman5b570812004-08-10 22:47:03 +0000492 MI->getOperand(2).getReg() == PPC::R0)
Misha Brukman46fd00a2004-06-24 23:04:11 +0000493 O << "0";
494 else
495 printOp(MI->getOperand(2));
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000496 O << ")\n";
497 } else {
Misha Brukman7f484a52004-06-24 23:51:00 +0000498 for (i = 0; i < ArgCount; ++i) {
Misha Brukmanab967902004-07-27 18:40:39 +0000499 // addi and friends
Misha Brukman5b570812004-08-10 22:47:03 +0000500 if (i == 1 && ArgCount == 3 && ArgType[2] == PPCII::Simm16 &&
Misha Brukman4363bdb2004-07-01 21:09:12 +0000501 MI->getOperand(1).hasAllocatedReg() &&
Misha Brukman5b570812004-08-10 22:47:03 +0000502 MI->getOperand(1).getReg() == PPC::R0) {
Misha Brukman46fd00a2004-06-24 23:04:11 +0000503 O << "0";
Misha Brukmanab967902004-07-27 18:40:39 +0000504 // for long branch support, bc $+8
505 } else if (i == 1 && ArgCount == 2 && MI->getOperand(1).isImmediate() &&
506 TII.isBranch(MI->getOpcode())) {
507 O << "$+8";
508 assert(8 == MI->getOperand(i).getImmedValue()
509 && "branch off PC not to pc+8?");
510 //printOp(MI->getOperand(i));
Misha Brukmanaf313fb2004-07-28 00:00:48 +0000511 } else if (MI->getOperand(i).isImmediate()) {
512 printImmOp(MI->getOperand(i), ArgType[i]);
Misha Brukman218bec72004-06-29 17:13:26 +0000513 } else {
Misha Brukman46fd00a2004-06-24 23:04:11 +0000514 printOp(MI->getOperand(i));
515 }
Misha Brukman7f484a52004-06-24 23:51:00 +0000516 if (ArgCount - 1 == i)
Misha Brukman46fd00a2004-06-24 23:04:11 +0000517 O << "\n";
518 else
519 O << ", ";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000520 }
521 }
Nate Begemane59bf592004-08-14 22:09:10 +0000522 return;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000523}
524
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000525// SwitchSection - Switch to the specified section of the executable if we are
526// not already in it!
527//
528static void SwitchSection(std::ostream &OS, std::string &CurSection,
529 const char *NewSection) {
530 if (CurSection != NewSection) {
531 CurSection = NewSection;
532 if (!CurSection.empty())
533 OS << "\t" << NewSection << "\n";
534 }
535}
536
Nate Begemane59bf592004-08-14 22:09:10 +0000537bool PowerPCAsmPrinter::doFinalization(Module &M) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000538 const TargetData &TD = TM.getTargetData();
539 std::string CurSection;
540
541 // Print out module-level global variables here.
542 for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
543 if (I->hasInitializer()) { // External global require no code
544 O << "\n\n";
545 std::string name = Mang->getValueName(I);
546 Constant *C = I->getInitializer();
547 unsigned Size = TD.getTypeSize(C->getType());
548 unsigned Align = TD.getTypeAlignment(C->getType());
549
Misha Brukman97a296f2004-07-21 20:11:11 +0000550 if (C->isNullValue() && /* FIXME: Verify correct */
551 (I->hasInternalLinkage() || I->hasWeakLinkage())) {
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000552 SwitchSection(O, CurSection, ".data");
553 if (I->hasInternalLinkage())
Misha Brukmane2eceb52004-07-23 16:08:20 +0000554 O << ".lcomm " << name << "," << TD.getTypeSize(C->getType())
Misha Brukman218bec72004-06-29 17:13:26 +0000555 << "," << (unsigned)TD.getTypeAlignment(C->getType());
556 else
Misha Brukmane2eceb52004-07-23 16:08:20 +0000557 O << ".comm " << name << "," << TD.getTypeSize(C->getType());
Misha Brukman218bec72004-06-29 17:13:26 +0000558 O << "\t\t; ";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000559 WriteAsOperand(O, I, true, true, &M);
560 O << "\n";
561 } else {
562 switch (I->getLinkage()) {
563 case GlobalValue::LinkOnceLinkage:
Misha Brukman97a296f2004-07-21 20:11:11 +0000564 O << ".section __TEXT,__textcoal_nt,coalesced,no_toc\n"
565 << ".weak_definition " << name << '\n'
566 << ".private_extern " << name << '\n'
567 << ".section __DATA,__datacoal_nt,coalesced,no_toc\n";
568 LinkOnceStubs.insert(name);
569 break;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000570 case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
571 // Nonnull linkonce -> weak
572 O << "\t.weak " << name << "\n";
573 SwitchSection(O, CurSection, "");
574 O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
575 break;
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000576 case GlobalValue::AppendingLinkage:
577 // FIXME: appending linkage variables should go into a section of
578 // their name or something. For now, just emit them as external.
579 case GlobalValue::ExternalLinkage:
580 // If external or appending, declare as a global symbol
581 O << "\t.globl " << name << "\n";
582 // FALL THROUGH
583 case GlobalValue::InternalLinkage:
Misha Brukman61297ee2004-06-29 23:40:57 +0000584 SwitchSection(O, CurSection, ".data");
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000585 break;
586 }
587
588 O << "\t.align " << Align << "\n";
Misha Brukman218bec72004-06-29 17:13:26 +0000589 O << name << ":\t\t\t\t; ";
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000590 WriteAsOperand(O, I, true, true, &M);
591 O << " = ";
592 WriteAsOperand(O, C, false, false, &M);
593 O << "\n";
594 emitGlobalConstant(C);
595 }
596 }
Misha Brukmanda2b13f2004-07-16 20:29:04 +0000597
598 // Output stubs for dynamically-linked functions
599 for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
600 i != e; ++i)
Misha Brukman46fd00a2004-06-24 23:04:11 +0000601 {
Misha Brukmane2eceb52004-07-23 16:08:20 +0000602 O << ".data\n";
603 O << ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n";
604 O << "\t.align 2\n";
Misha Brukman46fd00a2004-06-24 23:04:11 +0000605 O << "L" << *i << "$stub:\n";
606 O << "\t.indirect_symbol " << *i << "\n";
607 O << "\tmflr r0\n";
Misha Brukmane2eceb52004-07-23 16:08:20 +0000608 O << "\tbcl 20,31,L0$" << *i << "\n";
Misha Brukman46fd00a2004-06-24 23:04:11 +0000609 O << "L0$" << *i << ":\n";
610 O << "\tmflr r11\n";
611 O << "\taddis r11,r11,ha16(L" << *i << "$lazy_ptr-L0$" << *i << ")\n";
612 O << "\tmtlr r0\n";
Misha Brukmane2eceb52004-07-23 16:08:20 +0000613 O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n";
Misha Brukman46fd00a2004-06-24 23:04:11 +0000614 O << "\tmtctr r12\n";
615 O << "\tbctr\n";
616 O << ".data\n";
617 O << ".lazy_symbol_pointer\n";
618 O << "L" << *i << "$lazy_ptr:\n";
Misha Brukmane2eceb52004-07-23 16:08:20 +0000619 O << "\t.indirect_symbol " << *i << "\n";
620 O << "\t.long dyld_stub_binding_helper\n";
Misha Brukman46fd00a2004-06-24 23:04:11 +0000621 }
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000622
Misha Brukmanda2b13f2004-07-16 20:29:04 +0000623 O << "\n";
624
625 // Output stubs for external global variables
626 if (GVStubs.begin() != GVStubs.end())
Misha Brukmane2eceb52004-07-23 16:08:20 +0000627 O << ".data\n.non_lazy_symbol_pointer\n";
Misha Brukmanda2b13f2004-07-16 20:29:04 +0000628 for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
629 i != e; ++i) {
630 O << "L" << *i << "$non_lazy_ptr:\n";
631 O << "\t.indirect_symbol " << *i << "\n";
632 O << "\t.long\t0\n";
633 }
634
Nate Begemane59bf592004-08-14 22:09:10 +0000635 // Output stubs for link-once variables
636 if (LinkOnceStubs.begin() != LinkOnceStubs.end())
637 O << ".data\n.align 2\n";
638 for (std::set<std::string>::iterator i = LinkOnceStubs.begin(),
639 e = LinkOnceStubs.end(); i != e; ++i) {
640 O << "L" << *i << "$non_lazy_ptr:\n"
641 << "\t.long\t" << *i << '\n';
642 }
643
Chris Lattnera3840792004-08-16 23:25:21 +0000644 AsmPrinter::doFinalization(M);
Misha Brukman5dfe3a92004-06-21 16:55:25 +0000645 return false; // success
646}