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