X86AsmPrinter.cpp revision a0ea0539e359f6d82218e5aa4cdf3b50b17d6fbd
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 "X86Subtarget.h" 20#include "X86.h" 21#include "llvm/Constants.h" 22#include "llvm/Module.h" 23#include "llvm/Type.h" 24#include "llvm/Assembly/Writer.h" 25#include "llvm/Support/Mangler.h" 26#include "llvm/Support/CommandLine.h" 27using namespace llvm; 28using namespace x86; 29 30Statistic<> llvm::x86::EmittedInsts("asm-printer", 31 "Number of machine instrs printed"); 32 33enum AsmWriterFlavorTy { att, intel }; 34cl::opt<AsmWriterFlavorTy> 35AsmWriterFlavor("x86-asm-syntax", 36 cl::desc("Choose style of code to emit from X86 backend:"), 37 cl::values( 38 clEnumVal(att, " Emit AT&T-style assembly"), 39 clEnumVal(intel, " Emit Intel-style assembly"), 40 clEnumValEnd), 41 cl::init(att)); 42 43/// doInitialization 44bool X86SharedAsmPrinter::doInitialization(Module &M) { 45 const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>(); 46 47 forDarwin = false; 48 49 switch (Subtarget->TargetType) { 50 case X86Subtarget::isDarwin: 51 AlignmentIsInBytes = false; 52 GlobalPrefix = "_"; 53 Data64bitsDirective = 0; // we can't emit a 64-bit unit 54 ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. 55 PrivateGlobalPrefix = "L"; // Marker for constant pool idxs 56 ConstantPoolSection = "\t.const\n"; 57 LCOMMDirective = "\t.lcomm\t"; 58 COMMDirectiveTakesAlignment = false; 59 HasDotTypeDotSizeDirective = false; 60 forDarwin = true; 61 StaticCtorsSection = ".mod_init_func"; 62 StaticDtorsSection = ".mod_term_func"; 63 InlineAsmStart = InlineAsmEnd = ""; // Don't use #APP/#NO_APP 64 break; 65 case X86Subtarget::isCygwin: 66 GlobalPrefix = "_"; 67 COMMDirectiveTakesAlignment = false; 68 HasDotTypeDotSizeDirective = false; 69 break; 70 case X86Subtarget::isWindows: 71 GlobalPrefix = "_"; 72 HasDotTypeDotSizeDirective = false; 73 break; 74 default: break; 75 } 76 77 return AsmPrinter::doInitialization(M); 78} 79 80bool X86SharedAsmPrinter::doFinalization(Module &M) { 81 const TargetData &TD = TM.getTargetData(); 82 83 // Print out module-level global variables here. 84 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); 85 I != E; ++I) { 86 if (!I->hasInitializer()) continue; // External global require no code 87 88 // Check to see if this is a special global used by LLVM, if so, emit it. 89 if (I->hasAppendingLinkage() && EmitSpecialLLVMGlobal(I)) 90 continue; 91 92 std::string name = Mang->getValueName(I); 93 Constant *C = I->getInitializer(); 94 unsigned Size = TD.getTypeSize(C->getType()); 95 unsigned Align = getPreferredAlignmentLog(I); 96 97 if (C->isNullValue() && /* FIXME: Verify correct */ 98 (I->hasInternalLinkage() || I->hasWeakLinkage() || 99 I->hasLinkOnceLinkage() || 100 (forDarwin && I->hasExternalLinkage() && !I->hasSection()))) { 101 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. 102 if (I->hasExternalLinkage()) { 103 O << "\t.globl\t" << name << "\n"; 104 O << "\t.zerofill __DATA__, __common, " << name << ", " 105 << Size << ", " << Align; 106 } else { 107 SwitchSection(".data", I); 108 if (LCOMMDirective != NULL) { 109 if (I->hasInternalLinkage()) { 110 O << LCOMMDirective << name << "," << Size; 111 if (forDarwin) 112 O << "," << (AlignmentIsInBytes ? (1 << Align) : Align); 113 } else 114 O << COMMDirective << name << "," << Size; 115 } else { 116 if (I->hasInternalLinkage()) 117 O << "\t.local\t" << name << "\n"; 118 O << COMMDirective << name << "," << Size; 119 if (COMMDirectiveTakesAlignment) 120 O << "," << (AlignmentIsInBytes ? (1 << Align) : Align); 121 } 122 } 123 O << "\t\t" << CommentString << " " << I->getName() << "\n"; 124 } else { 125 switch (I->getLinkage()) { 126 case GlobalValue::LinkOnceLinkage: 127 case GlobalValue::WeakLinkage: 128 if (forDarwin) { 129 O << "\t.globl " << name << "\n" 130 << "\t.weak_definition " << name << "\n"; 131 SwitchSection(".section __DATA,__datacoal_nt,coalesced", I); 132 } else { 133 O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"; 134 O << "\t.weak " << name << "\n"; 135 } 136 break; 137 case GlobalValue::AppendingLinkage: 138 // FIXME: appending linkage variables should go into a section of 139 // their name or something. For now, just emit them as external. 140 case GlobalValue::ExternalLinkage: 141 // If external or appending, declare as a global symbol 142 O << "\t.globl " << name << "\n"; 143 // FALL THROUGH 144 case GlobalValue::InternalLinkage: 145 SwitchSection(".data", I); 146 break; 147 default: 148 assert(0 && "Unknown linkage type!"); 149 } 150 151 EmitAlignment(Align, I); 152 O << name << ":\t\t\t\t" << CommentString << " " << I->getName() 153 << "\n"; 154 if (HasDotTypeDotSizeDirective) 155 O << "\t.size " << name << ", " << Size << "\n"; 156 157 EmitGlobalConstant(C); 158 O << '\n'; 159 } 160 } 161 162 if (forDarwin) { 163 SwitchSection("", 0); 164 165 // Output stubs for dynamically-linked functions 166 unsigned j = 1; 167 for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end(); 168 i != e; ++i, ++j) { 169 SwitchSection(".section __IMPORT,__jump_table,symbol_stubs," 170 "self_modifying_code+pure_instructions,5", 0); 171 O << "L" << *i << "$stub:\n"; 172 O << "\t.indirect_symbol " << *i << "\n"; 173 O << "\thlt ; hlt ; hlt ; hlt ; hlt\n"; 174 } 175 176 O << "\n"; 177 178 // Output stubs for external and common global variables. 179 if (GVStubs.begin() != GVStubs.end()) 180 SwitchSection(".section __IMPORT,__pointers,non_lazy_symbol_pointers", 0); 181 for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end(); 182 i != e; ++i) { 183 O << "L" << *i << "$non_lazy_ptr:\n"; 184 O << "\t.indirect_symbol " << *i << "\n"; 185 O << "\t.long\t0\n"; 186 } 187 } 188 189 AsmPrinter::doFinalization(M); 190 return false; // success 191} 192 193/// createX86CodePrinterPass - Returns a pass that prints the X86 assembly code 194/// for a MachineFunction to the given output stream, using the given target 195/// machine description. 196/// 197FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){ 198 switch (AsmWriterFlavor) { 199 default: 200 assert(0 && "Unknown asm flavor!"); 201 case intel: 202 return new X86IntelAsmPrinter(o, tm); 203 case att: 204 return new X86ATTAsmPrinter(o, tm); 205 } 206} 207