| Dan Gohman | e33c4b7 | 2007-06-25 15:11:25 +0000 | [diff] [blame] | 1 | //===-- X86ATTAsmPrinter.cpp - Convert X86 LLVM code to AT&T assembly -----===// | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
| Chris Lattner | f3ebc3f | 2007-12-29 20:36:04 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This file contains a printer that converts from our internal representation | 
|  | 11 | // of machine-dependent LLVM code to AT&T format assembly | 
|  | 12 | // language. This printer is the output mechanism used by `llc'. | 
|  | 13 | // | 
|  | 14 | //===----------------------------------------------------------------------===// | 
|  | 15 |  | 
| Chris Lattner | 1ef9cd4 | 2006-12-19 22:59:26 +0000 | [diff] [blame] | 16 | #define DEBUG_TYPE "asm-printer" | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 17 | #include "X86ATTAsmPrinter.h" | 
| Cedric Venet | 954553c | 2008-08-17 18:24:26 +0000 | [diff] [blame] | 18 | #include "../X86.h" | 
|  | 19 | #include "../X86COFF.h" | 
|  | 20 | #include "../X86MachineFunctionInfo.h" | 
|  | 21 | #include "../X86TargetMachine.h" | 
|  | 22 | #include "../X86TargetAsmInfo.h" | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 23 | #include "llvm/CallingConv.h" | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 24 | #include "llvm/DerivedTypes.h" | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 25 | #include "llvm/Module.h" | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 26 | #include "llvm/Type.h" | 
|  | 27 | #include "llvm/ADT/Statistic.h" | 
|  | 28 | #include "llvm/ADT/StringExtras.h" | 
|  | 29 | #include "llvm/CodeGen/MachineJumpTableInfo.h" | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 30 | #include "llvm/Support/Mangler.h" | 
| Owen Anderson | 9371964 | 2008-08-21 00:14:44 +0000 | [diff] [blame^] | 31 | #include "llvm/Support/raw_ostream.h" | 
| Jim Laskey | 261779b | 2006-09-07 22:06:40 +0000 | [diff] [blame] | 32 | #include "llvm/Target/TargetAsmInfo.h" | 
| Evan Cheng | 5588de9 | 2006-02-18 00:15:05 +0000 | [diff] [blame] | 33 | #include "llvm/Target/TargetOptions.h" | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 34 | using namespace llvm; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 35 |  | 
| Chris Lattner | 1ef9cd4 | 2006-12-19 22:59:26 +0000 | [diff] [blame] | 36 | STATISTIC(EmittedInsts, "Number of machine instrs printed"); | 
|  | 37 |  | 
| Evan Cheng | f55b738 | 2008-01-05 00:41:47 +0000 | [diff] [blame] | 38 | static std::string getPICLabelString(unsigned FnNum, | 
|  | 39 | const TargetAsmInfo *TAI, | 
|  | 40 | const X86Subtarget* Subtarget) { | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 41 | std::string label; | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 42 | if (Subtarget->isTargetDarwin()) | 
| Evan Cheng | cdf3609 | 2007-10-14 05:57:21 +0000 | [diff] [blame] | 43 | label =  "\"L" + utostr_32(FnNum) + "$pb\""; | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 44 | else if (Subtarget->isTargetELF()) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 45 | label = ".Lllvm$" + utostr_32(FnNum) + "." "$piclabel"; | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 46 | else | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 47 | assert(0 && "Don't know how to print PIC label!\n"); | 
|  | 48 |  | 
|  | 49 | return label; | 
|  | 50 | } | 
|  | 51 |  | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 52 | static X86MachineFunctionInfo calculateFunctionInfo(const Function *F, | 
|  | 53 | const TargetData *TD) { | 
|  | 54 | X86MachineFunctionInfo Info; | 
|  | 55 | uint64_t Size = 0; | 
|  | 56 |  | 
|  | 57 | switch (F->getCallingConv()) { | 
|  | 58 | case CallingConv::X86_StdCall: | 
|  | 59 | Info.setDecorationStyle(StdCall); | 
|  | 60 | break; | 
|  | 61 | case CallingConv::X86_FastCall: | 
|  | 62 | Info.setDecorationStyle(FastCall); | 
|  | 63 | break; | 
|  | 64 | default: | 
|  | 65 | return Info; | 
|  | 66 | } | 
|  | 67 |  | 
|  | 68 | unsigned argNum = 1; | 
|  | 69 | for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); | 
|  | 70 | AI != AE; ++AI, ++argNum) { | 
|  | 71 | const Type* Ty = AI->getType(); | 
|  | 72 |  | 
|  | 73 | // 'Dereference' type in case of byval parameter attribute | 
|  | 74 | if (F->paramHasAttr(argNum, ParamAttr::ByVal)) | 
|  | 75 | Ty = cast<PointerType>(Ty)->getElementType(); | 
|  | 76 |  | 
|  | 77 | // Size should be aligned to DWORD boundary | 
|  | 78 | Size += ((TD->getABITypeSize(Ty) + 3)/4)*4; | 
|  | 79 | } | 
|  | 80 |  | 
|  | 81 | // We're not supporting tooooo huge arguments :) | 
|  | 82 | Info.setBytesToPopOnReturn((unsigned int)Size); | 
|  | 83 | return Info; | 
|  | 84 | } | 
|  | 85 |  | 
|  | 86 | /// PrintUnmangledNameSafely - Print out the printable characters in the name. | 
|  | 87 | /// Don't print things like \n or \0. | 
| Owen Anderson | 9371964 | 2008-08-21 00:14:44 +0000 | [diff] [blame^] | 88 | static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) { | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 89 | for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen(); | 
|  | 90 | Name != E; ++Name) | 
|  | 91 | if (isprint(*Name)) | 
|  | 92 | OS << *Name; | 
|  | 93 | } | 
|  | 94 |  | 
|  | 95 | /// decorateName - Query FunctionInfoMap and use this information for various | 
|  | 96 | /// name decoration. | 
|  | 97 | void X86ATTAsmPrinter::decorateName(std::string &Name, | 
|  | 98 | const GlobalValue *GV) { | 
|  | 99 | const Function *F = dyn_cast<Function>(GV); | 
|  | 100 | if (!F) return; | 
|  | 101 |  | 
|  | 102 | // We don't want to decorate non-stdcall or non-fastcall functions right now | 
|  | 103 | unsigned CC = F->getCallingConv(); | 
|  | 104 | if (CC != CallingConv::X86_StdCall && CC != CallingConv::X86_FastCall) | 
|  | 105 | return; | 
|  | 106 |  | 
|  | 107 | // Decorate names only when we're targeting Cygwin/Mingw32 targets | 
|  | 108 | if (!Subtarget->isTargetCygMing()) | 
|  | 109 | return; | 
|  | 110 |  | 
|  | 111 | FMFInfoMap::const_iterator info_item = FunctionInfoMap.find(F); | 
|  | 112 |  | 
|  | 113 | const X86MachineFunctionInfo *Info; | 
|  | 114 | if (info_item == FunctionInfoMap.end()) { | 
|  | 115 | // Calculate apropriate function info and populate map | 
|  | 116 | FunctionInfoMap[F] = calculateFunctionInfo(F, TM.getTargetData()); | 
|  | 117 | Info = &FunctionInfoMap[F]; | 
|  | 118 | } else { | 
|  | 119 | Info = &info_item->second; | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | const FunctionType *FT = F->getFunctionType(); | 
|  | 123 | switch (Info->getDecorationStyle()) { | 
|  | 124 | case None: | 
|  | 125 | break; | 
|  | 126 | case StdCall: | 
|  | 127 | // "Pure" variadic functions do not receive @0 suffix. | 
|  | 128 | if (!FT->isVarArg() || (FT->getNumParams() == 0) || | 
|  | 129 | (FT->getNumParams() == 1 && F->hasStructRetAttr())) | 
|  | 130 | Name += '@' + utostr_32(Info->getBytesToPopOnReturn()); | 
|  | 131 | break; | 
|  | 132 | case FastCall: | 
|  | 133 | // "Pure" variadic functions do not receive @0 suffix. | 
|  | 134 | if (!FT->isVarArg() || (FT->getNumParams() == 0) || | 
|  | 135 | (FT->getNumParams() == 1 && F->hasStructRetAttr())) | 
|  | 136 | Name += '@' + utostr_32(Info->getBytesToPopOnReturn()); | 
|  | 137 |  | 
|  | 138 | if (Name[0] == '_') { | 
|  | 139 | Name[0] = '@'; | 
|  | 140 | } else { | 
|  | 141 | Name = '@' + Name; | 
|  | 142 | } | 
|  | 143 | break; | 
|  | 144 | default: | 
|  | 145 | assert(0 && "Unsupported DecorationStyle"); | 
|  | 146 | } | 
|  | 147 | } | 
|  | 148 |  | 
| Anton Korobeynikov | fe047d2 | 2008-07-09 13:27:16 +0000 | [diff] [blame] | 149 | // Substitute old hook with new one temporary | 
| Chris Lattner | b82247b | 2006-10-05 02:43:52 +0000 | [diff] [blame] | 150 | std::string X86ATTAsmPrinter::getSectionForFunction(const Function &F) const { | 
| Anton Korobeynikov | fe047d2 | 2008-07-09 13:27:16 +0000 | [diff] [blame] | 151 | return TAI->SectionForGlobal(&F); | 
| Chris Lattner | b82247b | 2006-10-05 02:43:52 +0000 | [diff] [blame] | 152 | } | 
|  | 153 |  | 
| Anton Korobeynikov | 76b8828 | 2008-06-28 11:09:01 +0000 | [diff] [blame] | 154 | void X86ATTAsmPrinter::emitFunctionHeader(const MachineFunction &MF) { | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 155 | const Function *F = MF.getFunction(); | 
| Anton Korobeynikov | 03dc8bf | 2008-07-09 13:28:19 +0000 | [diff] [blame] | 156 | std::string SectionName = TAI->SectionForGlobal(F); | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 157 |  | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 158 | decorateName(CurrentFnName, F); | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 159 |  | 
| Anton Korobeynikov | 03dc8bf | 2008-07-09 13:28:19 +0000 | [diff] [blame] | 160 | SwitchToTextSection(SectionName.c_str()); | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 161 |  | 
| Evan Cheng | ddc58ff9 | 2008-03-25 22:29:46 +0000 | [diff] [blame] | 162 | unsigned FnAlign = OptimizeForSize ? 1 : 4; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 163 | switch (F->getLinkage()) { | 
|  | 164 | default: assert(0 && "Unknown linkage type!"); | 
|  | 165 | case Function::InternalLinkage:  // Symbols default to internal. | 
| Evan Cheng | ddc58ff9 | 2008-03-25 22:29:46 +0000 | [diff] [blame] | 166 | EmitAlignment(FnAlign, F); | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 167 | break; | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 168 | case Function::DLLExportLinkage: | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 169 | case Function::ExternalLinkage: | 
| Evan Cheng | ddc58ff9 | 2008-03-25 22:29:46 +0000 | [diff] [blame] | 170 | EmitAlignment(FnAlign, F); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 171 | O << "\t.globl\t" << CurrentFnName << '\n'; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 172 | break; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 173 | case Function::LinkOnceLinkage: | 
| Anton Korobeynikov | 24b7ac3 | 2006-10-18 09:12:29 +0000 | [diff] [blame] | 174 | case Function::WeakLinkage: | 
| Evan Cheng | ddc58ff9 | 2008-03-25 22:29:46 +0000 | [diff] [blame] | 175 | EmitAlignment(FnAlign, F); | 
| Jim Laskey | 3b4866e | 2006-07-27 02:05:13 +0000 | [diff] [blame] | 176 | if (Subtarget->isTargetDarwin()) { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 177 | O << "\t.globl\t" << CurrentFnName << '\n'; | 
|  | 178 | O << TAI->getWeakDefDirective() << CurrentFnName << '\n'; | 
| Anton Korobeynikov | 4efbbc9 | 2007-01-03 11:43:14 +0000 | [diff] [blame] | 179 | } else if (Subtarget->isTargetCygMing()) { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 180 | O << "\t.globl\t" << CurrentFnName << "\n" | 
|  | 181 | "\t.linkonce discard\n"; | 
| Anton Korobeynikov | 75b01be | 2006-10-17 20:29:49 +0000 | [diff] [blame] | 182 | } else { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 183 | O << "\t.weak\t" << CurrentFnName << '\n'; | 
| Anton Korobeynikov | 75b01be | 2006-10-17 20:29:49 +0000 | [diff] [blame] | 184 | } | 
|  | 185 | break; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 186 | } | 
| Anton Korobeynikov | ed47329 | 2008-08-08 18:25:07 +0000 | [diff] [blame] | 187 |  | 
|  | 188 | printVisibility(CurrentFnName, F->getVisibility()); | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 189 |  | 
|  | 190 | if (Subtarget->isTargetELF()) | 
| Dan Gohman | 204dece | 2007-07-30 15:08:02 +0000 | [diff] [blame] | 191 | O << "\t.type\t" << CurrentFnName << ",@function\n"; | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 192 | else if (Subtarget->isTargetCygMing()) { | 
|  | 193 | O << "\t.def\t " << CurrentFnName | 
|  | 194 | << ";\t.scl\t" << | 
|  | 195 | (F->getLinkage() == Function::InternalLinkage ? COFF::C_STAT : COFF::C_EXT) | 
|  | 196 | << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) | 
|  | 197 | << ";\t.endef\n"; | 
|  | 198 | } | 
|  | 199 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 200 | O << CurrentFnName << ":\n"; | 
| Anton Korobeynikov | 24b7ac3 | 2006-10-18 09:12:29 +0000 | [diff] [blame] | 201 | // Add some workaround for linkonce linkage on Cygwin\MinGW | 
| Anton Korobeynikov | 4efbbc9 | 2007-01-03 11:43:14 +0000 | [diff] [blame] | 202 | if (Subtarget->isTargetCygMing() && | 
| Anton Korobeynikov | 24b7ac3 | 2006-10-18 09:12:29 +0000 | [diff] [blame] | 203 | (F->getLinkage() == Function::LinkOnceLinkage || | 
|  | 204 | F->getLinkage() == Function::WeakLinkage)) | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 205 | O << "Lllvm$workaround$fake$stub$" << CurrentFnName << ":\n"; | 
| Anton Korobeynikov | 76b8828 | 2008-06-28 11:09:01 +0000 | [diff] [blame] | 206 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 207 |  | 
| Anton Korobeynikov | 76b8828 | 2008-06-28 11:09:01 +0000 | [diff] [blame] | 208 | /// runOnMachineFunction - This uses the printMachineInstruction() | 
|  | 209 | /// method to print assembly for each instruction. | 
|  | 210 | /// | 
|  | 211 | bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) { | 
|  | 212 | const Function *F = MF.getFunction(); | 
|  | 213 | unsigned CC = F->getCallingConv(); | 
|  | 214 |  | 
| Anton Korobeynikov | 76b8828 | 2008-06-28 11:09:01 +0000 | [diff] [blame] | 215 | SetupMachineFunction(MF); | 
|  | 216 | O << "\n\n"; | 
|  | 217 |  | 
|  | 218 | // Populate function information map.  Actually, We don't want to populate | 
|  | 219 | // non-stdcall or non-fastcall functions' information right now. | 
|  | 220 | if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall) | 
|  | 221 | FunctionInfoMap[F] = *MF.getInfo<X86MachineFunctionInfo>(); | 
|  | 222 |  | 
|  | 223 | // Print out constants referenced by the function | 
|  | 224 | EmitConstantPool(MF.getConstantPool()); | 
|  | 225 |  | 
|  | 226 | if (F->hasDLLExportLinkage()) | 
|  | 227 | DLLExportedFns.insert(Mang->makeNameProper(F->getName(), "")); | 
|  | 228 |  | 
|  | 229 | // Print the 'header' of function | 
|  | 230 | emitFunctionHeader(MF); | 
|  | 231 |  | 
|  | 232 | // Emit pre-function debug and/or EH information. | 
|  | 233 | if (TAI->doesSupportDebugInformation() || TAI->doesSupportExceptionHandling()) | 
|  | 234 | DW.BeginFunction(&MF); | 
|  | 235 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 236 | // Print out code for the function. | 
| Dale Johannesen | fe76762 | 2008-04-08 00:37:56 +0000 | [diff] [blame] | 237 | bool hasAnyRealCode = false; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 238 | for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); | 
|  | 239 | I != E; ++I) { | 
|  | 240 | // Print a label for the basic block. | 
| Dan Gohman | c731c97 | 2007-10-03 19:26:29 +0000 | [diff] [blame] | 241 | if (!I->pred_empty()) { | 
| Evan Cheng | c799065 | 2008-02-28 00:43:03 +0000 | [diff] [blame] | 242 | printBasicBlockLabel(I, true, true); | 
| Nate Begeman | b9d4f83 | 2006-05-02 05:37:32 +0000 | [diff] [blame] | 243 | O << '\n'; | 
|  | 244 | } | 
| Bill Wendling | 1a17ef0 | 2008-01-26 09:03:52 +0000 | [diff] [blame] | 245 | for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); | 
|  | 246 | II != IE; ++II) { | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 247 | // Print the assembly for the instruction. | 
| Dan Gohman | fb19f94 | 2008-07-01 00:05:16 +0000 | [diff] [blame] | 248 | if (!II->isLabel()) | 
| Dale Johannesen | fe76762 | 2008-04-08 00:37:56 +0000 | [diff] [blame] | 249 | hasAnyRealCode = true; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 250 | printMachineInstruction(II); | 
|  | 251 | } | 
|  | 252 | } | 
| Evan Cheng | 00884b5 | 2006-08-28 22:14:16 +0000 | [diff] [blame] | 253 |  | 
| Dale Johannesen | fe76762 | 2008-04-08 00:37:56 +0000 | [diff] [blame] | 254 | if (Subtarget->isTargetDarwin() && !hasAnyRealCode) { | 
|  | 255 | // If the function is empty, then we need to emit *something*. Otherwise, | 
|  | 256 | // the function's label might be associated with something that it wasn't | 
|  | 257 | // meant to be associated with. We emit a noop in this situation. | 
|  | 258 | // We are assuming inline asms are code. | 
|  | 259 | O << "\tnop\n"; | 
|  | 260 | } | 
|  | 261 |  | 
| Jim Laskey | a6211dc | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 262 | if (TAI->hasDotTypeDotSizeDirective()) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 263 | O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n'; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 264 |  | 
| Anton Korobeynikov | 76b8828 | 2008-06-28 11:09:01 +0000 | [diff] [blame] | 265 | // Emit post-function debug information. | 
|  | 266 | if (TAI->doesSupportDebugInformation()) | 
| Jim Laskey | cf0166f | 2006-03-23 18:09:44 +0000 | [diff] [blame] | 267 | DW.EndFunction(); | 
| Evan Cheng | 30d7b70 | 2006-03-07 02:02:57 +0000 | [diff] [blame] | 268 |  | 
| Anton Korobeynikov | 4db0090 | 2007-05-05 09:04:50 +0000 | [diff] [blame] | 269 | // Print out jump tables referenced by the function. | 
|  | 270 | EmitJumpTableInfo(MF.getJumpTableInfo(), MF); | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 271 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 272 | // We didn't modify anything. | 
|  | 273 | return false; | 
|  | 274 | } | 
|  | 275 |  | 
| Rafael Espindola | 29479df | 2008-06-09 09:52:31 +0000 | [diff] [blame] | 276 | static inline bool shouldPrintGOT(TargetMachine &TM, const X86Subtarget* ST) { | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 277 | return ST->isPICStyleGOT() && TM.getRelocationModel() == Reloc::PIC_; | 
|  | 278 | } | 
|  | 279 |  | 
| Rafael Espindola | 29479df | 2008-06-09 09:52:31 +0000 | [diff] [blame] | 280 | static inline bool shouldPrintPLT(TargetMachine &TM, const X86Subtarget* ST) { | 
|  | 281 | return ST->isTargetELF() && TM.getRelocationModel() == Reloc::PIC_ && | 
|  | 282 | (ST->isPICStyleRIPRel() || ST->isPICStyleGOT()); | 
|  | 283 | } | 
|  | 284 |  | 
|  | 285 | static inline bool shouldPrintStub(TargetMachine &TM, const X86Subtarget* ST) { | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 286 | return ST->isPICStyleStub() && TM.getRelocationModel() != Reloc::Static; | 
|  | 287 | } | 
|  | 288 |  | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 289 | void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, | 
| Evan Cheng | dd60ca0 | 2006-12-05 19:50:18 +0000 | [diff] [blame] | 290 | const char *Modifier, bool NotRIPRel) { | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 291 | const MachineOperand &MO = MI->getOperand(OpNo); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 292 | switch (MO.getType()) { | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 293 | case MachineOperand::MO_Register: { | 
| Dan Gohman | 3a4be0f | 2008-02-10 18:45:23 +0000 | [diff] [blame] | 294 | assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 295 | "Virtual registers should not make it this far!"); | 
|  | 296 | O << '%'; | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 297 | unsigned Reg = MO.getReg(); | 
| Evan Cheng | cfaffdd | 2006-05-31 22:34:26 +0000 | [diff] [blame] | 298 | if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) { | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 299 | MVT VT = (strcmp(Modifier+6,"64") == 0) ? | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 300 | MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 : | 
|  | 301 | ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8)); | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 302 | Reg = getX86SubSuperRegister(Reg, VT); | 
|  | 303 | } | 
| Evan Cheng | 90a92af | 2008-07-07 22:21:06 +0000 | [diff] [blame] | 304 | O << TRI->getAsmName(Reg); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 305 | return; | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 306 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 307 |  | 
| Chris Lattner | fef7a2d | 2006-05-04 17:21:20 +0000 | [diff] [blame] | 308 | case MachineOperand::MO_Immediate: | 
| Chris Lattner | e4bf50c | 2007-01-25 02:53:24 +0000 | [diff] [blame] | 309 | if (!Modifier || | 
|  | 310 | (strcmp(Modifier, "debug") && strcmp(Modifier, "mem"))) | 
| Evan Cheng | 30d7b70 | 2006-03-07 02:02:57 +0000 | [diff] [blame] | 311 | O << '$'; | 
| Chris Lattner | 5c46378 | 2007-12-30 20:49:49 +0000 | [diff] [blame] | 312 | O << MO.getImm(); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 313 | return; | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 314 | case MachineOperand::MO_MachineBasicBlock: | 
| Chris Lattner | a5bb370 | 2007-12-30 23:10:15 +0000 | [diff] [blame] | 315 | printBasicBlockLabel(MO.getMBB()); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 316 | return; | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 317 | case MachineOperand::MO_JumpTableIndex: { | 
|  | 318 | bool isMemOp  = Modifier && !strcmp(Modifier, "mem"); | 
|  | 319 | if (!isMemOp) O << '$'; | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 320 | O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' | 
| Chris Lattner | a5bb370 | 2007-12-30 23:10:15 +0000 | [diff] [blame] | 321 | << MO.getIndex(); | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 322 |  | 
|  | 323 | if (TM.getRelocationModel() == Reloc::PIC_) { | 
|  | 324 | if (Subtarget->isPICStyleStub()) | 
| Evan Cheng | cdf3609 | 2007-10-14 05:57:21 +0000 | [diff] [blame] | 325 | O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber() | 
|  | 326 | << "$pb\""; | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 327 | else if (Subtarget->isPICStyleGOT()) | 
|  | 328 | O << "@GOTOFF"; | 
|  | 329 | } | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 330 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 331 | if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel) | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 332 | O << "(%rip)"; | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 333 | return; | 
|  | 334 | } | 
| Evan Cheng | 75b8783 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 335 | case MachineOperand::MO_ConstantPoolIndex: { | 
|  | 336 | bool isMemOp  = Modifier && !strcmp(Modifier, "mem"); | 
|  | 337 | if (!isMemOp) O << '$'; | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 338 | O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' | 
| Chris Lattner | a5bb370 | 2007-12-30 23:10:15 +0000 | [diff] [blame] | 339 | << MO.getIndex(); | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 340 |  | 
|  | 341 | if (TM.getRelocationModel() == Reloc::PIC_) { | 
|  | 342 | if (Subtarget->isPICStyleStub()) | 
| Evan Cheng | cdf3609 | 2007-10-14 05:57:21 +0000 | [diff] [blame] | 343 | O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber() | 
|  | 344 | << "$pb\""; | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 345 | else if (Subtarget->isPICStyleGOT()) | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 346 | O << "@GOTOFF"; | 
|  | 347 | } | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 348 |  | 
| Evan Cheng | 75b8783 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 349 | int Offset = MO.getOffset(); | 
|  | 350 | if (Offset > 0) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 351 | O << '+' << Offset; | 
| Evan Cheng | 75b8783 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 352 | else if (Offset < 0) | 
|  | 353 | O << Offset; | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 354 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 355 | if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel) | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 356 | O << "(%rip)"; | 
| Evan Cheng | 75b8783 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 357 | return; | 
|  | 358 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 359 | case MachineOperand::MO_GlobalAddress: { | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 360 | bool isCallOp = Modifier && !strcmp(Modifier, "call"); | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 361 | bool isMemOp  = Modifier && !strcmp(Modifier, "mem"); | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 362 | bool needCloseParen = false; | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 363 |  | 
| Anton Korobeynikov | e8fa50f | 2008-03-11 22:38:53 +0000 | [diff] [blame] | 364 | const GlobalValue *GV = MO.getGlobal(); | 
|  | 365 | const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); | 
|  | 366 | if (!GVar) { | 
| Anton Korobeynikov | 2fa7518 | 2008-03-22 07:53:40 +0000 | [diff] [blame] | 367 | // If GV is an alias then use the aliasee for determining | 
|  | 368 | // thread-localness. | 
| Anton Korobeynikov | e8fa50f | 2008-03-11 22:38:53 +0000 | [diff] [blame] | 369 | if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) | 
|  | 370 | GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal()); | 
|  | 371 | } | 
|  | 372 |  | 
| Lauro Ramos Venancio | 2518889 | 2007-04-20 21:38:10 +0000 | [diff] [blame] | 373 | bool isThreadLocal = GVar && GVar->isThreadLocal(); | 
|  | 374 |  | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 375 | std::string Name = Mang->getValueName(GV); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 376 | decorateName(Name, GV); | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 377 |  | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 378 | if (!isMemOp && !isCallOp) | 
|  | 379 | O << '$'; | 
|  | 380 | else if (Name[0] == '$') { | 
|  | 381 | // The name begins with a dollar-sign. In order to avoid having it look | 
|  | 382 | // like an integer immediate to the assembler, enclose it in parens. | 
|  | 383 | O << '('; | 
|  | 384 | needCloseParen = true; | 
|  | 385 | } | 
|  | 386 |  | 
| Rafael Espindola | 29479df | 2008-06-09 09:52:31 +0000 | [diff] [blame] | 387 | if (shouldPrintStub(TM, Subtarget)) { | 
| Evan Cheng | 59ca6a8 | 2007-06-04 18:54:57 +0000 | [diff] [blame] | 388 | // Link-once, declaration, or Weakly-linked global variables need | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 389 | // non-lazily-resolved stubs | 
| Anton Korobeynikov | 577c45d | 2008-07-09 13:27:59 +0000 | [diff] [blame] | 390 | if (GV->isDeclaration() || GV->isWeakForLinker()) { | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 391 | // Dynamically-resolved functions need a stub for the function. | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 392 | if (isCallOp && isa<Function>(GV)) { | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 393 | FnStubs.insert(Name); | 
| Dale Johannesen | 5bf742f | 2008-05-19 21:38:18 +0000 | [diff] [blame] | 394 | printSuffixedName(Name, "$stub"); | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 395 | } else { | 
|  | 396 | GVStubs.insert(Name); | 
| Dale Johannesen | 5bf742f | 2008-05-19 21:38:18 +0000 | [diff] [blame] | 397 | printSuffixedName(Name, "$non_lazy_ptr"); | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 398 | } | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 399 | } else { | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 400 | if (GV->hasDLLImportLinkage()) | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 401 | O << "__imp_"; | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 402 | O << Name; | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 403 | } | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 404 |  | 
| Chris Lattner | 9e56e5c | 2006-07-26 21:12:04 +0000 | [diff] [blame] | 405 | if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_) | 
| Evan Cheng | f55b738 | 2008-01-05 00:41:47 +0000 | [diff] [blame] | 406 | O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget); | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 407 | } else { | 
|  | 408 | if (GV->hasDLLImportLinkage()) { | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 409 | O << "__imp_"; | 
|  | 410 | } | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 411 | O << Name; | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 412 |  | 
| Rafael Espindola | 29479df | 2008-06-09 09:52:31 +0000 | [diff] [blame] | 413 | if (isCallOp) { | 
|  | 414 | if (shouldPrintPLT(TM, Subtarget)) { | 
|  | 415 | // Assemble call via PLT for externally visible symbols | 
|  | 416 | if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() && | 
|  | 417 | !GV->hasInternalLinkage()) | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 418 | O << "@PLT"; | 
|  | 419 | } | 
| Reid Spencer | 5301e7c | 2007-01-30 20:08:39 +0000 | [diff] [blame] | 420 | if (Subtarget->isTargetCygMing() && GV->isDeclaration()) | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 421 | // Save function name for later type emission | 
|  | 422 | FnStubs.insert(Name); | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 423 | } | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 424 | } | 
| Anton Korobeynikov | 12c9494 | 2006-12-01 00:25:12 +0000 | [diff] [blame] | 425 |  | 
| Evan Cheng | 5b02034 | 2006-12-01 07:38:23 +0000 | [diff] [blame] | 426 | if (GV->hasExternalWeakLinkage()) | 
| Rafael Espindola | d7998d0 | 2006-12-18 03:37:18 +0000 | [diff] [blame] | 427 | ExtWeakSymbols.insert(GV); | 
| Anton Korobeynikov | 9205c85 | 2008-05-04 21:36:32 +0000 | [diff] [blame] | 428 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 429 | int Offset = MO.getOffset(); | 
|  | 430 | if (Offset > 0) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 431 | O << '+' << Offset; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 432 | else if (Offset < 0) | 
|  | 433 | O << Offset; | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 434 |  | 
| Lauro Ramos Venancio | 2518889 | 2007-04-20 21:38:10 +0000 | [diff] [blame] | 435 | if (isThreadLocal) { | 
| Anton Korobeynikov | 9205c85 | 2008-05-04 21:36:32 +0000 | [diff] [blame] | 436 | if (TM.getRelocationModel() == Reloc::PIC_ || Subtarget->is64Bit()) | 
| Lauro Ramos Venancio | 2518889 | 2007-04-20 21:38:10 +0000 | [diff] [blame] | 437 | O << "@TLSGD"; // general dynamic TLS model | 
|  | 438 | else | 
|  | 439 | if (GV->isDeclaration()) | 
|  | 440 | O << "@INDNTPOFF"; // initial exec TLS model | 
|  | 441 | else | 
|  | 442 | O << "@NTPOFF"; // local exec TLS model | 
|  | 443 | } else if (isMemOp) { | 
| Rafael Espindola | 29479df | 2008-06-09 09:52:31 +0000 | [diff] [blame] | 444 | if (shouldPrintGOT(TM, Subtarget)) { | 
| Anton Korobeynikov | 3f6d528 | 2007-01-17 10:33:08 +0000 | [diff] [blame] | 445 | if (Subtarget->GVRequiresExtraLoad(GV, TM, false)) | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 446 | O << "@GOT"; | 
| Anton Korobeynikov | 3f6d528 | 2007-01-17 10:33:08 +0000 | [diff] [blame] | 447 | else | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 448 | O << "@GOTOFF"; | 
| Chris Lattner | 9329e78 | 2007-11-04 19:23:28 +0000 | [diff] [blame] | 449 | } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel && | 
|  | 450 | TM.getRelocationModel() != Reloc::Static) { | 
| Anton Korobeynikov | c7ffe0f | 2008-01-20 13:59:37 +0000 | [diff] [blame] | 451 | if (Subtarget->GVRequiresExtraLoad(GV, TM, false)) | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 452 | O << "@GOTPCREL"; | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 453 |  | 
|  | 454 | if (needCloseParen) { | 
|  | 455 | needCloseParen = false; | 
|  | 456 | O << ')'; | 
|  | 457 | } | 
|  | 458 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 459 | // Use rip when possible to reduce code size, except when | 
|  | 460 | // index or base register are also part of the address. e.g. | 
|  | 461 | // foo(%rip)(%rcx,%rax,4) is not legal | 
|  | 462 | O << "(%rip)"; | 
|  | 463 | } | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 464 | } | 
|  | 465 |  | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 466 | if (needCloseParen) | 
|  | 467 | O << ')'; | 
|  | 468 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 469 | return; | 
|  | 470 | } | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 471 | case MachineOperand::MO_ExternalSymbol: { | 
|  | 472 | bool isCallOp = Modifier && !strcmp(Modifier, "call"); | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 473 | bool needCloseParen = false; | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 474 | std::string Name(TAI->getGlobalPrefix()); | 
|  | 475 | Name += MO.getSymbolName(); | 
| Rafael Espindola | 29479df | 2008-06-09 09:52:31 +0000 | [diff] [blame] | 476 | if (isCallOp && shouldPrintStub(TM, Subtarget)) { | 
| Nate Begeman | b62a4c8 | 2005-07-08 00:23:26 +0000 | [diff] [blame] | 477 | FnStubs.insert(Name); | 
| Dale Johannesen | 5bf742f | 2008-05-19 21:38:18 +0000 | [diff] [blame] | 478 | printSuffixedName(Name, "$stub"); | 
| Nate Begeman | b62a4c8 | 2005-07-08 00:23:26 +0000 | [diff] [blame] | 479 | return; | 
|  | 480 | } | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 481 | if (!isCallOp) | 
|  | 482 | O << '$'; | 
|  | 483 | else if (Name[0] == '$') { | 
|  | 484 | // The name begins with a dollar-sign. In order to avoid having it look | 
|  | 485 | // like an integer immediate to the assembler, enclose it in parens. | 
|  | 486 | O << '('; | 
|  | 487 | needCloseParen = true; | 
|  | 488 | } | 
|  | 489 |  | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 490 | O << Name; | 
|  | 491 |  | 
| Rafael Espindola | 29479df | 2008-06-09 09:52:31 +0000 | [diff] [blame] | 492 | if (shouldPrintPLT(TM, Subtarget)) { | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 493 | std::string GOTName(TAI->getGlobalPrefix()); | 
|  | 494 | GOTName+="_GLOBAL_OFFSET_TABLE_"; | 
|  | 495 | if (Name == GOTName) | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 496 | // HACK! Emit extra offset to PC during printing GOT offset to | 
|  | 497 | // compensate for the size of popl instruction. The resulting code | 
|  | 498 | // should look like: | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 499 | //   call .piclabel | 
|  | 500 | // piclabel: | 
|  | 501 | //   popl %some_register | 
|  | 502 | //   addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 503 | O << " + [.-" | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 504 | << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']'; | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 505 |  | 
|  | 506 | if (isCallOp) | 
|  | 507 | O << "@PLT"; | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 508 | } | 
|  | 509 |  | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 510 | if (needCloseParen) | 
|  | 511 | O << ')'; | 
|  | 512 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 513 | if (!isCallOp && Subtarget->isPICStyleRIPRel()) | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 514 | O << "(%rip)"; | 
|  | 515 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 516 | return; | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 517 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 518 | default: | 
|  | 519 | O << "<unknown operand type>"; return; | 
|  | 520 | } | 
|  | 521 | } | 
|  | 522 |  | 
| Nate Begeman | 6f8c1ac | 2005-11-30 18:54:35 +0000 | [diff] [blame] | 523 | void X86ATTAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) { | 
| Chris Lattner | 5c46378 | 2007-12-30 20:49:49 +0000 | [diff] [blame] | 524 | unsigned char value = MI->getOperand(Op).getImm(); | 
| Nate Begeman | 0f38dc4 | 2005-07-14 22:52:25 +0000 | [diff] [blame] | 525 | assert(value <= 7 && "Invalid ssecc argument!"); | 
|  | 526 | switch (value) { | 
|  | 527 | case 0: O << "eq"; break; | 
|  | 528 | case 1: O << "lt"; break; | 
|  | 529 | case 2: O << "le"; break; | 
|  | 530 | case 3: O << "unord"; break; | 
|  | 531 | case 4: O << "neq"; break; | 
|  | 532 | case 5: O << "nlt"; break; | 
|  | 533 | case 6: O << "nle"; break; | 
|  | 534 | case 7: O << "ord"; break; | 
|  | 535 | } | 
|  | 536 | } | 
|  | 537 |  | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 538 | void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op, | 
|  | 539 | const char *Modifier){ | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 540 | assert(isMem(MI, Op) && "Invalid memory reference!"); | 
| Chris Lattner | 5544e17 | 2007-01-14 00:13:07 +0000 | [diff] [blame] | 541 | MachineOperand BaseReg  = MI->getOperand(Op); | 
|  | 542 | MachineOperand IndexReg = MI->getOperand(Op+2); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 543 | const MachineOperand &DispSpec = MI->getOperand(Op+3); | 
|  | 544 |  | 
| Evan Cheng | dd60ca0 | 2006-12-05 19:50:18 +0000 | [diff] [blame] | 545 | bool NotRIPRel = IndexReg.getReg() || BaseReg.getReg(); | 
| Evan Cheng | 6d46414 | 2006-08-29 22:14:48 +0000 | [diff] [blame] | 546 | if (DispSpec.isGlobalAddress() || | 
|  | 547 | DispSpec.isConstantPoolIndex() || | 
|  | 548 | DispSpec.isJumpTableIndex()) { | 
| Evan Cheng | dd60ca0 | 2006-12-05 19:50:18 +0000 | [diff] [blame] | 549 | printOperand(MI, Op+3, "mem", NotRIPRel); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 550 | } else { | 
| Chris Lattner | 5c46378 | 2007-12-30 20:49:49 +0000 | [diff] [blame] | 551 | int DispVal = DispSpec.getImm(); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 552 | if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) | 
|  | 553 | O << DispVal; | 
|  | 554 | } | 
|  | 555 |  | 
|  | 556 | if (IndexReg.getReg() || BaseReg.getReg()) { | 
| Chris Lattner | 5c46378 | 2007-12-30 20:49:49 +0000 | [diff] [blame] | 557 | unsigned ScaleVal = MI->getOperand(Op+1).getImm(); | 
| Chris Lattner | 5544e17 | 2007-01-14 00:13:07 +0000 | [diff] [blame] | 558 | unsigned BaseRegOperand = 0, IndexRegOperand = 2; | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 559 |  | 
| Chris Lattner | 5544e17 | 2007-01-14 00:13:07 +0000 | [diff] [blame] | 560 | // There are cases where we can end up with ESP/RSP in the indexreg slot. | 
|  | 561 | // If this happens, swap the base/index register to support assemblers that | 
|  | 562 | // don't work when the index is *SP. | 
|  | 563 | if (IndexReg.getReg() == X86::ESP || IndexReg.getReg() == X86::RSP) { | 
|  | 564 | assert(ScaleVal == 1 && "Scale not supported for stack pointer!"); | 
|  | 565 | std::swap(BaseReg, IndexReg); | 
|  | 566 | std::swap(BaseRegOperand, IndexRegOperand); | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 567 | } | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 568 |  | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 569 | O << '('; | 
| Chris Lattner | 5544e17 | 2007-01-14 00:13:07 +0000 | [diff] [blame] | 570 | if (BaseReg.getReg()) | 
|  | 571 | printOperand(MI, Op+BaseRegOperand, Modifier); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 572 |  | 
|  | 573 | if (IndexReg.getReg()) { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 574 | O << ','; | 
| Chris Lattner | 5544e17 | 2007-01-14 00:13:07 +0000 | [diff] [blame] | 575 | printOperand(MI, Op+IndexRegOperand, Modifier); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 576 | if (ScaleVal != 1) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 577 | O << ',' << ScaleVal; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 578 | } | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 579 | O << ')'; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 580 | } | 
|  | 581 | } | 
|  | 582 |  | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 583 | void X86ATTAsmPrinter::printPICJumpTableSetLabel(unsigned uid, | 
| Evan Cheng | 797d56f | 2007-11-09 01:32:10 +0000 | [diff] [blame] | 584 | const MachineBasicBlock *MBB) const { | 
|  | 585 | if (!TAI->getSetDirective()) | 
|  | 586 | return; | 
| Anton Korobeynikov | 2c63878 | 2007-11-14 09:18:41 +0000 | [diff] [blame] | 587 |  | 
|  | 588 | // We don't need .set machinery if we have GOT-style relocations | 
|  | 589 | if (Subtarget->isPICStyleGOT()) | 
|  | 590 | return; | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 591 |  | 
| Evan Cheng | 797d56f | 2007-11-09 01:32:10 +0000 | [diff] [blame] | 592 | O << TAI->getSetDirective() << ' ' << TAI->getPrivateGlobalPrefix() | 
|  | 593 | << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ','; | 
| Evan Cheng | c799065 | 2008-02-28 00:43:03 +0000 | [diff] [blame] | 594 | printBasicBlockLabel(MBB, false, false, false); | 
| Evan Cheng | fb13fd6 | 2007-11-09 19:11:23 +0000 | [diff] [blame] | 595 | if (Subtarget->isPICStyleRIPRel()) | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 596 | O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() | 
| Evan Cheng | fb13fd6 | 2007-11-09 19:11:23 +0000 | [diff] [blame] | 597 | << '_' << uid << '\n'; | 
|  | 598 | else | 
| Evan Cheng | f55b738 | 2008-01-05 00:41:47 +0000 | [diff] [blame] | 599 | O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << '\n'; | 
| Evan Cheng | 797d56f | 2007-11-09 01:32:10 +0000 | [diff] [blame] | 600 | } | 
|  | 601 |  | 
| Evan Cheng | 5588de9 | 2006-02-18 00:15:05 +0000 | [diff] [blame] | 602 | void X86ATTAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) { | 
| Evan Cheng | f55b738 | 2008-01-05 00:41:47 +0000 | [diff] [blame] | 603 | std::string label = getPICLabelString(getFunctionNumber(), TAI, Subtarget); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 604 | O << label << '\n' << label << ':'; | 
| Evan Cheng | 5588de9 | 2006-02-18 00:15:05 +0000 | [diff] [blame] | 605 | } | 
|  | 606 |  | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 607 |  | 
| Anton Korobeynikov | 2c63878 | 2007-11-14 09:18:41 +0000 | [diff] [blame] | 608 | void X86ATTAsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI, | 
|  | 609 | const MachineBasicBlock *MBB, | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 610 | unsigned uid) const | 
|  | 611 | { | 
| Anton Korobeynikov | 2c63878 | 2007-11-14 09:18:41 +0000 | [diff] [blame] | 612 | const char *JTEntryDirective = MJTI->getEntrySize() == 4 ? | 
|  | 613 | TAI->getData32bitsDirective() : TAI->getData64bitsDirective(); | 
|  | 614 |  | 
|  | 615 | O << JTEntryDirective << ' '; | 
|  | 616 |  | 
|  | 617 | if (TM.getRelocationModel() == Reloc::PIC_) { | 
|  | 618 | if (Subtarget->isPICStyleRIPRel() || Subtarget->isPICStyleStub()) { | 
|  | 619 | O << TAI->getPrivateGlobalPrefix() << getFunctionNumber() | 
|  | 620 | << '_' << uid << "_set_" << MBB->getNumber(); | 
|  | 621 | } else if (Subtarget->isPICStyleGOT()) { | 
| Evan Cheng | c799065 | 2008-02-28 00:43:03 +0000 | [diff] [blame] | 622 | printBasicBlockLabel(MBB, false, false, false); | 
| Anton Korobeynikov | 2c63878 | 2007-11-14 09:18:41 +0000 | [diff] [blame] | 623 | O << "@GOTOFF"; | 
|  | 624 | } else | 
|  | 625 | assert(0 && "Don't know how to print MBB label for this PIC mode"); | 
|  | 626 | } else | 
| Evan Cheng | c799065 | 2008-02-28 00:43:03 +0000 | [diff] [blame] | 627 | printBasicBlockLabel(MBB, false, false, false); | 
| Anton Korobeynikov | 2c63878 | 2007-11-14 09:18:41 +0000 | [diff] [blame] | 628 | } | 
|  | 629 |  | 
| Anton Korobeynikov | 3c21b05 | 2008-06-28 11:10:06 +0000 | [diff] [blame] | 630 | bool X86ATTAsmPrinter::printAsmMRegister(const MachineOperand &MO, | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 631 | const char Mode) { | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 632 | unsigned Reg = MO.getReg(); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 633 | switch (Mode) { | 
|  | 634 | default: return true;  // Unknown mode. | 
|  | 635 | case 'b': // Print QImode register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 636 | Reg = getX86SubSuperRegister(Reg, MVT::i8); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 637 | break; | 
|  | 638 | case 'h': // Print QImode high register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 639 | Reg = getX86SubSuperRegister(Reg, MVT::i8, true); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 640 | break; | 
|  | 641 | case 'w': // Print HImode register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 642 | Reg = getX86SubSuperRegister(Reg, MVT::i16); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 643 | break; | 
|  | 644 | case 'k': // Print SImode register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 645 | Reg = getX86SubSuperRegister(Reg, MVT::i32); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 646 | break; | 
| Chris Lattner | 5e99fd8 | 2007-10-29 03:09:07 +0000 | [diff] [blame] | 647 | case 'q': // Print DImode register | 
|  | 648 | Reg = getX86SubSuperRegister(Reg, MVT::i64); | 
|  | 649 | break; | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 650 | } | 
|  | 651 |  | 
| Evan Cheng | 90a92af | 2008-07-07 22:21:06 +0000 | [diff] [blame] | 652 | O << '%'<< TRI->getAsmName(Reg); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 653 | return false; | 
|  | 654 | } | 
|  | 655 |  | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 656 | /// PrintAsmOperand - Print out an operand for an inline asm expression. | 
|  | 657 | /// | 
| Anton Korobeynikov | a54216a | 2008-06-28 11:09:48 +0000 | [diff] [blame] | 658 | bool X86ATTAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 659 | unsigned AsmVariant, | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 660 | const char *ExtraCode) { | 
|  | 661 | // Does this asm operand have a single letter operand modifier? | 
|  | 662 | if (ExtraCode && ExtraCode[0]) { | 
|  | 663 | if (ExtraCode[1] != 0) return true; // Unknown modifier. | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 664 |  | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 665 | switch (ExtraCode[0]) { | 
|  | 666 | default: return true;  // Unknown modifier. | 
| Chris Lattner | e4bf50c | 2007-01-25 02:53:24 +0000 | [diff] [blame] | 667 | case 'c': // Don't print "$" before a global var name or constant. | 
| Chris Lattner | 60ce558 | 2006-10-31 20:12:30 +0000 | [diff] [blame] | 668 | printOperand(MI, OpNo, "mem"); | 
|  | 669 | return false; | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 670 | case 'b': // Print QImode register | 
|  | 671 | case 'h': // Print QImode high register | 
|  | 672 | case 'w': // Print HImode register | 
|  | 673 | case 'k': // Print SImode register | 
| Chris Lattner | 5e99fd8 | 2007-10-29 03:09:07 +0000 | [diff] [blame] | 674 | case 'q': // Print DImode register | 
| Dan Gohman | 9da02f5 | 2007-09-14 20:33:02 +0000 | [diff] [blame] | 675 | if (MI->getOperand(OpNo).isRegister()) | 
| Chris Lattner | 927f30d | 2007-03-25 02:01:03 +0000 | [diff] [blame] | 676 | return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]); | 
|  | 677 | printOperand(MI, OpNo); | 
|  | 678 | return false; | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 679 |  | 
| Chris Lattner | c8ddca7 | 2007-03-25 01:44:57 +0000 | [diff] [blame] | 680 | case 'P': // Don't print @PLT, but do print as memory. | 
|  | 681 | printOperand(MI, OpNo, "mem"); | 
|  | 682 | return false; | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 683 | } | 
|  | 684 | } | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 685 |  | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 686 | printOperand(MI, OpNo); | 
|  | 687 | return false; | 
|  | 688 | } | 
|  | 689 |  | 
| Anton Korobeynikov | 3c21b05 | 2008-06-28 11:10:06 +0000 | [diff] [blame] | 690 | bool X86ATTAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 691 | unsigned OpNo, | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 692 | unsigned AsmVariant, | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 693 | const char *ExtraCode) { | 
| Chris Lattner | 5e99fd8 | 2007-10-29 03:09:07 +0000 | [diff] [blame] | 694 | if (ExtraCode && ExtraCode[0]) { | 
|  | 695 | if (ExtraCode[1] != 0) return true; // Unknown modifier. | 
| Anton Korobeynikov | 5643cb7 | 2008-06-28 11:08:09 +0000 | [diff] [blame] | 696 |  | 
| Chris Lattner | 5e99fd8 | 2007-10-29 03:09:07 +0000 | [diff] [blame] | 697 | switch (ExtraCode[0]) { | 
|  | 698 | default: return true;  // Unknown modifier. | 
|  | 699 | case 'b': // Print QImode register | 
|  | 700 | case 'h': // Print QImode high register | 
|  | 701 | case 'w': // Print HImode register | 
|  | 702 | case 'k': // Print SImode register | 
|  | 703 | case 'q': // Print SImode register | 
|  | 704 | // These only apply to registers, ignore on mem. | 
|  | 705 | break; | 
|  | 706 | } | 
|  | 707 | } | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 708 | printMemReference(MI, OpNo); | 
|  | 709 | return false; | 
|  | 710 | } | 
|  | 711 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 712 | /// printMachineInstruction -- Print out a single X86 LLVM instruction | 
| Dan Gohman | e33c4b7 | 2007-06-25 15:11:25 +0000 | [diff] [blame] | 713 | /// MI in AT&T syntax to the current output stream. | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 714 | /// | 
|  | 715 | void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) { | 
|  | 716 | ++EmittedInsts; | 
| Evan Cheng | fcdce6d | 2006-01-26 02:27:43 +0000 | [diff] [blame] | 717 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 718 | // Call the autogenerated instruction printer routines. | 
|  | 719 | printInstruction(MI); | 
|  | 720 | } | 
|  | 721 |  | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 722 | /// doInitialization | 
|  | 723 | bool X86ATTAsmPrinter::doInitialization(Module &M) { | 
|  | 724 | if (TAI->doesSupportDebugInformation()) { | 
|  | 725 | // Emit initial debug information. | 
|  | 726 | DW.BeginModule(&M); | 
|  | 727 | } | 
|  | 728 |  | 
| Evan Cheng | 49c8e68 | 2008-07-09 06:36:53 +0000 | [diff] [blame] | 729 | bool Result = AsmPrinter::doInitialization(M); | 
|  | 730 |  | 
| Dale Johannesen | 605d386 | 2008-07-09 20:55:35 +0000 | [diff] [blame] | 731 | if (TAI->doesSupportDebugInformation()) { | 
|  | 732 | // Let PassManager know we need debug information and relay | 
|  | 733 | // the MachineModuleInfo address on to DwarfWriter. | 
|  | 734 | // AsmPrinter::doInitialization did this analysis. | 
|  | 735 | MMI = getAnalysisToUpdate<MachineModuleInfo>(); | 
|  | 736 | DW.SetModuleInfo(MMI); | 
|  | 737 | } | 
|  | 738 |  | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 739 | // Darwin wants symbols to be quoted if they have complex names. | 
|  | 740 | if (Subtarget->isTargetDarwin()) | 
|  | 741 | Mang->setUseQuotes(true); | 
|  | 742 |  | 
|  | 743 | return Result; | 
|  | 744 | } | 
|  | 745 |  | 
|  | 746 |  | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 747 | void X86ATTAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 748 | const TargetData *TD = TM.getTargetData(); | 
|  | 749 |  | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 750 | if (!GVar->hasInitializer()) | 
|  | 751 | return;   // External global require no code | 
|  | 752 |  | 
|  | 753 | // Check to see if this is a special global used by LLVM, if so, emit it. | 
|  | 754 | if (EmitSpecialLLVMGlobal(GVar)) { | 
|  | 755 | if (Subtarget->isTargetDarwin() && | 
|  | 756 | TM.getRelocationModel() == Reloc::Static) { | 
|  | 757 | if (GVar->getName() == "llvm.global_ctors") | 
|  | 758 | O << ".reference .constructors_used\n"; | 
|  | 759 | else if (GVar->getName() == "llvm.global_dtors") | 
|  | 760 | O << ".reference .destructors_used\n"; | 
|  | 761 | } | 
|  | 762 | return; | 
|  | 763 | } | 
|  | 764 |  | 
| Anton Korobeynikov | 0408352 | 2008-08-07 09:54:23 +0000 | [diff] [blame] | 765 | std::string SectionName = TAI->SectionForGlobal(GVar); | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 766 | std::string name = Mang->getValueName(GVar); | 
|  | 767 | Constant *C = GVar->getInitializer(); | 
|  | 768 | const Type *Type = C->getType(); | 
|  | 769 | unsigned Size = TD->getABITypeSize(Type); | 
|  | 770 | unsigned Align = TD->getPreferredAlignmentLog(GVar); | 
|  | 771 |  | 
| Anton Korobeynikov | ed47329 | 2008-08-08 18:25:07 +0000 | [diff] [blame] | 772 | printVisibility(name, GVar->getVisibility()); | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 773 |  | 
|  | 774 | if (Subtarget->isTargetELF()) | 
|  | 775 | O << "\t.type\t" << name << ",@object\n"; | 
|  | 776 |  | 
| Anton Korobeynikov | fe047d2 | 2008-07-09 13:27:16 +0000 | [diff] [blame] | 777 | SwitchToDataSection(SectionName.c_str()); | 
|  | 778 |  | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 779 | if (C->isNullValue() && !GVar->hasSection()) { | 
| Anton Korobeynikov | fe047d2 | 2008-07-09 13:27:16 +0000 | [diff] [blame] | 780 | // FIXME: This seems to be pretty darwin-specific | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 781 | if (GVar->hasExternalLinkage()) { | 
|  | 782 | if (const char *Directive = TAI->getZeroFillDirective()) { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 783 | O << "\t.globl " << name << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 784 | O << Directive << "__DATA, __common, " << name << ", " | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 785 | << Size << ", " << Align << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 786 | return; | 
|  | 787 | } | 
|  | 788 | } | 
|  | 789 |  | 
|  | 790 | if (!GVar->isThreadLocal() && | 
| Anton Korobeynikov | 577c45d | 2008-07-09 13:27:59 +0000 | [diff] [blame] | 791 | (GVar->hasInternalLinkage() || GVar->isWeakForLinker())) { | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 792 | if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it. | 
| Anton Korobeynikov | fe047d2 | 2008-07-09 13:27:16 +0000 | [diff] [blame] | 793 |  | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 794 | if (TAI->getLCOMMDirective() != NULL) { | 
|  | 795 | if (GVar->hasInternalLinkage()) { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 796 | O << TAI->getLCOMMDirective() << name << ',' << Size; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 797 | if (Subtarget->isTargetDarwin()) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 798 | O << ',' << Align; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 799 | } else if (Subtarget->isTargetDarwin() && !GVar->hasCommonLinkage()) { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 800 | O << "\t.globl " << name << '\n' | 
|  | 801 | << TAI->getWeakDefDirective() << name << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 802 | EmitAlignment(Align, GVar); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 803 | O << name << ":\t\t\t\t" << TAI->getCommentString() << ' '; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 804 | PrintUnmangledNameSafely(GVar, O); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 805 | O << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 806 | EmitGlobalConstant(C); | 
|  | 807 | return; | 
|  | 808 | } else { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 809 | O << TAI->getCOMMDirective()  << name << ',' << Size; | 
| Anton Korobeynikov | 793108b | 2008-08-08 18:25:52 +0000 | [diff] [blame] | 810 | if (TAI->getCOMMDirectiveTakesAlignment()) | 
|  | 811 | O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 812 | } | 
|  | 813 | } else { | 
|  | 814 | if (!Subtarget->isTargetCygMing()) { | 
|  | 815 | if (GVar->hasInternalLinkage()) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 816 | O << "\t.local\t" << name << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 817 | } | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 818 | O << TAI->getCOMMDirective()  << name << ',' << Size; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 819 | if (TAI->getCOMMDirectiveTakesAlignment()) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 820 | O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 821 | } | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 822 | O << "\t\t" << TAI->getCommentString() << ' '; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 823 | PrintUnmangledNameSafely(GVar, O); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 824 | O << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 825 | return; | 
|  | 826 | } | 
|  | 827 | } | 
|  | 828 |  | 
|  | 829 | switch (GVar->getLinkage()) { | 
| Evan Cheng | 319548b | 2008-08-08 06:43:59 +0000 | [diff] [blame] | 830 | case GlobalValue::CommonLinkage: | 
|  | 831 | case GlobalValue::LinkOnceLinkage: | 
|  | 832 | case GlobalValue::WeakLinkage: | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 833 | if (Subtarget->isTargetDarwin()) { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 834 | O << "\t.globl " << name << '\n' | 
|  | 835 | << TAI->getWeakDefDirective() << name << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 836 | } else if (Subtarget->isTargetCygMing()) { | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 837 | O << "\t.globl\t" << name << "\n" | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 838 | "\t.linkonce same_size\n"; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 839 | } else { | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 840 | O << "\t.weak\t" << name << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 841 | } | 
|  | 842 | break; | 
| Evan Cheng | 319548b | 2008-08-08 06:43:59 +0000 | [diff] [blame] | 843 | case GlobalValue::DLLExportLinkage: | 
|  | 844 | case GlobalValue::AppendingLinkage: | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 845 | // FIXME: appending linkage variables should go into a section of | 
|  | 846 | // their name or something.  For now, just emit them as external. | 
| Evan Cheng | 319548b | 2008-08-08 06:43:59 +0000 | [diff] [blame] | 847 | case GlobalValue::ExternalLinkage: | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 848 | // If external or appending, declare as a global symbol | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 849 | O << "\t.globl " << name << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 850 | // FALL THROUGH | 
| Evan Cheng | 319548b | 2008-08-08 06:43:59 +0000 | [diff] [blame] | 851 | case GlobalValue::InternalLinkage: | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 852 | break; | 
| Evan Cheng | 319548b | 2008-08-08 06:43:59 +0000 | [diff] [blame] | 853 | default: | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 854 | assert(0 && "Unknown linkage type!"); | 
|  | 855 | } | 
|  | 856 |  | 
|  | 857 | EmitAlignment(Align, GVar); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 858 | O << name << ":\t\t\t\t" << TAI->getCommentString() << ' '; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 859 | PrintUnmangledNameSafely(GVar, O); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 860 | O << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 861 | if (TAI->hasDotTypeDotSizeDirective()) | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 862 | O << "\t.size\t" << name << ", " << Size << '\n'; | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 863 |  | 
|  | 864 | // If the initializer is a extern weak symbol, remember to emit the weak | 
|  | 865 | // reference! | 
|  | 866 | if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) | 
|  | 867 | if (GV->hasExternalWeakLinkage()) | 
|  | 868 | ExtWeakSymbols.insert(GV); | 
|  | 869 |  | 
|  | 870 | EmitGlobalConstant(C); | 
|  | 871 | } | 
|  | 872 |  | 
| Evan Cheng | 5349522 | 2008-07-08 00:55:58 +0000 | [diff] [blame] | 873 | /// printGVStub - Print stub for a global value. | 
|  | 874 | /// | 
|  | 875 | void X86ATTAsmPrinter::printGVStub(const char *GV, const char *Prefix) { | 
| Evan Cheng | 0a1e672 | 2008-07-08 16:40:43 +0000 | [diff] [blame] | 876 | printSuffixedName(GV, "$non_lazy_ptr", Prefix); | 
| Evan Cheng | 5349522 | 2008-07-08 00:55:58 +0000 | [diff] [blame] | 877 | O << ":\n\t.indirect_symbol "; | 
|  | 878 | if (Prefix) O << Prefix; | 
|  | 879 | O << GV << "\n\t.long\t0\n"; | 
|  | 880 | } | 
|  | 881 |  | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 882 |  | 
|  | 883 | bool X86ATTAsmPrinter::doFinalization(Module &M) { | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 884 | // Print out module-level global variables here. | 
|  | 885 | for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); | 
| Anton Korobeynikov | a54216a | 2008-06-28 11:09:48 +0000 | [diff] [blame] | 886 | I != E; ++I) { | 
| Anton Korobeynikov | ab9ff5a | 2008-06-28 11:09:32 +0000 | [diff] [blame] | 887 | printModuleLevelGV(I); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 888 |  | 
| Anton Korobeynikov | a54216a | 2008-06-28 11:09:48 +0000 | [diff] [blame] | 889 | if (I->hasDLLExportLinkage()) | 
|  | 890 | DLLExportedGVs.insert(Mang->makeNameProper(I->getName(),"")); | 
|  | 891 | } | 
|  | 892 |  | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 893 | // Output linker support code for dllexported globals | 
| Anton Korobeynikov | 7d345eb | 2008-06-28 11:08:44 +0000 | [diff] [blame] | 894 | if (!DLLExportedGVs.empty()) | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 895 | SwitchToDataSection(".section .drectve"); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 896 |  | 
|  | 897 | for (StringSet<>::iterator i = DLLExportedGVs.begin(), | 
|  | 898 | e = DLLExportedGVs.end(); | 
| Anton Korobeynikov | 7d345eb | 2008-06-28 11:08:44 +0000 | [diff] [blame] | 899 | i != e; ++i) | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 900 | O << "\t.ascii \" -export:" << i->getKeyData() << ",data\"\n"; | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 901 |  | 
|  | 902 | if (!DLLExportedFns.empty()) { | 
|  | 903 | SwitchToDataSection(".section .drectve"); | 
|  | 904 | } | 
|  | 905 |  | 
|  | 906 | for (StringSet<>::iterator i = DLLExportedFns.begin(), | 
|  | 907 | e = DLLExportedFns.end(); | 
| Anton Korobeynikov | 7d345eb | 2008-06-28 11:08:44 +0000 | [diff] [blame] | 908 | i != e; ++i) | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 909 | O << "\t.ascii \" -export:" << i->getKeyData() << "\"\n"; | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 910 |  | 
|  | 911 | if (Subtarget->isTargetDarwin()) { | 
|  | 912 | SwitchToDataSection(""); | 
|  | 913 |  | 
|  | 914 | // Output stubs for dynamically-linked functions | 
|  | 915 | unsigned j = 1; | 
|  | 916 | for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end(); | 
|  | 917 | i != e; ++i, ++j) { | 
|  | 918 | SwitchToDataSection("\t.section __IMPORT,__jump_table,symbol_stubs," | 
|  | 919 | "self_modifying_code+pure_instructions,5", 0); | 
| Evan Cheng | 5349522 | 2008-07-08 00:55:58 +0000 | [diff] [blame] | 920 | const char *p = i->getKeyData(); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 921 | printSuffixedName(p, "$stub"); | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 922 | O << ":\n" | 
|  | 923 | "\t.indirect_symbol " << p << "\n" | 
|  | 924 | "\thlt ; hlt ; hlt ; hlt ; hlt\n"; | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 925 | } | 
|  | 926 |  | 
| Dan Gohman | 6896901e | 2008-06-30 22:03:41 +0000 | [diff] [blame] | 927 | O << '\n'; | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 928 |  | 
| Evan Cheng | 5349522 | 2008-07-08 00:55:58 +0000 | [diff] [blame] | 929 | // Print global value stubs. | 
|  | 930 | bool InStubSection = false; | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 931 | if (TAI->doesSupportExceptionHandling() && MMI && !Subtarget->is64Bit()) { | 
|  | 932 | // Add the (possibly multiple) personalities to the set of global values. | 
|  | 933 | // Only referenced functions get into the Personalities list. | 
|  | 934 | const std::vector<Function *>& Personalities = MMI->getPersonalities(); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 935 | for (std::vector<Function *>::const_iterator I = Personalities.begin(), | 
| Evan Cheng | 5349522 | 2008-07-08 00:55:58 +0000 | [diff] [blame] | 936 | E = Personalities.end(); I != E; ++I) { | 
|  | 937 | if (!*I) | 
|  | 938 | continue; | 
|  | 939 | if (!InStubSection) { | 
|  | 940 | SwitchToDataSection( | 
|  | 941 | "\t.section __IMPORT,__pointers,non_lazy_symbol_pointers"); | 
|  | 942 | InStubSection = true; | 
|  | 943 | } | 
|  | 944 | printGVStub((*I)->getNameStart(), "_"); | 
|  | 945 | } | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 946 | } | 
|  | 947 |  | 
|  | 948 | // Output stubs for external and common global variables. | 
| Evan Cheng | 5349522 | 2008-07-08 00:55:58 +0000 | [diff] [blame] | 949 | if (!InStubSection && !GVStubs.empty()) | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 950 | SwitchToDataSection( | 
|  | 951 | "\t.section __IMPORT,__pointers,non_lazy_symbol_pointers"); | 
|  | 952 | for (StringSet<>::iterator i = GVStubs.begin(), e = GVStubs.end(); | 
| Evan Cheng | 5349522 | 2008-07-08 00:55:58 +0000 | [diff] [blame] | 953 | i != e; ++i) | 
|  | 954 | printGVStub(i->getKeyData()); | 
| Anton Korobeynikov | 016d1d0 | 2008-06-28 11:08:27 +0000 | [diff] [blame] | 955 |  | 
|  | 956 | // Emit final debug information. | 
|  | 957 | DW.EndModule(); | 
|  | 958 |  | 
|  | 959 | // Funny Darwin hack: This flag tells the linker that no global symbols | 
|  | 960 | // contain code that falls through to other global symbols (e.g. the obvious | 
|  | 961 | // implementation of multiple entry points).  If this doesn't occur, the | 
|  | 962 | // linker can safely perform dead code stripping.  Since LLVM never | 
|  | 963 | // generates code that does this, it is always safe to set. | 
|  | 964 | O << "\t.subsections_via_symbols\n"; | 
|  | 965 | } else if (Subtarget->isTargetCygMing()) { | 
|  | 966 | // Emit type information for external functions | 
|  | 967 | for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end(); | 
|  | 968 | i != e; ++i) { | 
|  | 969 | O << "\t.def\t " << i->getKeyData() | 
|  | 970 | << ";\t.scl\t" << COFF::C_EXT | 
|  | 971 | << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) | 
|  | 972 | << ";\t.endef\n"; | 
|  | 973 | } | 
|  | 974 |  | 
|  | 975 | // Emit final debug information. | 
|  | 976 | DW.EndModule(); | 
|  | 977 | } else if (Subtarget->isTargetELF()) { | 
|  | 978 | // Emit final debug information. | 
|  | 979 | DW.EndModule(); | 
|  | 980 | } | 
|  | 981 |  | 
|  | 982 | return AsmPrinter::doFinalization(M); | 
|  | 983 | } | 
|  | 984 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 985 | // Include the auto-generated portion of the assembly writer. | 
|  | 986 | #include "X86GenAsmWriter.inc" |