X86AsmPrinter.cpp revision b12c9fa565ca03fdfc40d8d9933561f47bc5f89e
1//===-- X86AsmPrinter.cpp - Convert X86 LLVM IR to X86 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 the shared super class printer that converts from our internal 11// representation of machine-dependent LLVM code to Intel and AT&T format 12// assembly language. 13// This printer is the output mechanism used by `llc'. 14// 15//===----------------------------------------------------------------------===// 16 17#include "X86ATTAsmPrinter.h" 18#include "X86IntelAsmPrinter.h" 19#include "X86.h" 20#include "llvm/Module.h" 21#include "llvm/Assembly/Writer.h" 22#include "llvm/CodeGen/MachineConstantPool.h" 23#include "llvm/Support/Mangler.h" 24#include "llvm/Support/CommandLine.h" 25using namespace llvm; 26using namespace x86; 27 28Statistic<> llvm::x86::EmittedInsts("asm-printer", 29 "Number of machine instrs printed"); 30 31enum AsmWriterFlavorTy { att, intel }; 32cl::opt<AsmWriterFlavorTy> 33AsmWriterFlavor("x86-asm-syntax", 34 cl::desc("Choose style of code to emit from X86 backend:"), 35 cl::values( 36 clEnumVal(att, " Emit AT&T-style assembly"), 37 clEnumVal(intel, " Emit Intel-style assembly"), 38 clEnumValEnd), 39 cl::init(att)); 40 41/// doInitialization 42bool X86SharedAsmPrinter::doInitialization(Module& M) { 43 bool leadingUnderscore = false; 44 forCygwin = false; 45 const std::string& TT = M.getTargetTriple(); 46 if (TT.length() > 5) { 47 forCygwin = TT.find("cygwin") != std::string::npos || 48 TT.find("mingw") != std::string::npos; 49 forDarwin = TT.find("darwin") != std::string::npos; 50 } else if (TT.empty()) { 51#if defined(__CYGWIN__) || defined(__MINGW32__) 52 forCygwin = true; 53#elif defined(__APPLE__) 54 forDarwin = true; 55#elif defined(_WIN32) 56 leadingUnderscore = true; 57#else 58 leadingUnderscore = false; 59#endif 60 } 61 if (leadingUnderscore || forCygwin || forDarwin) 62 GlobalPrefix = "_"; 63 64 if (forDarwin) 65 AlignmentIsInBytes = false; 66 67 return AsmPrinter::doInitialization(M); 68} 69 70/// printConstantPool - Print to the current output stream assembly 71/// representations of the constants in the constant pool MCP. This is 72/// used to print out constants which have been "spilled to memory" by 73/// the code generator. 74/// 75void X86SharedAsmPrinter::printConstantPool(MachineConstantPool *MCP) { 76 const std::vector<Constant*> &CP = MCP->getConstants(); 77 const TargetData &TD = TM.getTargetData(); 78 79 if (CP.empty()) return; 80 81 for (unsigned i = 0, e = CP.size(); i != e; ++i) { 82 if (forDarwin) 83 O << "\t.data\n"; 84 else 85 O << "\t.section .rodata\n"; 86 emitAlignment(TD.getTypeAlignmentShift(CP[i]->getType())); 87 O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t" << CommentString 88 << *CP[i] << "\n"; 89 emitGlobalConstant(CP[i]); 90 } 91} 92 93bool X86SharedAsmPrinter::doFinalization(Module &M) { 94 const TargetData &TD = TM.getTargetData(); 95 std::string CurSection; 96 97 // Print out module-level global variables here. 98 for (Module::const_global_iterator I = M.global_begin(), 99 E = M.global_end(); I != E; ++I) 100 if (I->hasInitializer()) { // External global require no code 101 O << "\n\n"; 102 std::string name = Mang->getValueName(I); 103 Constant *C = I->getInitializer(); 104 unsigned Size = TD.getTypeSize(C->getType()); 105 unsigned Align = TD.getTypeAlignmentShift(C->getType()); 106 107 if (C->isNullValue() && 108 (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || 109 I->hasWeakLinkage() /* FIXME: Verify correct */)) { 110 SwitchSection(O, CurSection, ".data"); 111 if (!forCygwin && !forDarwin && I->hasInternalLinkage()) 112 O << "\t.local " << name << "\n"; 113 if (forDarwin && I->hasInternalLinkage()) 114 O << "\t.lcomm " << name << "," << Size << "," << Align; 115 else 116 O << "\t.comm " << name << "," << Size; 117 if (!forCygwin && !forDarwin) 118 O << "," << (1 << Align); 119 O << "\t\t# "; 120 WriteAsOperand(O, I, true, true, &M); 121 O << "\n"; 122 } else { 123 switch (I->getLinkage()) { 124 default: assert(0 && "Unknown linkage type!"); 125 case GlobalValue::LinkOnceLinkage: 126 case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. 127 // Nonnull linkonce -> weak 128 O << "\t.weak " << name << "\n"; 129 SwitchSection(O, CurSection, ""); 130 O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"; 131 break; 132 case GlobalValue::AppendingLinkage: 133 // FIXME: appending linkage variables should go into a section of 134 // their name or something. For now, just emit them as external. 135 case GlobalValue::ExternalLinkage: 136 // If external or appending, declare as a global symbol 137 O << "\t.globl " << name << "\n"; 138 // FALL THROUGH 139 case GlobalValue::InternalLinkage: 140 if (C->isNullValue()) 141 SwitchSection(O, CurSection, ".bss"); 142 else 143 SwitchSection(O, CurSection, ".data"); 144 break; 145 } 146 147 emitAlignment(Align); 148 if (!forCygwin && !forDarwin) { 149 O << "\t.type " << name << ",@object\n"; 150 O << "\t.size " << name << "," << Size << "\n"; 151 } 152 O << name << ":\t\t\t\t# "; 153 WriteAsOperand(O, I, true, true, &M); 154 O << " = "; 155 WriteAsOperand(O, C, false, false, &M); 156 O << "\n"; 157 emitGlobalConstant(C); 158 } 159 } 160 161 if (forDarwin) { 162 // Output stubs for dynamically-linked functions 163 unsigned j = 1; 164 for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end(); 165 i != e; ++i, ++j) { 166 O << "\t.symbol_stub\n"; 167 O << "L" << *i << "$stub:\n"; 168 O << "\t.indirect_symbol " << *i << "\n"; 169 O << "\tjmp\t*L" << j << "$lz\n"; 170 O << "L" << *i << "$stub_binder:\n"; 171 O << "\tpushl\t$L" << j << "$lz\n"; 172 O << "\tjmp\tdyld_stub_binding_helper\n"; 173 O << "\t.section __DATA, __la_sym_ptr3,lazy_symbol_pointers\n"; 174 O << "L" << j << "$lz:\n"; 175 O << "\t.indirect_symbol " << *i << "\n"; 176 O << "\t.long\tL" << *i << "$stub_binder\n"; 177 } 178 179 O << "\n"; 180 181 // Output stubs for external global variables 182 if (GVStubs.begin() != GVStubs.end()) 183 O << ".data\n.non_lazy_symbol_pointer\n"; 184 for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end(); 185 i != e; ++i) { 186 O << "L" << *i << "$non_lazy_ptr:\n"; 187 O << "\t.indirect_symbol " << *i << "\n"; 188 O << "\t.long\t0\n"; 189 } 190 191 // Output stubs for link-once variables 192 if (LinkOnceStubs.begin() != LinkOnceStubs.end()) 193 O << ".data\n.align 2\n"; 194 for (std::set<std::string>::iterator i = LinkOnceStubs.begin(), 195 e = LinkOnceStubs.end(); i != e; ++i) { 196 O << "L" << *i << "$non_lazy_ptr:\n" 197 << "\t.long\t" << *i << '\n'; 198 } 199 } 200 201 AsmPrinter::doFinalization(M); 202 return false; // success 203} 204 205/// createX86CodePrinterPass - Returns a pass that prints the X86 assembly code 206/// for a MachineFunction to the given output stream, using the given target 207/// machine description. 208/// 209FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){ 210 switch (AsmWriterFlavor) { 211 default: 212 assert(0 && "Unknown asm flavor!"); 213 case intel: 214 return new X86IntelAsmPrinter(o, tm); 215 case att: 216 return new X86ATTAsmPrinter(o, tm); 217 } 218} 219