PPCAsmPrinter.cpp revision b7a8f2cdaa3db15861c7f06238fcacc4b10b74f3
1//===-- PPC32AsmPrinter.cpp - Print machine instrs to PowerPC assembly ----===// 2// 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// 10// This file contains a printer that converts from our internal representation 11// of machine-dependent LLVM code to PowerPC assembly language. This printer is 12// the output mechanism used by `llc'. 13// 14// Documentation at http://developer.apple.com/documentation/DeveloperTools/ 15// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html 16// 17//===----------------------------------------------------------------------===// 18 19#define DEBUG_TYPE "asmprinter" 20#include "PowerPC.h" 21#include "PPC32TargetMachine.h" 22#include "llvm/Constants.h" 23#include "llvm/DerivedTypes.h" 24#include "llvm/Module.h" 25#include "llvm/Assembly/Writer.h" 26#include "llvm/CodeGen/AsmPrinter.h" 27#include "llvm/CodeGen/MachineConstantPool.h" 28#include "llvm/CodeGen/MachineFunctionPass.h" 29#include "llvm/CodeGen/MachineInstr.h" 30#include "llvm/CodeGen/ValueTypes.h" 31#include "llvm/Support/Mangler.h" 32#include "llvm/Support/CommandLine.h" 33#include "llvm/Support/Debug.h" 34#include "llvm/ADT/Statistic.h" 35#include "llvm/ADT/StringExtras.h" 36#include <set> 37using namespace llvm; 38 39namespace { 40 Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed"); 41 42 struct PPC32AsmPrinter : public AsmPrinter { 43 std::set<std::string> FnStubs, GVStubs, LinkOnceStubs; 44 std::set<std::string> Strings; 45 46 PPC32AsmPrinter(std::ostream &O, TargetMachine &TM) 47 : AsmPrinter(O, TM), LabelNumber(0) { 48 CommentString = ";"; 49 GlobalPrefix = "_"; 50 ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. 51 Data64bitsDirective = 0; // we can't emit a 64-bit unit 52 AlignmentIsInBytes = false; // Alignment is by power of 2. 53 } 54 55 /// Unique incrementer for label values for referencing Global values. 56 /// 57 unsigned LabelNumber; 58 59 virtual const char *getPassName() const { 60 return "PPC32 Assembly Printer"; 61 } 62 63 PPC32TargetMachine &getTM() { 64 return static_cast<PPC32TargetMachine&>(TM); 65 } 66 67 /// printInstruction - This method is automatically generated by tablegen 68 /// from the instruction set description. This method returns true if the 69 /// machine instruction was sufficiently described to print it, otherwise it 70 /// returns false. 71 bool printInstruction(const MachineInstr *MI); 72 73 void printMachineInstruction(const MachineInstr *MI); 74 void printOp(const MachineOperand &MO, bool LoadAddrOp = false); 75 void printImmOp(const MachineOperand &MO, unsigned ArgType); 76 77 void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){ 78 const MachineOperand &MO = MI->getOperand(OpNo); 79 if (MO.getType() == MachineOperand::MO_MachineRegister) { 80 assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??"); 81 O << LowercaseString(TM.getRegisterInfo()->get(MO.getReg()).Name); 82 } else if (MO.isImmediate()) { 83 O << MO.getImmedValue(); 84 } else { 85 printOp(MO); 86 } 87 } 88 89 void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo, 90 MVT::ValueType VT) { 91 unsigned char value = MI->getOperand(OpNo).getImmedValue(); 92 assert(value <= 31 && "Invalid u5imm argument!"); 93 O << (unsigned int)value; 94 } 95 void printU6ImmOperand(const MachineInstr *MI, unsigned OpNo, 96 MVT::ValueType VT) { 97 unsigned char value = MI->getOperand(OpNo).getImmedValue(); 98 assert(value <= 63 && "Invalid u6imm argument!"); 99 O << (unsigned int)value; 100 } 101 void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo, 102 MVT::ValueType VT) { 103 O << (unsigned short)MI->getOperand(OpNo).getImmedValue(); 104 } 105 void printBranchOperand(const MachineInstr *MI, unsigned OpNo, 106 MVT::ValueType VT) { 107 printOp(MI->getOperand(OpNo)); 108 } 109 void printPICLabel(const MachineInstr *MI, unsigned OpNo, 110 MVT::ValueType VT) { 111 // FIXME: should probably be converted to cout.width and cout.fill 112 O << "\"L0000" << LabelNumber << "$pb\"\n"; 113 O << "\"L0000" << LabelNumber << "$pb\":"; 114 } 115 116 void printConstantPool(MachineConstantPool *MCP); 117 bool runOnMachineFunction(MachineFunction &F); 118 bool doFinalization(Module &M); 119 }; 120} // end of anonymous namespace 121 122/// createPPC32AsmPrinterPass - Returns a pass that prints the PPC 123/// assembly code for a MachineFunction to the given output stream, 124/// using the given target machine description. This should work 125/// regardless of whether the function is in SSA form or not. 126/// 127FunctionPass *llvm::createPPC32AsmPrinter(std::ostream &o, TargetMachine &tm) { 128 return new PPC32AsmPrinter(o, tm); 129} 130 131// Include the auto-generated portion of the assembly writer 132#include "PowerPCGenAsmWriter.inc" 133 134/// printConstantPool - Print to the current output stream assembly 135/// representations of the constants in the constant pool MCP. This is 136/// used to print out constants which have been "spilled to memory" by 137/// the code generator. 138/// 139void PPC32AsmPrinter::printConstantPool(MachineConstantPool *MCP) { 140 const std::vector<Constant*> &CP = MCP->getConstants(); 141 const TargetData &TD = TM.getTargetData(); 142 143 if (CP.empty()) return; 144 145 for (unsigned i = 0, e = CP.size(); i != e; ++i) { 146 O << "\t.const\n"; 147 emitAlignment(TD.getTypeAlignmentShift(CP[i]->getType())); 148 O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t" << CommentString 149 << *CP[i] << "\n"; 150 emitGlobalConstant(CP[i]); 151 } 152} 153 154/// runOnMachineFunction - This uses the printMachineInstruction() 155/// method to print assembly for each instruction. 156/// 157bool PPC32AsmPrinter::runOnMachineFunction(MachineFunction &MF) { 158 setupMachineFunction(MF); 159 O << "\n\n"; 160 161 // Print out constants referenced by the function 162 printConstantPool(MF.getConstantPool()); 163 164 // Print out labels for the function. 165 O << "\t.text\n"; 166 emitAlignment(2); 167 O << "\t.globl\t" << CurrentFnName << "\n"; 168 O << CurrentFnName << ":\n"; 169 170 // Print out code for the function. 171 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 172 I != E; ++I) { 173 // Print a label for the basic block. 174 O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t" 175 << CommentString << " " << I->getBasicBlock()->getName() << "\n"; 176 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); 177 II != E; ++II) { 178 // Print the assembly for the instruction. 179 O << "\t"; 180 printMachineInstruction(II); 181 } 182 } 183 ++LabelNumber; 184 185 // We didn't modify anything. 186 return false; 187} 188 189void PPC32AsmPrinter::printOp(const MachineOperand &MO, 190 bool LoadAddrOp /* = false */) { 191 const MRegisterInfo &RI = *TM.getRegisterInfo(); 192 int new_symbol; 193 194 switch (MO.getType()) { 195 case MachineOperand::MO_VirtualRegister: 196 if (Value *V = MO.getVRegValueOrNull()) { 197 O << "<" << V->getName() << ">"; 198 return; 199 } 200 // FALLTHROUGH 201 case MachineOperand::MO_MachineRegister: 202 case MachineOperand::MO_CCRegister: 203 O << LowercaseString(RI.get(MO.getReg()).Name); 204 return; 205 206 case MachineOperand::MO_SignExtendedImmed: 207 case MachineOperand::MO_UnextendedImmed: 208 std::cerr << "printOp() does not handle immediate values\n"; 209 abort(); 210 return; 211 212 case MachineOperand::MO_PCRelativeDisp: 213 std::cerr << "Shouldn't use addPCDisp() when building PPC MachineInstrs"; 214 abort(); 215 return; 216 217 case MachineOperand::MO_MachineBasicBlock: { 218 MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); 219 O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction()) 220 << "_" << MBBOp->getNumber() << "\t; " 221 << MBBOp->getBasicBlock()->getName(); 222 return; 223 } 224 225 case MachineOperand::MO_ConstantPoolIndex: 226 O << ".CPI" << CurrentFnName << "_" << MO.getConstantPoolIndex(); 227 return; 228 229 case MachineOperand::MO_ExternalSymbol: 230 O << MO.getSymbolName(); 231 return; 232 233 case MachineOperand::MO_GlobalAddress: { 234 GlobalValue *GV = MO.getGlobal(); 235 std::string Name = Mang->getValueName(GV); 236 237 // Dynamically-resolved functions need a stub for the function. Be 238 // wary however not to output $stub for external functions whose addresses 239 // are taken. Those should be emitted as $non_lazy_ptr below. 240 Function *F = dyn_cast<Function>(GV); 241 if (F && F->isExternal() && !LoadAddrOp && 242 getTM().CalledFunctions.count(F)) { 243 FnStubs.insert(Name); 244 O << "L" << Name << "$stub"; 245 return; 246 } 247 248 // External global variables need a non-lazily-resolved stub 249 if (GV->isExternal() && getTM().AddressTaken.count(GV)) { 250 GVStubs.insert(Name); 251 O << "L" << Name << "$non_lazy_ptr"; 252 return; 253 } 254 255 if (F && LoadAddrOp && getTM().AddressTaken.count(GV)) { 256 LinkOnceStubs.insert(Name); 257 O << "L" << Name << "$non_lazy_ptr"; 258 return; 259 } 260 261 O << Mang->getValueName(GV); 262 return; 263 } 264 265 default: 266 O << "<unknown operand type: " << MO.getType() << ">"; 267 return; 268 } 269} 270 271void PPC32AsmPrinter::printImmOp(const MachineOperand &MO, unsigned ArgType) { 272 int Imm = MO.getImmedValue(); 273 if (ArgType == PPCII::Simm16 || ArgType == PPCII::Disimm16) { 274 O << (short)Imm; 275 } else { 276 O << Imm; 277 } 278} 279 280/// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to 281/// the current output stream. 282/// 283void PPC32AsmPrinter::printMachineInstruction(const MachineInstr *MI) { 284 ++EmittedInsts; 285 if (printInstruction(MI)) 286 return; // Printer was automatically generated 287 288 unsigned Opcode = MI->getOpcode(); 289 const TargetInstrInfo &TII = *TM.getInstrInfo(); 290 const TargetInstrDescriptor &Desc = TII.get(Opcode); 291 unsigned i; 292 293 unsigned ArgCount = MI->getNumOperands(); 294 unsigned ArgType[] = { 295 (Desc.TSFlags >> PPCII::Arg0TypeShift) & PPCII::ArgTypeMask, 296 (Desc.TSFlags >> PPCII::Arg1TypeShift) & PPCII::ArgTypeMask, 297 (Desc.TSFlags >> PPCII::Arg2TypeShift) & PPCII::ArgTypeMask, 298 (Desc.TSFlags >> PPCII::Arg3TypeShift) & PPCII::ArgTypeMask, 299 (Desc.TSFlags >> PPCII::Arg4TypeShift) & PPCII::ArgTypeMask 300 }; 301 assert(((Desc.TSFlags & PPCII::VMX) == 0) && 302 "Instruction requires VMX support"); 303 assert(((Desc.TSFlags & PPCII::PPC64) == 0) && 304 "Instruction requires 64 bit support"); 305 306 O << TII.getName(Opcode) << " "; 307 if (Opcode == PPC::LOADHiAddr) { 308 printOp(MI->getOperand(0)); 309 O << ", "; 310 if (MI->getOperand(1).getReg() == PPC::R0) 311 O << "0"; 312 else 313 printOp(MI->getOperand(1)); 314 O << ", ha16(" ; 315 printOp(MI->getOperand(2), true /* LoadAddrOp */); 316 O << "-\"L0000" << LabelNumber << "$pb\")\n"; 317 } else if (ArgCount == 3 && (MI->getOperand(2).isConstantPoolIndex() 318 || MI->getOperand(2).isGlobalAddress())) { 319 printOp(MI->getOperand(0)); 320 O << ", lo16("; 321 printOp(MI->getOperand(2), true /* LoadAddrOp */); 322 O << "-\"L0000" << LabelNumber << "$pb\")"; 323 O << "("; 324 if (MI->getOperand(1).getReg() == PPC::R0) 325 O << "0"; 326 else 327 printOp(MI->getOperand(1)); 328 O << ")\n"; 329 } else if (ArgCount == 3 && ArgType[1] == PPCII::Disimm16) { 330 printOp(MI->getOperand(0)); 331 O << ", "; 332 printImmOp(MI->getOperand(1), ArgType[1]); 333 O << "("; 334 if (MI->getOperand(2).hasAllocatedReg() && 335 MI->getOperand(2).getReg() == PPC::R0) 336 O << "0"; 337 else 338 printOp(MI->getOperand(2)); 339 O << ")\n"; 340 } else { 341 for (i = 0; i < ArgCount; ++i) { 342 // addi and friends 343 if (i == 1 && ArgCount == 3 && ArgType[2] == PPCII::Simm16 && 344 MI->getOperand(1).hasAllocatedReg() && 345 MI->getOperand(1).getReg() == PPC::R0) { 346 O << "0"; 347 // for long branch support, bc $+8 348 } else if (i == 1 && ArgCount == 2 && MI->getOperand(1).isImmediate() && 349 TII.isBranch(MI->getOpcode())) { 350 O << "$+8"; 351 assert(8 == MI->getOperand(i).getImmedValue() 352 && "branch off PC not to pc+8?"); 353 //printOp(MI->getOperand(i)); 354 } else if (MI->getOperand(i).isImmediate()) { 355 printImmOp(MI->getOperand(i), ArgType[i]); 356 } else { 357 printOp(MI->getOperand(i)); 358 } 359 if (ArgCount - 1 == i) 360 O << "\n"; 361 else 362 O << ", "; 363 } 364 } 365 return; 366} 367 368// SwitchSection - Switch to the specified section of the executable if we are 369// not already in it! 370// 371static void SwitchSection(std::ostream &OS, std::string &CurSection, 372 const char *NewSection) { 373 if (CurSection != NewSection) { 374 CurSection = NewSection; 375 if (!CurSection.empty()) 376 OS << "\t" << NewSection << "\n"; 377 } 378} 379 380bool PPC32AsmPrinter::doFinalization(Module &M) { 381 const TargetData &TD = TM.getTargetData(); 382 std::string CurSection; 383 384 // Print out module-level global variables here. 385 for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I) 386 if (I->hasInitializer()) { // External global require no code 387 O << "\n\n"; 388 std::string name = Mang->getValueName(I); 389 Constant *C = I->getInitializer(); 390 unsigned Size = TD.getTypeSize(C->getType()); 391 unsigned Align = TD.getTypeAlignmentShift(C->getType()); 392 393 if (C->isNullValue() && /* FIXME: Verify correct */ 394 (I->hasInternalLinkage() || I->hasWeakLinkage())) { 395 SwitchSection(O, CurSection, ".data"); 396 if (I->hasInternalLinkage()) 397 O << ".lcomm " << name << "," << TD.getTypeSize(C->getType()) 398 << "," << Align; 399 else 400 O << ".comm " << name << "," << TD.getTypeSize(C->getType()); 401 O << "\t\t; "; 402 WriteAsOperand(O, I, true, true, &M); 403 O << "\n"; 404 } else { 405 switch (I->getLinkage()) { 406 case GlobalValue::LinkOnceLinkage: 407 O << ".section __TEXT,__textcoal_nt,coalesced,no_toc\n" 408 << ".weak_definition " << name << '\n' 409 << ".private_extern " << name << '\n' 410 << ".section __DATA,__datacoal_nt,coalesced,no_toc\n"; 411 LinkOnceStubs.insert(name); 412 break; 413 case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. 414 // Nonnull linkonce -> weak 415 O << "\t.weak " << name << "\n"; 416 SwitchSection(O, CurSection, ""); 417 O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"; 418 break; 419 case GlobalValue::AppendingLinkage: 420 // FIXME: appending linkage variables should go into a section of 421 // their name or something. For now, just emit them as external. 422 case GlobalValue::ExternalLinkage: 423 // If external or appending, declare as a global symbol 424 O << "\t.globl " << name << "\n"; 425 // FALL THROUGH 426 case GlobalValue::InternalLinkage: 427 SwitchSection(O, CurSection, ".data"); 428 break; 429 } 430 431 emitAlignment(Align); 432 O << name << ":\t\t\t\t; "; 433 WriteAsOperand(O, I, true, true, &M); 434 O << " = "; 435 WriteAsOperand(O, C, false, false, &M); 436 O << "\n"; 437 emitGlobalConstant(C); 438 } 439 } 440 441 // Output stubs for dynamically-linked functions 442 for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end(); 443 i != e; ++i) 444 { 445 O << ".data\n"; 446 O << ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"; 447 emitAlignment(2); 448 O << "L" << *i << "$stub:\n"; 449 O << "\t.indirect_symbol " << *i << "\n"; 450 O << "\tmflr r0\n"; 451 O << "\tbcl 20,31,L0$" << *i << "\n"; 452 O << "L0$" << *i << ":\n"; 453 O << "\tmflr r11\n"; 454 O << "\taddis r11,r11,ha16(L" << *i << "$lazy_ptr-L0$" << *i << ")\n"; 455 O << "\tmtlr r0\n"; 456 O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n"; 457 O << "\tmtctr r12\n"; 458 O << "\tbctr\n"; 459 O << ".data\n"; 460 O << ".lazy_symbol_pointer\n"; 461 O << "L" << *i << "$lazy_ptr:\n"; 462 O << "\t.indirect_symbol " << *i << "\n"; 463 O << "\t.long dyld_stub_binding_helper\n"; 464 } 465 466 O << "\n"; 467 468 // Output stubs for external global variables 469 if (GVStubs.begin() != GVStubs.end()) 470 O << ".data\n.non_lazy_symbol_pointer\n"; 471 for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end(); 472 i != e; ++i) { 473 O << "L" << *i << "$non_lazy_ptr:\n"; 474 O << "\t.indirect_symbol " << *i << "\n"; 475 O << "\t.long\t0\n"; 476 } 477 478 // Output stubs for link-once variables 479 if (LinkOnceStubs.begin() != LinkOnceStubs.end()) 480 O << ".data\n.align 2\n"; 481 for (std::set<std::string>::iterator i = LinkOnceStubs.begin(), 482 e = LinkOnceStubs.end(); i != e; ++i) { 483 O << "L" << *i << "$non_lazy_ptr:\n" 484 << "\t.long\t" << *i << '\n'; 485 } 486 487 AsmPrinter::doFinalization(M); 488 return false; // success 489} 490