X86AsmPrinter.cpp revision 72b286b0a0f8987bc247ae052ac86008c553e9ae
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(), E = M.global_end(); I != E; ++I) 99 if (I->hasInitializer()) { // External global require no code 100 O << "\n\n"; 101 std::string name = Mang->getValueName(I); 102 Constant *C = I->getInitializer(); 103 unsigned Size = TD.getTypeSize(C->getType()); 104 unsigned Align = TD.getTypeAlignmentShift(C->getType()); 105 106 if (C->isNullValue() && 107 (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || 108 I->hasWeakLinkage() /* FIXME: Verify correct */)) { 109 SwitchSection(O, CurSection, ".data"); 110 if (!forCygwin && !forDarwin && I->hasInternalLinkage()) 111 O << "\t.local " << name << "\n"; 112 if (forDarwin && I->hasInternalLinkage()) 113 O << "\t.lcomm " << name << "," << Size << "," << Align; 114 else 115 O << "\t.comm " << name << "," << Size; 116 if (!forCygwin && !forDarwin) 117 O << "," << (1 << Align); 118 O << "\t\t# "; 119 WriteAsOperand(O, I, true, true, &M); 120 O << "\n"; 121 } else { 122 switch (I->getLinkage()) { 123 case GlobalValue::LinkOnceLinkage: 124 case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. 125 // Nonnull linkonce -> weak 126 O << "\t.weak " << name << "\n"; 127 SwitchSection(O, CurSection, ""); 128 O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"; 129 break; 130 case GlobalValue::AppendingLinkage: 131 // FIXME: appending linkage variables should go into a section of 132 // their name or something. For now, just emit them as external. 133 case GlobalValue::ExternalLinkage: 134 // If external or appending, declare as a global symbol 135 O << "\t.globl " << name << "\n"; 136 // FALL THROUGH 137 case GlobalValue::InternalLinkage: 138 if (C->isNullValue()) 139 SwitchSection(O, CurSection, ".bss"); 140 else 141 SwitchSection(O, CurSection, ".data"); 142 break; 143 case GlobalValue::GhostLinkage: 144 std::cerr << "GhostLinkage cannot appear in X86AsmPrinter!\n"; 145 abort(); 146 } 147 148 emitAlignment(Align); 149 if (!forCygwin && !forDarwin) { 150 O << "\t.type " << name << ",@object\n"; 151 O << "\t.size " << name << "," << Size << "\n"; 152 } 153 O << name << ":\t\t\t\t# "; 154 WriteAsOperand(O, I, true, true, &M); 155 O << " = "; 156 WriteAsOperand(O, C, false, false, &M); 157 O << "\n"; 158 emitGlobalConstant(C); 159 } 160 } 161 162 if (forDarwin) { 163 // Output stubs for dynamically-linked functions 164 unsigned j = 1; 165 for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end(); 166 i != e; ++i, ++j) 167 { 168 O << "\t.symbol_stub\n"; 169 O << "L" << *i << "$stub:\n"; 170 O << "\t.indirect_symbol " << *i << "\n"; 171 O << "\tjmp\t*L" << j << "$lz\n"; 172 O << "L" << *i << "$stub_binder:\n"; 173 O << "\tpushl\t$L" << j << "$lz\n"; 174 O << "\tjmp\tdyld_stub_binding_helper\n"; 175 O << "\t.section __DATA, __la_sym_ptr3,lazy_symbol_pointers\n"; 176 O << "L" << j << "$lz:\n"; 177 O << "\t.indirect_symbol " << *i << "\n"; 178 O << "\t.long\tL" << *i << "$stub_binder\n"; 179 } 180 181 O << "\n"; 182 183 // Output stubs for external global variables 184 if (GVStubs.begin() != GVStubs.end()) 185 O << ".data\n.non_lazy_symbol_pointer\n"; 186 for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end(); 187 i != e; ++i) { 188 O << "L" << *i << "$non_lazy_ptr:\n"; 189 O << "\t.indirect_symbol " << *i << "\n"; 190 O << "\t.long\t0\n"; 191 } 192 193 // Output stubs for link-once variables 194 if (LinkOnceStubs.begin() != LinkOnceStubs.end()) 195 O << ".data\n.align 2\n"; 196 for (std::set<std::string>::iterator i = LinkOnceStubs.begin(), 197 e = LinkOnceStubs.end(); i != e; ++i) { 198 O << "L" << *i << "$non_lazy_ptr:\n" 199 << "\t.long\t" << *i << '\n'; 200 } 201 } 202 203 AsmPrinter::doFinalization(M); 204 return false; // success 205} 206 207/// createX86CodePrinterPass - Returns a pass that prints the X86 assembly code 208/// for a MachineFunction to the given output stream, using the given target 209/// machine description. 210/// 211FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){ 212 switch (AsmWriterFlavor) { 213 default: 214 assert(0 && "Unknown asm flavor!"); 215 case intel: 216 return new X86IntelAsmPrinter(o, tm); 217 case att: 218 return new X86ATTAsmPrinter(o, tm); 219 } 220} 221