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