PPCAsmPrinter.cpp revision 72b286b0a0f8987bc247ae052ac86008c553e9ae
1//===-- PowerPCAsmPrinter.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 "PowerPCTargetMachine.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/MathExtras.h" 33#include "llvm/Support/CommandLine.h" 34#include "llvm/Support/Debug.h" 35#include "llvm/Target/MRegisterInfo.h" 36#include "llvm/Target/TargetInstrInfo.h" 37#include "llvm/ADT/Statistic.h" 38#include "llvm/ADT/StringExtras.h" 39#include <set> 40using namespace llvm; 41 42namespace { 43 Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed"); 44 45 struct PowerPCAsmPrinter : public AsmPrinter { 46 std::set<std::string> FnStubs, GVStubs, LinkOnceStubs; 47 48 PowerPCAsmPrinter(std::ostream &O, TargetMachine &TM) 49 : AsmPrinter(O, TM), LabelNumber(0) {} 50 51 /// Unique incrementer for label values for referencing Global values. 52 /// 53 unsigned LabelNumber; 54 55 virtual const char *getPassName() const { 56 return "PowerPC Assembly Printer"; 57 } 58 59 PowerPCTargetMachine &getTM() { 60 return static_cast<PowerPCTargetMachine&>(TM); 61 } 62 63 /// 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 69 void printMachineInstruction(const MachineInstr *MI); 70 void printOp(const MachineOperand &MO, bool IsCallOp = false); 71 72 void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){ 73 const MachineOperand &MO = MI->getOperand(OpNo); 74 if (MO.getType() == MachineOperand::MO_MachineRegister) { 75 assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??"); 76 O << LowercaseString(TM.getRegisterInfo()->get(MO.getReg()).Name); 77 } else if (MO.isImmediate()) { 78 O << MO.getImmedValue(); 79 } else { 80 printOp(MO); 81 } 82 } 83 84 void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo, 85 MVT::ValueType VT) { 86 unsigned char value = MI->getOperand(OpNo).getImmedValue(); 87 assert(value <= 31 && "Invalid u5imm argument!"); 88 O << (unsigned int)value; 89 } 90 void printU6ImmOperand(const MachineInstr *MI, unsigned OpNo, 91 MVT::ValueType VT) { 92 unsigned char value = MI->getOperand(OpNo).getImmedValue(); 93 assert(value <= 63 && "Invalid u6imm argument!"); 94 O << (unsigned int)value; 95 } 96 void printS16ImmOperand(const MachineInstr *MI, unsigned OpNo, 97 MVT::ValueType VT) { 98 O << (short)MI->getOperand(OpNo).getImmedValue(); 99 } 100 void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo, 101 MVT::ValueType VT) { 102 O << (unsigned short)MI->getOperand(OpNo).getImmedValue(); 103 } 104 void printBranchOperand(const MachineInstr *MI, unsigned OpNo, 105 MVT::ValueType VT) { 106 // Branches can take an immediate operand. This is used by the branch 107 // selection pass to print $+8, an eight byte displacement from the PC. 108 if (MI->getOperand(OpNo).isImmediate()) { 109 O << "$+" << MI->getOperand(OpNo).getImmedValue(); 110 } else { 111 printOp(MI->getOperand(OpNo), 112 TM.getInstrInfo()->isCall(MI->getOpcode())); 113 } 114 } 115 void printPICLabel(const MachineInstr *MI, unsigned OpNo, 116 MVT::ValueType VT) { 117 // FIXME: should probably be converted to cout.width and cout.fill 118 O << "\"L0000" << LabelNumber << "$pb\"\n"; 119 O << "\"L0000" << LabelNumber << "$pb\":"; 120 } 121 void printSymbolHi(const MachineInstr *MI, unsigned OpNo, 122 MVT::ValueType VT) { 123 O << "ha16("; 124 printOp(MI->getOperand(OpNo)); 125 O << "-\"L0000" << LabelNumber << "$pb\")"; 126 } 127 void printSymbolLo(const MachineInstr *MI, unsigned OpNo, 128 MVT::ValueType VT) { 129 // FIXME: Because LFS, LFD, and LWZ can be used either with a s16imm or 130 // a lo16 of a global or constant pool operand, we must handle both here. 131 // this isn't a great design, but it works for now. 132 if (MI->getOperand(OpNo).isImmediate()) { 133 O << (short)MI->getOperand(OpNo).getImmedValue(); 134 } else { 135 O << "lo16("; 136 printOp(MI->getOperand(OpNo)); 137 O << "-\"L0000" << LabelNumber << "$pb\")"; 138 } 139 } 140 void printcrbit(const MachineInstr *MI, unsigned OpNo, 141 MVT::ValueType VT) { 142 unsigned char value = MI->getOperand(OpNo).getImmedValue(); 143 assert(value <= 3 && "Invalid crbit argument!"); 144 unsigned RegNo, CCReg = MI->getOperand(OpNo-1).getReg(); 145 switch (CCReg) { 146 case PPC::CR0: RegNo = 0; break; 147 case PPC::CR1: RegNo = 1; break; 148 case PPC::CR2: RegNo = 2; break; 149 case PPC::CR3: RegNo = 3; break; 150 case PPC::CR4: RegNo = 4; break; 151 case PPC::CR5: RegNo = 5; break; 152 case PPC::CR6: RegNo = 6; break; 153 case PPC::CR7: RegNo = 7; break; 154 default: 155 std::cerr << "Unhandled reg in enumRegToRealReg!\n"; 156 abort(); 157 } 158 O << 4 * RegNo + value; 159 } 160 161 virtual void printConstantPool(MachineConstantPool *MCP) = 0; 162 virtual bool runOnMachineFunction(MachineFunction &F) = 0; 163 virtual bool doFinalization(Module &M) = 0; 164 }; 165 166 /// DarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac OS 167 /// X 168 /// 169 struct DarwinAsmPrinter : public PowerPCAsmPrinter { 170 171 DarwinAsmPrinter(std::ostream &O, TargetMachine &TM) 172 : PowerPCAsmPrinter(O, TM) { 173 CommentString = ";"; 174 GlobalPrefix = "_"; 175 ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. 176 Data64bitsDirective = 0; // we can't emit a 64-bit unit 177 AlignmentIsInBytes = false; // Alignment is by power of 2. 178 } 179 180 virtual const char *getPassName() const { 181 return "Darwin PPC Assembly Printer"; 182 } 183 184 void printConstantPool(MachineConstantPool *MCP); 185 bool runOnMachineFunction(MachineFunction &F); 186 bool doFinalization(Module &M); 187 }; 188 189 /// AIXAsmPrinter - PowerPC assembly printer, customized for AIX 190 /// 191 struct AIXAsmPrinter : public PowerPCAsmPrinter { 192 /// Map for labels corresponding to global variables 193 /// 194 std::map<const GlobalVariable*,std::string> GVToLabelMap; 195 196 AIXAsmPrinter(std::ostream &O, TargetMachine &TM) 197 : PowerPCAsmPrinter(O, TM) { 198 CommentString = "#"; 199 GlobalPrefix = "_"; 200 ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. 201 Data64bitsDirective = 0; // we can't emit a 64-bit unit 202 AlignmentIsInBytes = false; // Alignment is by power of 2. 203 } 204 205 virtual const char *getPassName() const { 206 return "AIX PPC Assembly Printer"; 207 } 208 209 void printConstantPool(MachineConstantPool *MCP); 210 bool runOnMachineFunction(MachineFunction &F); 211 bool doInitialization(Module &M); 212 bool doFinalization(Module &M); 213 }; 214} // end of anonymous namespace 215 216// SwitchSection - Switch to the specified section of the executable if we are 217// not already in it! 218// 219static void SwitchSection(std::ostream &OS, std::string &CurSection, 220 const char *NewSection) { 221 if (CurSection != NewSection) { 222 CurSection = NewSection; 223 if (!CurSection.empty()) 224 OS << "\t" << NewSection << "\n"; 225 } 226} 227 228/// isStringCompatible - Can we treat the specified array as a string? 229/// Only if it is an array of ubytes or non-negative sbytes. 230/// 231static bool isStringCompatible(const ConstantArray *CVA) { 232 const Type *ETy = cast<ArrayType>(CVA->getType())->getElementType(); 233 if (ETy == Type::UByteTy) return true; 234 if (ETy != Type::SByteTy) return false; 235 236 for (unsigned i = 0; i < CVA->getNumOperands(); ++i) 237 if (cast<ConstantSInt>(CVA->getOperand(i))->getValue() < 0) 238 return false; 239 240 return true; 241} 242 243/// toOctal - Convert the low order bits of X into an octal digit. 244/// 245static inline char toOctal(int X) { 246 return (X&7)+'0'; 247} 248 249// Possible states while outputting ASCII strings 250namespace { 251 enum StringSection { 252 None, 253 Alpha, 254 Numeric 255 }; 256} 257 258/// SwitchStringSection - manage the changes required to output bytes as 259/// characters in a string vs. numeric decimal values 260/// 261static inline void SwitchStringSection(std::ostream &O, StringSection NewSect, 262 StringSection &Current) { 263 if (Current == None) { 264 if (NewSect == Alpha) 265 O << "\t.byte \""; 266 else if (NewSect == Numeric) 267 O << "\t.byte "; 268 } else if (Current == Alpha) { 269 if (NewSect == None) 270 O << "\""; 271 else if (NewSect == Numeric) 272 O << "\"\n" 273 << "\t.byte "; 274 } else if (Current == Numeric) { 275 if (NewSect == Alpha) 276 O << '\n' 277 << "\t.byte \""; 278 else if (NewSect == Numeric) 279 O << ", "; 280 } 281 282 Current = NewSect; 283} 284 285/// getAsCString - Return the specified array as a C compatible 286/// string, only if the predicate isStringCompatible is true. 287/// 288static void printAsCString(std::ostream &O, const ConstantArray *CVA) { 289 assert(isStringCompatible(CVA) && "Array is not string compatible!"); 290 291 if (CVA->getNumOperands() == 0) 292 return; 293 294 StringSection Current = None; 295 for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i) { 296 unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue(); 297 if (C == '"') { 298 SwitchStringSection(O, Alpha, Current); 299 O << "\"\""; 300 } else if (isprint(C)) { 301 SwitchStringSection(O, Alpha, Current); 302 O << C; 303 } else { 304 SwitchStringSection(O, Numeric, Current); 305 O << utostr((unsigned)C); 306 } 307 } 308 SwitchStringSection(O, None, Current); 309 O << '\n'; 310} 311 312/// createDarwinAsmPrinterPass - Returns a pass that prints the PPC assembly 313/// code for a MachineFunction to the given output stream, in a format that the 314/// Darwin assembler can deal with. 315/// 316FunctionPass *llvm::createDarwinAsmPrinter(std::ostream &o, TargetMachine &tm) { 317 return new DarwinAsmPrinter(o, tm); 318} 319 320/// createAIXAsmPrinterPass - Returns a pass that prints the PPC assembly code 321/// for a MachineFunction to the given output stream, in a format that the 322/// AIX 5L assembler can deal with. 323/// 324FunctionPass *llvm::createAIXAsmPrinter(std::ostream &o, TargetMachine &tm) { 325 return new AIXAsmPrinter(o, tm); 326} 327 328// Include the auto-generated portion of the assembly writer 329#include "PowerPCGenAsmWriter.inc" 330 331void PowerPCAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) { 332 const MRegisterInfo &RI = *TM.getRegisterInfo(); 333 int new_symbol; 334 335 switch (MO.getType()) { 336 case MachineOperand::MO_VirtualRegister: 337 if (Value *V = MO.getVRegValueOrNull()) { 338 O << "<" << V->getName() << ">"; 339 return; 340 } 341 // FALLTHROUGH 342 case MachineOperand::MO_MachineRegister: 343 case MachineOperand::MO_CCRegister: 344 O << LowercaseString(RI.get(MO.getReg()).Name); 345 return; 346 347 case MachineOperand::MO_SignExtendedImmed: 348 case MachineOperand::MO_UnextendedImmed: 349 std::cerr << "printOp() does not handle immediate values\n"; 350 abort(); 351 return; 352 353 case MachineOperand::MO_PCRelativeDisp: 354 std::cerr << "Shouldn't use addPCDisp() when building PPC MachineInstrs"; 355 abort(); 356 return; 357 358 case MachineOperand::MO_MachineBasicBlock: { 359 MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); 360 O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction()) 361 << "_" << MBBOp->getNumber() << "\t; " 362 << MBBOp->getBasicBlock()->getName(); 363 return; 364 } 365 366 case MachineOperand::MO_ConstantPoolIndex: 367 O << ".CPI" << CurrentFnName << "_" << MO.getConstantPoolIndex(); 368 return; 369 370 case MachineOperand::MO_ExternalSymbol: 371 if (IsCallOp) { 372 std::string Name(GlobalPrefix); Name += MO.getSymbolName(); 373 FnStubs.insert(Name); 374 O << "L" << Name << "$stub"; 375 return; 376 } 377 O << GlobalPrefix << MO.getSymbolName(); 378 return; 379 380 case MachineOperand::MO_GlobalAddress: { 381 GlobalValue *GV = MO.getGlobal(); 382 std::string Name = Mang->getValueName(GV); 383 384 // Dynamically-resolved functions need a stub for the function. Be 385 // wary however not to output $stub for external functions whose addresses 386 // are taken. Those should be emitted as $non_lazy_ptr below. 387 Function *F = dyn_cast<Function>(GV); 388 if (F && IsCallOp && F->isExternal()) { 389 FnStubs.insert(Name); 390 O << "L" << Name << "$stub"; 391 return; 392 } 393 394 // External or weakly linked global variables need non-lazily-resolved stubs 395 if ((GV->isExternal() || GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())){ 396 if (GV->hasLinkOnceLinkage()) 397 LinkOnceStubs.insert(Name); 398 else 399 GVStubs.insert(Name); 400 O << "L" << Name << "$non_lazy_ptr"; 401 return; 402 } 403 404 O << Mang->getValueName(GV); 405 return; 406 } 407 408 default: 409 O << "<unknown operand type: " << MO.getType() << ">"; 410 return; 411 } 412} 413 414/// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to 415/// the current output stream. 416/// 417void PowerPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) { 418 ++EmittedInsts; 419 // Check for slwi/srwi mnemonics. 420 if (MI->getOpcode() == PPC::RLWINM) { 421 bool FoundMnemonic = false; 422 unsigned char SH = MI->getOperand(2).getImmedValue(); 423 unsigned char MB = MI->getOperand(3).getImmedValue(); 424 unsigned char ME = MI->getOperand(4).getImmedValue(); 425 if (SH <= 31 && MB == 0 && ME == (31-SH)) { 426 O << "slwi "; FoundMnemonic = true; 427 } 428 if (SH <= 31 && MB == (32-SH) && ME == 31) { 429 O << "srwi "; FoundMnemonic = true; 430 SH = 32-SH; 431 } 432 if (FoundMnemonic) { 433 printOperand(MI, 0, MVT::i64); 434 O << ", "; 435 printOperand(MI, 1, MVT::i64); 436 O << ", " << (unsigned int)SH << "\n"; 437 return; 438 } 439 } 440 441 if (printInstruction(MI)) 442 return; // Printer was automatically generated 443 444 assert(0 && "Unhandled instruction in asm writer!"); 445 abort(); 446 return; 447} 448 449/// runOnMachineFunction - This uses the printMachineInstruction() 450/// method to print assembly for each instruction. 451/// 452bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 453 setupMachineFunction(MF); 454 O << "\n\n"; 455 456 // Print out constants referenced by the function 457 printConstantPool(MF.getConstantPool()); 458 459 // Print out labels for the function. 460 O << "\t.text\n"; 461 emitAlignment(2); 462 O << "\t.globl\t" << CurrentFnName << "\n"; 463 O << CurrentFnName << ":\n"; 464 465 // Print out code for the function. 466 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 467 I != E; ++I) { 468 // Print a label for the basic block. 469 O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t" 470 << CommentString << " " << I->getBasicBlock()->getName() << "\n"; 471 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); 472 II != E; ++II) { 473 // Print the assembly for the instruction. 474 O << "\t"; 475 printMachineInstruction(II); 476 } 477 } 478 ++LabelNumber; 479 480 // We didn't modify anything. 481 return false; 482} 483 484/// printConstantPool - Print to the current output stream assembly 485/// representations of the constants in the constant pool MCP. This is 486/// used to print out constants which have been "spilled to memory" by 487/// the code generator. 488/// 489void DarwinAsmPrinter::printConstantPool(MachineConstantPool *MCP) { 490 const std::vector<Constant*> &CP = MCP->getConstants(); 491 const TargetData &TD = TM.getTargetData(); 492 493 if (CP.empty()) return; 494 495 for (unsigned i = 0, e = CP.size(); i != e; ++i) { 496 O << "\t.const\n"; 497 emitAlignment(TD.getTypeAlignmentShift(CP[i]->getType())); 498 O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t" << CommentString 499 << *CP[i] << "\n"; 500 emitGlobalConstant(CP[i]); 501 } 502} 503 504bool DarwinAsmPrinter::doFinalization(Module &M) { 505 const TargetData &TD = TM.getTargetData(); 506 std::string CurSection; 507 508 // Print out module-level global variables here. 509 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) 510 if (I->hasInitializer()) { // External global require no code 511 O << '\n'; 512 std::string name = Mang->getValueName(I); 513 Constant *C = I->getInitializer(); 514 unsigned Size = TD.getTypeSize(C->getType()); 515 unsigned Align = TD.getTypeAlignmentShift(C->getType()); 516 517 if (C->isNullValue() && /* FIXME: Verify correct */ 518 (I->hasInternalLinkage() || I->hasWeakLinkage() || 519 I->hasLinkOnceLinkage())) { 520 SwitchSection(O, CurSection, ".data"); 521 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. 522 if (I->hasInternalLinkage()) 523 O << ".lcomm " << name << "," << Size << "," << Align; 524 else 525 O << ".comm " << name << "," << Size; 526 O << "\t\t; "; 527 WriteAsOperand(O, I, true, true, &M); 528 O << '\n'; 529 } else { 530 switch (I->getLinkage()) { 531 case GlobalValue::LinkOnceLinkage: 532 O << ".section __TEXT,__textcoal_nt,coalesced,no_toc\n" 533 << ".weak_definition " << name << '\n' 534 << ".private_extern " << name << '\n' 535 << ".section __DATA,__datacoal_nt,coalesced,no_toc\n"; 536 LinkOnceStubs.insert(name); 537 break; 538 case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. 539 // Nonnull linkonce -> weak 540 O << "\t.weak " << name << "\n"; 541 SwitchSection(O, CurSection, ""); 542 O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"; 543 break; 544 case GlobalValue::AppendingLinkage: 545 // FIXME: appending linkage variables should go into a section of 546 // their name or something. For now, just emit them as external. 547 case GlobalValue::ExternalLinkage: 548 // If external or appending, declare as a global symbol 549 O << "\t.globl " << name << "\n"; 550 // FALL THROUGH 551 case GlobalValue::InternalLinkage: 552 SwitchSection(O, CurSection, ".data"); 553 break; 554 case GlobalValue::GhostLinkage: 555 std::cerr << "Error: unmaterialized (GhostLinkage) function in asm!"; 556 abort(); 557 } 558 559 emitAlignment(Align); 560 O << name << ":\t\t\t\t; "; 561 WriteAsOperand(O, I, true, true, &M); 562 O << " = "; 563 WriteAsOperand(O, C, false, false, &M); 564 O << "\n"; 565 emitGlobalConstant(C); 566 } 567 } 568 569 // Output stubs for dynamically-linked functions 570 for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end(); 571 i != e; ++i) 572 { 573 O << ".data\n"; 574 O << ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"; 575 emitAlignment(2); 576 O << "L" << *i << "$stub:\n"; 577 O << "\t.indirect_symbol " << *i << "\n"; 578 O << "\tmflr r0\n"; 579 O << "\tbcl 20,31,L0$" << *i << "\n"; 580 O << "L0$" << *i << ":\n"; 581 O << "\tmflr r11\n"; 582 O << "\taddis r11,r11,ha16(L" << *i << "$lazy_ptr-L0$" << *i << ")\n"; 583 O << "\tmtlr r0\n"; 584 O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n"; 585 O << "\tmtctr r12\n"; 586 O << "\tbctr\n"; 587 O << ".data\n"; 588 O << ".lazy_symbol_pointer\n"; 589 O << "L" << *i << "$lazy_ptr:\n"; 590 O << "\t.indirect_symbol " << *i << "\n"; 591 O << "\t.long dyld_stub_binding_helper\n"; 592 } 593 594 O << "\n"; 595 596 // Output stubs for external global variables 597 if (GVStubs.begin() != GVStubs.end()) 598 O << ".data\n.non_lazy_symbol_pointer\n"; 599 for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end(); 600 i != e; ++i) { 601 O << "L" << *i << "$non_lazy_ptr:\n"; 602 O << "\t.indirect_symbol " << *i << "\n"; 603 O << "\t.long\t0\n"; 604 } 605 606 // Output stubs for link-once variables 607 if (LinkOnceStubs.begin() != LinkOnceStubs.end()) 608 O << ".data\n.align 2\n"; 609 for (std::set<std::string>::iterator i = LinkOnceStubs.begin(), 610 e = LinkOnceStubs.end(); i != e; ++i) { 611 O << "L" << *i << "$non_lazy_ptr:\n" 612 << "\t.long\t" << *i << '\n'; 613 } 614 615 AsmPrinter::doFinalization(M); 616 return false; // success 617} 618 619/// runOnMachineFunction - This uses the printMachineInstruction() 620/// method to print assembly for each instruction. 621/// 622bool AIXAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 623 CurrentFnName = MF.getFunction()->getName(); 624 625 // Print out constants referenced by the function 626 printConstantPool(MF.getConstantPool()); 627 628 // Print out header for the function. 629 O << "\t.csect .text[PR]\n" 630 << "\t.align 2\n" 631 << "\t.globl " << CurrentFnName << '\n' 632 << "\t.globl ." << CurrentFnName << '\n' 633 << "\t.csect " << CurrentFnName << "[DS],3\n" 634 << CurrentFnName << ":\n" 635 << "\t.llong ." << CurrentFnName << ", TOC[tc0], 0\n" 636 << "\t.csect .text[PR]\n" 637 << '.' << CurrentFnName << ":\n"; 638 639 // Print out code for the function. 640 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 641 I != E; ++I) { 642 // Print a label for the basic block. 643 O << "LBB" << CurrentFnName << "_" << I->getNumber() << ":\t# " 644 << I->getBasicBlock()->getName() << "\n"; 645 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); 646 II != E; ++II) { 647 // Print the assembly for the instruction. 648 O << "\t"; 649 printMachineInstruction(II); 650 } 651 } 652 ++LabelNumber; 653 654 O << "LT.." << CurrentFnName << ":\n" 655 << "\t.long 0\n" 656 << "\t.byte 0,0,32,65,128,0,0,0\n" 657 << "\t.long LT.." << CurrentFnName << "-." << CurrentFnName << '\n' 658 << "\t.short 3\n" 659 << "\t.byte \"" << CurrentFnName << "\"\n" 660 << "\t.align 2\n"; 661 662 // We didn't modify anything. 663 return false; 664} 665 666/// printConstantPool - Print to the current output stream assembly 667/// representations of the constants in the constant pool MCP. This is 668/// used to print out constants which have been "spilled to memory" by 669/// the code generator. 670/// 671void AIXAsmPrinter::printConstantPool(MachineConstantPool *MCP) { 672 const std::vector<Constant*> &CP = MCP->getConstants(); 673 const TargetData &TD = TM.getTargetData(); 674 675 if (CP.empty()) return; 676 677 for (unsigned i = 0, e = CP.size(); i != e; ++i) { 678 O << "\t.const\n"; 679 O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType()) 680 << "\n"; 681 O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t;" 682 << *CP[i] << "\n"; 683 emitGlobalConstant(CP[i]); 684 } 685} 686 687bool AIXAsmPrinter::doInitialization(Module &M) { 688 const TargetData &TD = TM.getTargetData(); 689 std::string CurSection; 690 691 O << "\t.machine \"ppc64\"\n" 692 << "\t.toc\n" 693 << "\t.csect .text[PR]\n"; 694 695 // Print out module-level global variables 696 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { 697 if (!I->hasInitializer()) 698 continue; 699 700 std::string Name = I->getName(); 701 Constant *C = I->getInitializer(); 702 // N.B.: We are defaulting to writable strings 703 if (I->hasExternalLinkage()) { 704 O << "\t.globl " << Name << '\n' 705 << "\t.csect .data[RW],3\n"; 706 } else { 707 O << "\t.csect _global.rw_c[RW],3\n"; 708 } 709 O << Name << ":\n"; 710 emitGlobalConstant(C); 711 } 712 713 // Output labels for globals 714 if (M.global_begin() != M.global_end()) O << "\t.toc\n"; 715 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { 716 const GlobalVariable *GV = I; 717 // Do not output labels for unused variables 718 if (GV->isExternal() && GV->use_begin() == GV->use_end()) 719 continue; 720 721 std::string Name = GV->getName(); 722 std::string Label = "LC.." + utostr(LabelNumber++); 723 GVToLabelMap[GV] = Label; 724 O << Label << ":\n" 725 << "\t.tc " << Name << "[TC]," << Name; 726 if (GV->isExternal()) O << "[RW]"; 727 O << '\n'; 728 } 729 730 Mang = new Mangler(M, "."); 731 return false; // success 732} 733 734bool AIXAsmPrinter::doFinalization(Module &M) { 735 const TargetData &TD = TM.getTargetData(); 736 // Print out module-level global variables 737 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { 738 if (I->hasInitializer() || I->hasExternalLinkage()) 739 continue; 740 741 std::string Name = I->getName(); 742 if (I->hasInternalLinkage()) { 743 O << "\t.lcomm " << Name << ",16,_global.bss_c"; 744 } else { 745 O << "\t.comm " << Name << "," << TD.getTypeSize(I->getType()) 746 << "," << log2((unsigned)TD.getTypeAlignment(I->getType())); 747 } 748 O << "\t\t# "; 749 WriteAsOperand(O, I, true, true, &M); 750 O << "\n"; 751 } 752 753 O << "_section_.text:\n" 754 << "\t.csect .data[RW],3\n" 755 << "\t.llong _section_.text\n"; 756 757 delete Mang; 758 return false; // success 759} 760