PPCAsmPrinter.cpp revision a7217c824d512d6a80fbe97b82f4c2e15ec2a338
1//===-- PPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly --------=// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// 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 "PPC.h" 21#include "PPCPredicates.h" 22#include "PPCTargetMachine.h" 23#include "PPCSubtarget.h" 24#include "llvm/Analysis/DebugInfo.h" 25#include "llvm/Constants.h" 26#include "llvm/DerivedTypes.h" 27#include "llvm/Module.h" 28#include "llvm/Assembly/Writer.h" 29#include "llvm/CodeGen/AsmPrinter.h" 30#include "llvm/CodeGen/MachineFunctionPass.h" 31#include "llvm/CodeGen/MachineInstr.h" 32#include "llvm/CodeGen/MachineInstrBuilder.h" 33#include "llvm/CodeGen/MachineModuleInfoImpls.h" 34#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 35#include "llvm/MC/MCAsmInfo.h" 36#include "llvm/MC/MCContext.h" 37#include "llvm/MC/MCExpr.h" 38#include "llvm/MC/MCInst.h" 39#include "llvm/MC/MCSectionMachO.h" 40#include "llvm/MC/MCStreamer.h" 41#include "llvm/MC/MCSymbol.h" 42#include "llvm/Target/Mangler.h" 43#include "llvm/Target/TargetRegisterInfo.h" 44#include "llvm/Target/TargetInstrInfo.h" 45#include "llvm/Target/TargetOptions.h" 46#include "llvm/Target/TargetRegistry.h" 47#include "llvm/Support/CommandLine.h" 48#include "llvm/Support/Debug.h" 49#include "llvm/Support/MathExtras.h" 50#include "llvm/Support/ErrorHandling.h" 51#include "llvm/Support/raw_ostream.h" 52#include "llvm/ADT/StringExtras.h" 53#include "llvm/ADT/StringSet.h" 54#include "llvm/ADT/SmallString.h" 55#include "InstPrinter/PPCInstPrinter.h" 56using namespace llvm; 57 58// This option tells the asmprinter to use the new (experimental) MCInstPrinter 59// path. 60static cl::opt<bool> UseInstPrinter("enable-ppc-inst-printer", 61 cl::ReallyHidden 62 //, cl::init(true) 63 ); 64 65namespace { 66 class PPCAsmPrinter : public AsmPrinter { 67 protected: 68 DenseMap<MCSymbol*, MCSymbol*> TOC; 69 const PPCSubtarget &Subtarget; 70 uint64_t LabelID; 71 public: 72 explicit PPCAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 73 : AsmPrinter(TM, Streamer), 74 Subtarget(TM.getSubtarget<PPCSubtarget>()), LabelID(0) {} 75 76 virtual const char *getPassName() const { 77 return "PowerPC Assembly Printer"; 78 } 79 80 unsigned enumRegToMachineReg(unsigned enumReg) { 81 switch (enumReg) { 82 default: llvm_unreachable("Unhandled register!"); 83 case PPC::CR0: return 0; 84 case PPC::CR1: return 1; 85 case PPC::CR2: return 2; 86 case PPC::CR3: return 3; 87 case PPC::CR4: return 4; 88 case PPC::CR5: return 5; 89 case PPC::CR6: return 6; 90 case PPC::CR7: return 7; 91 } 92 llvm_unreachable(0); 93 } 94 95 /// printInstruction - This method is automatically generated by tablegen 96 /// from the instruction set description. This method returns true if the 97 /// machine instruction was sufficiently described to print it, otherwise it 98 /// returns false. 99 void printInstruction(const MachineInstr *MI, raw_ostream &O); 100 static const char *getRegisterName(unsigned RegNo); 101 102 103 virtual void EmitInstruction(const MachineInstr *MI); 104 void printOp(const MachineOperand &MO, raw_ostream &O); 105 106 /// stripRegisterPrefix - This method strips the character prefix from a 107 /// register name so that only the number is left. Used by for linux asm. 108 const char *stripRegisterPrefix(const char *RegName) { 109 switch (RegName[0]) { 110 case 'r': 111 case 'f': 112 case 'v': return RegName + 1; 113 case 'c': if (RegName[1] == 'r') return RegName + 2; 114 } 115 116 return RegName; 117 } 118 119 /// printRegister - Print register according to target requirements. 120 /// 121 void printRegister(const MachineOperand &MO, bool R0AsZero, raw_ostream &O){ 122 unsigned RegNo = MO.getReg(); 123 assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??"); 124 125 // If we should use 0 for R0. 126 if (R0AsZero && RegNo == PPC::R0) { 127 O << "0"; 128 return; 129 } 130 131 const char *RegName = getRegisterName(RegNo); 132 // Linux assembler (Others?) does not take register mnemonics. 133 // FIXME - What about special registers used in mfspr/mtspr? 134 if (!Subtarget.isDarwin()) RegName = stripRegisterPrefix(RegName); 135 O << RegName; 136 } 137 138 void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { 139 const MachineOperand &MO = MI->getOperand(OpNo); 140 if (MO.isReg()) { 141 printRegister(MO, false, O); 142 } else if (MO.isImm()) { 143 O << MO.getImm(); 144 } else { 145 printOp(MO, O); 146 } 147 } 148 149 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 150 unsigned AsmVariant, const char *ExtraCode, 151 raw_ostream &O); 152 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 153 unsigned AsmVariant, const char *ExtraCode, 154 raw_ostream &O); 155 156 157 void printS5ImmOperand(const MachineInstr *MI, unsigned OpNo, 158 raw_ostream &O) { 159 char value = MI->getOperand(OpNo).getImm(); 160 value = (value << (32-5)) >> (32-5); 161 O << (int)value; 162 } 163 void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo, 164 raw_ostream &O) { 165 unsigned char value = MI->getOperand(OpNo).getImm(); 166 assert(value <= 31 && "Invalid u5imm argument!"); 167 O << (unsigned int)value; 168 } 169 void printU6ImmOperand(const MachineInstr *MI, unsigned OpNo, 170 raw_ostream &O) { 171 unsigned char value = MI->getOperand(OpNo).getImm(); 172 assert(value <= 63 && "Invalid u6imm argument!"); 173 O << (unsigned int)value; 174 } 175 void printS16ImmOperand(const MachineInstr *MI, unsigned OpNo, 176 raw_ostream &O) { 177 O << (short)MI->getOperand(OpNo).getImm(); 178 } 179 void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo, 180 raw_ostream &O) { 181 O << (unsigned short)MI->getOperand(OpNo).getImm(); 182 } 183 void printS16X4ImmOperand(const MachineInstr *MI, unsigned OpNo, 184 raw_ostream &O) { 185 if (MI->getOperand(OpNo).isImm()) { 186 O << (short)(MI->getOperand(OpNo).getImm()*4); 187 } else { 188 O << "lo16("; 189 printOp(MI->getOperand(OpNo), O); 190 if (TM.getRelocationModel() == Reloc::PIC_) 191 O << "-\"L" << getFunctionNumber() << "$pb\")"; 192 else 193 O << ')'; 194 } 195 } 196 void printBranchOperand(const MachineInstr *MI, unsigned OpNo, 197 raw_ostream &O) { 198 // Branches can take an immediate operand. This is used by the branch 199 // selection pass to print $+8, an eight byte displacement from the PC. 200 if (MI->getOperand(OpNo).isImm()) { 201 O << "$+" << MI->getOperand(OpNo).getImm()*4; 202 } else { 203 printOp(MI->getOperand(OpNo), O); 204 } 205 } 206 void printCallOperand(const MachineInstr *MI, unsigned OpNo, 207 raw_ostream &O) { 208 const MachineOperand &MO = MI->getOperand(OpNo); 209 if (TM.getRelocationModel() != Reloc::Static) { 210 if (MO.isGlobal()) { 211 const GlobalValue *GV = MO.getGlobal(); 212 if (GV->isDeclaration() || GV->isWeakForLinker()) { 213 // Dynamically-resolved functions need a stub for the function. 214 MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$stub"); 215 MachineModuleInfoImpl::StubValueTy &StubSym = 216 MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym); 217 if (StubSym.getPointer() == 0) 218 StubSym = MachineModuleInfoImpl:: 219 StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); 220 O << *Sym; 221 return; 222 } 223 } 224 if (MO.isSymbol()) { 225 SmallString<128> TempNameStr; 226 TempNameStr += StringRef(MO.getSymbolName()); 227 TempNameStr += StringRef("$stub"); 228 229 MCSymbol *Sym = GetExternalSymbolSymbol(TempNameStr.str()); 230 MachineModuleInfoImpl::StubValueTy &StubSym = 231 MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym); 232 if (StubSym.getPointer() == 0) 233 StubSym = MachineModuleInfoImpl:: 234 StubValueTy(GetExternalSymbolSymbol(MO.getSymbolName()), true); 235 O << *Sym; 236 return; 237 } 238 } 239 240 printOp(MI->getOperand(OpNo), O); 241 } 242 void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo, 243 raw_ostream &O) { 244 O << (int)MI->getOperand(OpNo).getImm()*4; 245 } 246 void printPICLabel(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { 247 O << "\"L" << getFunctionNumber() << "$pb\"\n"; 248 O << "\"L" << getFunctionNumber() << "$pb\":"; 249 } 250 void printSymbolHi(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { 251 if (MI->getOperand(OpNo).isImm()) { 252 printS16ImmOperand(MI, OpNo, O); 253 } else { 254 if (Subtarget.isDarwin()) O << "ha16("; 255 printOp(MI->getOperand(OpNo), O); 256 if (TM.getRelocationModel() == Reloc::PIC_) 257 O << "-\"L" << getFunctionNumber() << "$pb\""; 258 if (Subtarget.isDarwin()) 259 O << ')'; 260 else 261 O << "@ha"; 262 } 263 } 264 void printSymbolLo(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { 265 if (MI->getOperand(OpNo).isImm()) { 266 printS16ImmOperand(MI, OpNo, O); 267 } else { 268 if (Subtarget.isDarwin()) O << "lo16("; 269 printOp(MI->getOperand(OpNo), O); 270 if (TM.getRelocationModel() == Reloc::PIC_) 271 O << "-\"L" << getFunctionNumber() << "$pb\""; 272 if (Subtarget.isDarwin()) 273 O << ')'; 274 else 275 O << "@l"; 276 } 277 } 278 void printcrbitm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { 279 unsigned CCReg = MI->getOperand(OpNo).getReg(); 280 unsigned RegNo = enumRegToMachineReg(CCReg); 281 O << (0x80 >> RegNo); 282 } 283 // The new addressing mode printers. 284 void printMemRegImm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { 285 printSymbolLo(MI, OpNo, O); 286 O << '('; 287 if (MI->getOperand(OpNo+1).isReg() && 288 MI->getOperand(OpNo+1).getReg() == PPC::R0) 289 O << "0"; 290 else 291 printOperand(MI, OpNo+1, O); 292 O << ')'; 293 } 294 void printMemRegImmShifted(const MachineInstr *MI, unsigned OpNo, 295 raw_ostream &O) { 296 if (MI->getOperand(OpNo).isImm()) 297 printS16X4ImmOperand(MI, OpNo, O); 298 else 299 printSymbolLo(MI, OpNo, O); 300 O << '('; 301 if (MI->getOperand(OpNo+1).isReg() && 302 MI->getOperand(OpNo+1).getReg() == PPC::R0) 303 O << "0"; 304 else 305 printOperand(MI, OpNo+1, O); 306 O << ')'; 307 } 308 309 void printMemRegReg(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { 310 // When used as the base register, r0 reads constant zero rather than 311 // the value contained in the register. For this reason, the darwin 312 // assembler requires that we print r0 as 0 (no r) when used as the base. 313 const MachineOperand &MO = MI->getOperand(OpNo); 314 printRegister(MO, true, O); 315 O << ", "; 316 printOperand(MI, OpNo+1, O); 317 } 318 319 void printTOCEntryLabel(const MachineInstr *MI, unsigned OpNo, 320 raw_ostream &O) { 321 const MachineOperand &MO = MI->getOperand(OpNo); 322 assert(MO.isGlobal()); 323 MCSymbol *Sym = Mang->getSymbol(MO.getGlobal()); 324 325 // Map symbol -> label of TOC entry. 326 MCSymbol *&TOCEntry = TOC[Sym]; 327 if (TOCEntry == 0) 328 TOCEntry = OutContext. 329 GetOrCreateSymbol(StringRef(MAI->getPrivateGlobalPrefix()) + 330 "C" + Twine(LabelID++)); 331 332 O << *TOCEntry << "@toc"; 333 } 334 335 void printPredicateOperand(const MachineInstr *MI, unsigned OpNo, 336 raw_ostream &O, const char *Modifier); 337 338 MachineLocation getDebugValueLocation(const MachineInstr *MI) const { 339 340 MachineLocation Location; 341 assert (MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); 342 // Frame address. Currently handles register +- offset only. 343 if (MI->getOperand(0).isReg() && MI->getOperand(2).isImm()) 344 Location.set(MI->getOperand(0).getReg(), MI->getOperand(2).getImm()); 345 else { 346 DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n"); 347 } 348 return Location; 349 } 350 }; 351 352 /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux 353 class PPCLinuxAsmPrinter : public PPCAsmPrinter { 354 public: 355 explicit PPCLinuxAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 356 : PPCAsmPrinter(TM, Streamer) {} 357 358 virtual const char *getPassName() const { 359 return "Linux PPC Assembly Printer"; 360 } 361 362 bool doFinalization(Module &M); 363 364 virtual void EmitFunctionEntryLabel(); 365 }; 366 367 /// PPCDarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac 368 /// OS X 369 class PPCDarwinAsmPrinter : public PPCAsmPrinter { 370 public: 371 explicit PPCDarwinAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 372 : PPCAsmPrinter(TM, Streamer) {} 373 374 virtual const char *getPassName() const { 375 return "Darwin PPC Assembly Printer"; 376 } 377 378 bool doFinalization(Module &M); 379 void EmitStartOfAsmFile(Module &M); 380 381 void EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs); 382 }; 383} // end of anonymous namespace 384 385// Include the auto-generated portion of the assembly writer 386#include "PPCGenAsmWriter.inc" 387 388void PPCAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) { 389 switch (MO.getType()) { 390 case MachineOperand::MO_Immediate: 391 llvm_unreachable("printOp() does not handle immediate values"); 392 393 case MachineOperand::MO_MachineBasicBlock: 394 O << *MO.getMBB()->getSymbol(); 395 return; 396 case MachineOperand::MO_JumpTableIndex: 397 O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() 398 << '_' << MO.getIndex(); 399 // FIXME: PIC relocation model 400 return; 401 case MachineOperand::MO_ConstantPoolIndex: 402 O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() 403 << '_' << MO.getIndex(); 404 return; 405 case MachineOperand::MO_BlockAddress: 406 O << *GetBlockAddressSymbol(MO.getBlockAddress()); 407 return; 408 case MachineOperand::MO_ExternalSymbol: { 409 // Computing the address of an external symbol, not calling it. 410 if (TM.getRelocationModel() == Reloc::Static) { 411 O << *GetExternalSymbolSymbol(MO.getSymbolName()); 412 return; 413 } 414 415 MCSymbol *NLPSym = 416 OutContext.GetOrCreateSymbol(StringRef(MAI->getGlobalPrefix())+ 417 MO.getSymbolName()+"$non_lazy_ptr"); 418 MachineModuleInfoImpl::StubValueTy &StubSym = 419 MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(NLPSym); 420 if (StubSym.getPointer() == 0) 421 StubSym = MachineModuleInfoImpl:: 422 StubValueTy(GetExternalSymbolSymbol(MO.getSymbolName()), true); 423 424 O << *NLPSym; 425 return; 426 } 427 case MachineOperand::MO_GlobalAddress: { 428 // Computing the address of a global symbol, not calling it. 429 const GlobalValue *GV = MO.getGlobal(); 430 MCSymbol *SymToPrint; 431 432 // External or weakly linked global variables need non-lazily-resolved stubs 433 if (TM.getRelocationModel() != Reloc::Static && 434 (GV->isDeclaration() || GV->isWeakForLinker())) { 435 if (!GV->hasHiddenVisibility()) { 436 SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 437 MachineModuleInfoImpl::StubValueTy &StubSym = 438 MMI->getObjFileInfo<MachineModuleInfoMachO>() 439 .getGVStubEntry(SymToPrint); 440 if (StubSym.getPointer() == 0) 441 StubSym = MachineModuleInfoImpl:: 442 StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); 443 } else if (GV->isDeclaration() || GV->hasCommonLinkage() || 444 GV->hasAvailableExternallyLinkage()) { 445 SymToPrint = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 446 447 MachineModuleInfoImpl::StubValueTy &StubSym = 448 MMI->getObjFileInfo<MachineModuleInfoMachO>(). 449 getHiddenGVStubEntry(SymToPrint); 450 if (StubSym.getPointer() == 0) 451 StubSym = MachineModuleInfoImpl:: 452 StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); 453 } else { 454 SymToPrint = Mang->getSymbol(GV); 455 } 456 } else { 457 SymToPrint = Mang->getSymbol(GV); 458 } 459 460 O << *SymToPrint; 461 462 printOffset(MO.getOffset(), O); 463 return; 464 } 465 466 default: 467 O << "<unknown operand type: " << MO.getType() << ">"; 468 return; 469 } 470} 471 472/// PrintAsmOperand - Print out an operand for an inline asm expression. 473/// 474bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 475 unsigned AsmVariant, 476 const char *ExtraCode, raw_ostream &O) { 477 // Does this asm operand have a single letter operand modifier? 478 if (ExtraCode && ExtraCode[0]) { 479 if (ExtraCode[1] != 0) return true; // Unknown modifier. 480 481 switch (ExtraCode[0]) { 482 default: return true; // Unknown modifier. 483 case 'c': // Don't print "$" before a global var name or constant. 484 // PPC never has a prefix. 485 printOperand(MI, OpNo, O); 486 return false; 487 case 'L': // Write second word of DImode reference. 488 // Verify that this operand has two consecutive registers. 489 if (!MI->getOperand(OpNo).isReg() || 490 OpNo+1 == MI->getNumOperands() || 491 !MI->getOperand(OpNo+1).isReg()) 492 return true; 493 ++OpNo; // Return the high-part. 494 break; 495 case 'I': 496 // Write 'i' if an integer constant, otherwise nothing. Used to print 497 // addi vs add, etc. 498 if (MI->getOperand(OpNo).isImm()) 499 O << "i"; 500 return false; 501 } 502 } 503 504 printOperand(MI, OpNo, O); 505 return false; 506} 507 508// At the moment, all inline asm memory operands are a single register. 509// In any case, the output of this routine should always be just one 510// assembler operand. 511 512bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 513 unsigned AsmVariant, 514 const char *ExtraCode, 515 raw_ostream &O) { 516 if (ExtraCode && ExtraCode[0]) 517 return true; // Unknown modifier. 518 assert (MI->getOperand(OpNo).isReg()); 519 O << "0("; 520 printOperand(MI, OpNo, O); 521 O << ")"; 522 return false; 523} 524 525void PPCAsmPrinter::printPredicateOperand(const MachineInstr *MI, unsigned OpNo, 526 raw_ostream &O, const char *Modifier){ 527 assert(Modifier && "Must specify 'cc' or 'reg' as predicate op modifier!"); 528 unsigned Code = MI->getOperand(OpNo).getImm(); 529 if (!strcmp(Modifier, "cc")) { 530 switch ((PPC::Predicate)Code) { 531 case PPC::PRED_ALWAYS: return; // Don't print anything for always. 532 case PPC::PRED_LT: O << "lt"; return; 533 case PPC::PRED_LE: O << "le"; return; 534 case PPC::PRED_EQ: O << "eq"; return; 535 case PPC::PRED_GE: O << "ge"; return; 536 case PPC::PRED_GT: O << "gt"; return; 537 case PPC::PRED_NE: O << "ne"; return; 538 case PPC::PRED_UN: O << "un"; return; 539 case PPC::PRED_NU: O << "nu"; return; 540 } 541 542 } else { 543 assert(!strcmp(Modifier, "reg") && 544 "Need to specify 'cc' or 'reg' as predicate op modifier!"); 545 // Don't print the register for 'always'. 546 if (Code == PPC::PRED_ALWAYS) return; 547 printOperand(MI, OpNo+1, O); 548 } 549} 550 551 552/// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to 553/// the current output stream. 554/// 555void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { 556 if (UseInstPrinter) { 557 // Lower multi-instruction pseudo operations. 558 switch (MI->getOpcode()) { 559 default: break; 560 // TODO: implement me. 561 } 562 563 MCInst TmpInst; 564 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); 565 OutStreamer.EmitInstruction(TmpInst); 566 return; 567 } 568 569 570 SmallString<128> Str; 571 raw_svector_ostream O(Str); 572 573 if (MI->getOpcode() == TargetOpcode::DBG_VALUE) { 574 unsigned NOps = MI->getNumOperands(); 575 assert(NOps==4); 576 O << '\t' << MAI->getCommentString() << "DEBUG_VALUE: "; 577 // cast away const; DIetc do not take const operands for some reason. 578 DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata())); 579 O << V.getName(); 580 O << " <- "; 581 // Frame address. Currently handles register +- offset only. 582 assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm()); 583 O << '['; printOperand(MI, 0, O); O << '+'; printOperand(MI, 1, O); 584 O << ']'; 585 O << "+"; 586 printOperand(MI, NOps-2, O); 587 OutStreamer.EmitRawText(O.str()); 588 return; 589 } 590 // Check for slwi/srwi mnemonics. 591 if (MI->getOpcode() == PPC::RLWINM) { 592 unsigned char SH = MI->getOperand(2).getImm(); 593 unsigned char MB = MI->getOperand(3).getImm(); 594 unsigned char ME = MI->getOperand(4).getImm(); 595 bool useSubstituteMnemonic = false; 596 if (SH <= 31 && MB == 0 && ME == (31-SH)) { 597 O << "\tslwi "; useSubstituteMnemonic = true; 598 } 599 if (SH <= 31 && MB == (32-SH) && ME == 31) { 600 O << "\tsrwi "; useSubstituteMnemonic = true; 601 SH = 32-SH; 602 } 603 if (useSubstituteMnemonic) { 604 printOperand(MI, 0, O); 605 O << ", "; 606 printOperand(MI, 1, O); 607 O << ", " << (unsigned int)SH; 608 OutStreamer.EmitRawText(O.str()); 609 return; 610 } 611 } 612 613 if ((MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) && 614 MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) { 615 O << "\tmr "; 616 printOperand(MI, 0, O); 617 O << ", "; 618 printOperand(MI, 1, O); 619 OutStreamer.EmitRawText(O.str()); 620 return; 621 } 622 623 if (MI->getOpcode() == PPC::RLDICR) { 624 unsigned char SH = MI->getOperand(2).getImm(); 625 unsigned char ME = MI->getOperand(3).getImm(); 626 // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH 627 if (63-SH == ME) { 628 O << "\tsldi "; 629 printOperand(MI, 0, O); 630 O << ", "; 631 printOperand(MI, 1, O); 632 O << ", " << (unsigned int)SH; 633 OutStreamer.EmitRawText(O.str()); 634 return; 635 } 636 } 637 638 printInstruction(MI, O); 639 OutStreamer.EmitRawText(O.str()); 640} 641 642void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() { 643 if (!Subtarget.isPPC64()) // linux/ppc32 - Normal entry label. 644 return AsmPrinter::EmitFunctionEntryLabel(); 645 646 // Emit an official procedure descriptor. 647 // FIXME 64-bit SVR4: Use MCSection here! 648 OutStreamer.EmitRawText(StringRef("\t.section\t\".opd\",\"aw\"")); 649 OutStreamer.EmitRawText(StringRef("\t.align 3")); 650 OutStreamer.EmitLabel(CurrentFnSym); 651 OutStreamer.EmitRawText("\t.quad .L." + Twine(CurrentFnSym->getName()) + 652 ",.TOC.@tocbase"); 653 OutStreamer.EmitRawText(StringRef("\t.previous")); 654 OutStreamer.EmitRawText(".L." + Twine(CurrentFnSym->getName()) + ":"); 655} 656 657 658bool PPCLinuxAsmPrinter::doFinalization(Module &M) { 659 const TargetData *TD = TM.getTargetData(); 660 661 bool isPPC64 = TD->getPointerSizeInBits() == 64; 662 663 if (isPPC64 && !TOC.empty()) { 664 // FIXME 64-bit SVR4: Use MCSection here? 665 OutStreamer.EmitRawText(StringRef("\t.section\t\".toc\",\"aw\"")); 666 667 // FIXME: This is nondeterminstic! 668 for (DenseMap<MCSymbol*, MCSymbol*>::iterator I = TOC.begin(), 669 E = TOC.end(); I != E; ++I) { 670 OutStreamer.EmitLabel(I->second); 671 OutStreamer.EmitRawText("\t.tc " + Twine(I->first->getName()) + 672 "[TC]," + I->first->getName()); 673 } 674 } 675 676 return AsmPrinter::doFinalization(M); 677} 678 679void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) { 680 static const char *const CPUDirectives[] = { 681 "", 682 "ppc", 683 "ppc601", 684 "ppc602", 685 "ppc603", 686 "ppc7400", 687 "ppc750", 688 "ppc970", 689 "ppc64" 690 }; 691 692 unsigned Directive = Subtarget.getDarwinDirective(); 693 if (Subtarget.isGigaProcessor() && Directive < PPC::DIR_970) 694 Directive = PPC::DIR_970; 695 if (Subtarget.hasAltivec() && Directive < PPC::DIR_7400) 696 Directive = PPC::DIR_7400; 697 if (Subtarget.isPPC64() && Directive < PPC::DIR_970) 698 Directive = PPC::DIR_64; 699 assert(Directive <= PPC::DIR_64 && "Directive out of range."); 700 OutStreamer.EmitRawText("\t.machine " + Twine(CPUDirectives[Directive])); 701 702 // Prime text sections so they are adjacent. This reduces the likelihood a 703 // large data or debug section causes a branch to exceed 16M limit. 704 const TargetLoweringObjectFileMachO &TLOFMacho = 705 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); 706 OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection()); 707 if (TM.getRelocationModel() == Reloc::PIC_) { 708 OutStreamer.SwitchSection( 709 OutContext.getMachOSection("__TEXT", "__picsymbolstub1", 710 MCSectionMachO::S_SYMBOL_STUBS | 711 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 712 32, SectionKind::getText())); 713 } else if (TM.getRelocationModel() == Reloc::DynamicNoPIC) { 714 OutStreamer.SwitchSection( 715 OutContext.getMachOSection("__TEXT","__symbol_stub1", 716 MCSectionMachO::S_SYMBOL_STUBS | 717 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 718 16, SectionKind::getText())); 719 } 720 OutStreamer.SwitchSection(getObjFileLowering().getTextSection()); 721} 722 723static MCSymbol *GetLazyPtr(MCSymbol *Sym, MCContext &Ctx) { 724 // Remove $stub suffix, add $lazy_ptr. 725 SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end()-5); 726 TmpStr += "$lazy_ptr"; 727 return Ctx.GetOrCreateSymbol(TmpStr.str()); 728} 729 730static MCSymbol *GetAnonSym(MCSymbol *Sym, MCContext &Ctx) { 731 // Add $tmp suffix to $stub, yielding $stub$tmp. 732 SmallString<128> TmpStr(Sym->getName().begin(), Sym->getName().end()); 733 TmpStr += "$tmp"; 734 return Ctx.GetOrCreateSymbol(TmpStr.str()); 735} 736 737void PPCDarwinAsmPrinter:: 738EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { 739 bool isPPC64 = TM.getTargetData()->getPointerSizeInBits() == 64; 740 741 const TargetLoweringObjectFileMachO &TLOFMacho = 742 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); 743 744 // .lazy_symbol_pointer 745 const MCSection *LSPSection = TLOFMacho.getLazySymbolPointerSection(); 746 747 // Output stubs for dynamically-linked functions 748 if (TM.getRelocationModel() == Reloc::PIC_) { 749 const MCSection *StubSection = 750 OutContext.getMachOSection("__TEXT", "__picsymbolstub1", 751 MCSectionMachO::S_SYMBOL_STUBS | 752 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 753 32, SectionKind::getText()); 754 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 755 OutStreamer.SwitchSection(StubSection); 756 EmitAlignment(4); 757 758 MCSymbol *Stub = Stubs[i].first; 759 MCSymbol *RawSym = Stubs[i].second.getPointer(); 760 MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); 761 MCSymbol *AnonSymbol = GetAnonSym(Stub, OutContext); 762 763 OutStreamer.EmitLabel(Stub); 764 OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); 765 // FIXME: MCize this. 766 OutStreamer.EmitRawText(StringRef("\tmflr r0")); 767 OutStreamer.EmitRawText("\tbcl 20,31," + Twine(AnonSymbol->getName())); 768 OutStreamer.EmitLabel(AnonSymbol); 769 OutStreamer.EmitRawText(StringRef("\tmflr r11")); 770 OutStreamer.EmitRawText("\taddis r11,r11,ha16("+Twine(LazyPtr->getName())+ 771 "-" + AnonSymbol->getName() + ")"); 772 OutStreamer.EmitRawText(StringRef("\tmtlr r0")); 773 774 if (isPPC64) 775 OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) + 776 "-" + AnonSymbol->getName() + ")(r11)"); 777 else 778 OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) + 779 "-" + AnonSymbol->getName() + ")(r11)"); 780 OutStreamer.EmitRawText(StringRef("\tmtctr r12")); 781 OutStreamer.EmitRawText(StringRef("\tbctr")); 782 783 OutStreamer.SwitchSection(LSPSection); 784 OutStreamer.EmitLabel(LazyPtr); 785 OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); 786 787 if (isPPC64) 788 OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper")); 789 else 790 OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper")); 791 } 792 OutStreamer.AddBlankLine(); 793 return; 794 } 795 796 const MCSection *StubSection = 797 OutContext.getMachOSection("__TEXT","__symbol_stub1", 798 MCSectionMachO::S_SYMBOL_STUBS | 799 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 800 16, SectionKind::getText()); 801 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 802 MCSymbol *Stub = Stubs[i].first; 803 MCSymbol *RawSym = Stubs[i].second.getPointer(); 804 MCSymbol *LazyPtr = GetLazyPtr(Stub, OutContext); 805 806 OutStreamer.SwitchSection(StubSection); 807 EmitAlignment(4); 808 OutStreamer.EmitLabel(Stub); 809 OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); 810 OutStreamer.EmitRawText("\tlis r11,ha16(" + Twine(LazyPtr->getName()) +")"); 811 if (isPPC64) 812 OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) + 813 ")(r11)"); 814 else 815 OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) + 816 ")(r11)"); 817 OutStreamer.EmitRawText(StringRef("\tmtctr r12")); 818 OutStreamer.EmitRawText(StringRef("\tbctr")); 819 OutStreamer.SwitchSection(LSPSection); 820 OutStreamer.EmitLabel(LazyPtr); 821 OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); 822 823 if (isPPC64) 824 OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper")); 825 else 826 OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper")); 827 } 828 829 OutStreamer.AddBlankLine(); 830} 831 832 833bool PPCDarwinAsmPrinter::doFinalization(Module &M) { 834 bool isPPC64 = TM.getTargetData()->getPointerSizeInBits() == 64; 835 836 // Darwin/PPC always uses mach-o. 837 const TargetLoweringObjectFileMachO &TLOFMacho = 838 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); 839 MachineModuleInfoMachO &MMIMacho = 840 MMI->getObjFileInfo<MachineModuleInfoMachO>(); 841 842 MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetFnStubList(); 843 if (!Stubs.empty()) 844 EmitFunctionStubs(Stubs); 845 846 if (MAI->doesSupportExceptionHandling() && MMI) { 847 // Add the (possibly multiple) personalities to the set of global values. 848 // Only referenced functions get into the Personalities list. 849 const std::vector<const Function*> &Personalities = MMI->getPersonalities(); 850 for (std::vector<const Function*>::const_iterator I = Personalities.begin(), 851 E = Personalities.end(); I != E; ++I) { 852 if (*I) { 853 MCSymbol *NLPSym = GetSymbolWithGlobalValueBase(*I, "$non_lazy_ptr"); 854 MachineModuleInfoImpl::StubValueTy &StubSym = 855 MMIMacho.getGVStubEntry(NLPSym); 856 StubSym = MachineModuleInfoImpl::StubValueTy(Mang->getSymbol(*I), true); 857 } 858 } 859 } 860 861 // Output stubs for dynamically-linked functions. 862 Stubs = MMIMacho.GetGVStubList(); 863 864 // Output macho stubs for external and common global variables. 865 if (!Stubs.empty()) { 866 // Switch with ".non_lazy_symbol_pointer" directive. 867 OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); 868 EmitAlignment(isPPC64 ? 3 : 2); 869 870 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 871 // L_foo$stub: 872 OutStreamer.EmitLabel(Stubs[i].first); 873 // .indirect_symbol _foo 874 MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second; 875 OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol); 876 877 if (MCSym.getInt()) 878 // External to current translation unit. 879 OutStreamer.EmitIntValue(0, isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/); 880 else 881 // Internal to current translation unit. 882 // 883 // When we place the LSDA into the TEXT section, the type info pointers 884 // need to be indirect and pc-rel. We accomplish this by using NLPs. 885 // However, sometimes the types are local to the file. So we need to 886 // fill in the value for the NLP in those cases. 887 OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(), 888 OutContext), 889 isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/); 890 } 891 892 Stubs.clear(); 893 OutStreamer.AddBlankLine(); 894 } 895 896 Stubs = MMIMacho.GetHiddenGVStubList(); 897 if (!Stubs.empty()) { 898 OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); 899 EmitAlignment(isPPC64 ? 3 : 2); 900 901 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 902 // L_foo$stub: 903 OutStreamer.EmitLabel(Stubs[i].first); 904 // .long _foo 905 OutStreamer.EmitValue(MCSymbolRefExpr:: 906 Create(Stubs[i].second.getPointer(), 907 OutContext), 908 isPPC64 ? 8 : 4/*size*/, 0/*addrspace*/); 909 } 910 911 Stubs.clear(); 912 OutStreamer.AddBlankLine(); 913 } 914 915 // Funny Darwin hack: This flag tells the linker that no global symbols 916 // contain code that falls through to other global symbols (e.g. the obvious 917 // implementation of multiple entry points). If this doesn't occur, the 918 // linker can safely perform dead code stripping. Since LLVM never generates 919 // code that does this, it is always safe to set. 920 OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); 921 922 return AsmPrinter::doFinalization(M); 923} 924 925/// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code 926/// for a MachineFunction to the given output stream, in a format that the 927/// Darwin assembler can deal with. 928/// 929static AsmPrinter *createPPCAsmPrinterPass(TargetMachine &tm, 930 MCStreamer &Streamer) { 931 const PPCSubtarget *Subtarget = &tm.getSubtarget<PPCSubtarget>(); 932 933 if (Subtarget->isDarwin()) 934 return new PPCDarwinAsmPrinter(tm, Streamer); 935 return new PPCLinuxAsmPrinter(tm, Streamer); 936} 937 938static MCInstPrinter *createPPCMCInstPrinter(const Target &T, 939 unsigned SyntaxVariant, 940 const MCAsmInfo &MAI) { 941 return new PPCInstPrinter(MAI, SyntaxVariant); 942} 943 944 945// Force static initialization. 946extern "C" void LLVMInitializePowerPCAsmPrinter() { 947 TargetRegistry::RegisterAsmPrinter(ThePPC32Target, createPPCAsmPrinterPass); 948 TargetRegistry::RegisterAsmPrinter(ThePPC64Target, createPPCAsmPrinterPass); 949 950 TargetRegistry::RegisterMCInstPrinter(ThePPC32Target, createPPCMCInstPrinter); 951 TargetRegistry::RegisterMCInstPrinter(ThePPC32Target, createPPCMCInstPrinter); 952} 953