| 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 | // | 
|  | 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 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" | 
|  | 18 | #include "X86.h" | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 19 | #include "X86COFF.h" | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 20 | #include "X86MachineFunctionInfo.h" | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 21 | #include "X86TargetMachine.h" | 
| Jim Laskey | 261779b | 2006-09-07 22:06:40 +0000 | [diff] [blame] | 22 | #include "X86TargetAsmInfo.h" | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 23 | #include "llvm/ADT/StringExtras.h" | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 24 | #include "llvm/CallingConv.h" | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 25 | #include "llvm/Module.h" | 
|  | 26 | #include "llvm/Support/Mangler.h" | 
| Jim Laskey | 261779b | 2006-09-07 22:06:40 +0000 | [diff] [blame] | 27 | #include "llvm/Target/TargetAsmInfo.h" | 
| Evan Cheng | 5588de9 | 2006-02-18 00:15:05 +0000 | [diff] [blame] | 28 | #include "llvm/Target/TargetOptions.h" | 
| Chris Lattner | 1ef9cd4 | 2006-12-19 22:59:26 +0000 | [diff] [blame] | 29 | #include "llvm/ADT/Statistic.h" | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 30 | using namespace llvm; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 31 |  | 
| Chris Lattner | 1ef9cd4 | 2006-12-19 22:59:26 +0000 | [diff] [blame] | 32 | STATISTIC(EmittedInsts, "Number of machine instrs printed"); | 
|  | 33 |  | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 34 | static std::string computePICLabel(unsigned FnNum, | 
|  | 35 | const TargetAsmInfo *TAI, | 
|  | 36 | const X86Subtarget* Subtarget)  { | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 37 | std::string label; | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 38 | if (Subtarget->isTargetDarwin()) | 
|  | 39 | label =  "\"L" + utostr_32(FnNum) + "$pb\""; | 
|  | 40 | else if (Subtarget->isTargetELF()) | 
|  | 41 | label = ".Lllvm$" + utostr_32(FnNum) + "$piclabel"; | 
|  | 42 | else | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 43 | assert(0 && "Don't know how to print PIC label!\n"); | 
|  | 44 |  | 
|  | 45 | return label; | 
|  | 46 | } | 
|  | 47 |  | 
| Chris Lattner | b82247b | 2006-10-05 02:43:52 +0000 | [diff] [blame] | 48 | /// getSectionForFunction - Return the section that we should emit the | 
|  | 49 | /// specified function body into. | 
|  | 50 | std::string X86ATTAsmPrinter::getSectionForFunction(const Function &F) const { | 
|  | 51 | switch (F.getLinkage()) { | 
|  | 52 | default: assert(0 && "Unknown linkage type!"); | 
|  | 53 | case Function::InternalLinkage: | 
|  | 54 | case Function::DLLExportLinkage: | 
|  | 55 | case Function::ExternalLinkage: | 
|  | 56 | return TAI->getTextSection(); | 
|  | 57 | case Function::WeakLinkage: | 
|  | 58 | case Function::LinkOnceLinkage: | 
|  | 59 | if (Subtarget->isTargetDarwin()) { | 
|  | 60 | return ".section __TEXT,__textcoal_nt,coalesced,pure_instructions"; | 
| Anton Korobeynikov | 4efbbc9 | 2007-01-03 11:43:14 +0000 | [diff] [blame] | 61 | } else if (Subtarget->isTargetCygMing()) { | 
| Dan Gohman | 3a8e2a8 | 2007-06-14 15:00:27 +0000 | [diff] [blame] | 62 | return "\t.section\t.text$linkonce." + CurrentFnName + ",\"ax\""; | 
| Chris Lattner | b82247b | 2006-10-05 02:43:52 +0000 | [diff] [blame] | 63 | } else { | 
|  | 64 | return "\t.section\t.llvm.linkonce.t." + CurrentFnName + | 
| Dan Gohman | 3a8e2a8 | 2007-06-14 15:00:27 +0000 | [diff] [blame] | 65 | ",\"ax\",@progbits"; | 
| Chris Lattner | b82247b | 2006-10-05 02:43:52 +0000 | [diff] [blame] | 66 | } | 
|  | 67 | } | 
|  | 68 | } | 
|  | 69 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 70 | /// runOnMachineFunction - This uses the printMachineInstruction() | 
|  | 71 | /// method to print assembly for each instruction. | 
|  | 72 | /// | 
|  | 73 | bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) { | 
| Anton Korobeynikov | 4db0090 | 2007-05-05 09:04:50 +0000 | [diff] [blame] | 74 | if (TAI->doesSupportDebugInformation()) { | 
| Jim Laskey | 5ba7c23 | 2006-07-19 11:54:50 +0000 | [diff] [blame] | 75 | // Let PassManager know we need debug information and relay | 
| Jim Laskey | c56315c | 2007-01-26 21:22:28 +0000 | [diff] [blame] | 76 | // the MachineModuleInfo address on to DwarfWriter. | 
| Bill Wendling | 2b8fc31 | 2007-09-11 08:27:17 +0000 | [diff] [blame] | 77 | MMI = &getAnalysis<MachineModuleInfo>(); | 
|  | 78 | DW.SetModuleInfo(MMI); | 
| Jim Laskey | 5ba7c23 | 2006-07-19 11:54:50 +0000 | [diff] [blame] | 79 | } | 
| Evan Cheng | 30d7b70 | 2006-03-07 02:02:57 +0000 | [diff] [blame] | 80 |  | 
| Chris Lattner | 99946fb | 2005-11-21 07:51:23 +0000 | [diff] [blame] | 81 | SetupMachineFunction(MF); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 82 | O << "\n\n"; | 
|  | 83 |  | 
|  | 84 | // Print out constants referenced by the function | 
| Chris Lattner | 8a5f3c1 | 2005-11-21 08:32:23 +0000 | [diff] [blame] | 85 | EmitConstantPool(MF.getConstantPool()); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 86 |  | 
|  | 87 | // Print out labels for the function. | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 88 | const Function *F = MF.getFunction(); | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 89 | unsigned CC = F->getCallingConv(); | 
|  | 90 |  | 
|  | 91 | // Populate function information map.  Actually, We don't want to populate | 
|  | 92 | // non-stdcall or non-fastcall functions' information right now. | 
| Chris Lattner | 104aa5d | 2006-09-26 03:57:53 +0000 | [diff] [blame] | 93 | if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall) | 
| Chris Lattner | ff0598d | 2007-04-17 17:21:52 +0000 | [diff] [blame] | 94 | FunctionInfoMap[F] = *MF.getInfo<X86MachineFunctionInfo>(); | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 95 |  | 
|  | 96 | X86SharedAsmPrinter::decorateName(CurrentFnName, F); | 
|  | 97 |  | 
| Anton Korobeynikov | a9ab109 | 2007-01-07 00:41:20 +0000 | [diff] [blame] | 98 | SwitchToTextSection(getSectionForFunction(*F).c_str(), F); | 
| Anton Korobeynikov | bb162f4 | 2007-01-06 18:24:26 +0000 | [diff] [blame] | 99 |  | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 100 | switch (F->getLinkage()) { | 
|  | 101 | default: assert(0 && "Unknown linkage type!"); | 
|  | 102 | case Function::InternalLinkage:  // Symbols default to internal. | 
| Evan Cheng | 952aa69 | 2007-07-25 23:36:05 +0000 | [diff] [blame] | 103 | if (Subtarget->isTargetDarwin()) | 
|  | 104 | // FIXME: This should be parameterized somewhere. | 
|  | 105 | EmitAlignment(4, F, 0, true, 0x90); | 
|  | 106 | else | 
|  | 107 | EmitAlignment(4, F);     // FIXME: This should be parameterized somewhere. | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 108 | break; | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 109 | case Function::DLLExportLinkage: | 
|  | 110 | DLLExportedFns.insert(Mang->makeNameProper(F->getName(), "")); | 
|  | 111 | //FALLS THROUGH | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 112 | case Function::ExternalLinkage: | 
| Evan Cheng | 952aa69 | 2007-07-25 23:36:05 +0000 | [diff] [blame] | 113 | if (Subtarget->isTargetDarwin()) | 
|  | 114 | // FIXME: This should be parameterized somewhere. | 
|  | 115 | EmitAlignment(4, F, 0, true, 0x90); | 
|  | 116 | else | 
|  | 117 | EmitAlignment(4, F);     // FIXME: This should be parameterized somewhere. | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 118 | O << "\t.globl\t" << CurrentFnName << "\n"; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 119 | break; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 120 | case Function::LinkOnceLinkage: | 
| Anton Korobeynikov | 24b7ac3 | 2006-10-18 09:12:29 +0000 | [diff] [blame] | 121 | case Function::WeakLinkage: | 
| Jim Laskey | 3b4866e | 2006-07-27 02:05:13 +0000 | [diff] [blame] | 122 | if (Subtarget->isTargetDarwin()) { | 
| Evan Cheng | 952aa69 | 2007-07-25 23:36:05 +0000 | [diff] [blame] | 123 | // FIXME: This should be parameterized somewhere. | 
|  | 124 | EmitAlignment(4, F, 0, true, 0x90); | 
| Evan Cheng | 7714a59 | 2006-02-22 23:59:57 +0000 | [diff] [blame] | 125 | O << "\t.globl\t" << CurrentFnName << "\n"; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 126 | O << "\t.weak_definition\t" << CurrentFnName << "\n"; | 
| Anton Korobeynikov | 4efbbc9 | 2007-01-03 11:43:14 +0000 | [diff] [blame] | 127 | } else if (Subtarget->isTargetCygMing()) { | 
| Evan Cheng | 2554e3d | 2006-05-25 21:59:08 +0000 | [diff] [blame] | 128 | EmitAlignment(4, F);     // FIXME: This should be parameterized somewhere. | 
| Anton Korobeynikov | 75b01be | 2006-10-17 20:29:49 +0000 | [diff] [blame] | 129 | O << "\t.globl " << CurrentFnName << "\n"; | 
| Anton Korobeynikov | 01b49ce | 2007-02-23 01:58:50 +0000 | [diff] [blame] | 130 | O << "\t.linkonce discard\n"; | 
| Anton Korobeynikov | 75b01be | 2006-10-17 20:29:49 +0000 | [diff] [blame] | 131 | } else { | 
|  | 132 | EmitAlignment(4, F);     // FIXME: This should be parameterized somewhere. | 
| Dan Gohman | 204dece | 2007-07-30 15:08:02 +0000 | [diff] [blame] | 133 | O << "\t.weak\t" << CurrentFnName << "\n"; | 
| Anton Korobeynikov | 75b01be | 2006-10-17 20:29:49 +0000 | [diff] [blame] | 134 | } | 
|  | 135 | break; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 136 | } | 
| Anton Korobeynikov | 39f3cff | 2007-04-29 18:35:00 +0000 | [diff] [blame] | 137 | if (F->hasHiddenVisibility()) { | 
| Chris Lattner | 8c51bf5 | 2007-01-14 06:29:53 +0000 | [diff] [blame] | 138 | if (const char *Directive = TAI->getHiddenDirective()) | 
|  | 139 | O << Directive << CurrentFnName << "\n"; | 
| Anton Korobeynikov | 39f3cff | 2007-04-29 18:35:00 +0000 | [diff] [blame] | 140 | } else if (F->hasProtectedVisibility()) { | 
|  | 141 | if (const char *Directive = TAI->getProtectedDirective()) | 
|  | 142 | O << Directive << CurrentFnName << "\n"; | 
|  | 143 | } | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 144 |  | 
|  | 145 | if (Subtarget->isTargetELF()) | 
| Dan Gohman | 204dece | 2007-07-30 15:08:02 +0000 | [diff] [blame] | 146 | O << "\t.type\t" << CurrentFnName << ",@function\n"; | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 147 | else if (Subtarget->isTargetCygMing()) { | 
|  | 148 | O << "\t.def\t " << CurrentFnName | 
|  | 149 | << ";\t.scl\t" << | 
|  | 150 | (F->getLinkage() == Function::InternalLinkage ? COFF::C_STAT : COFF::C_EXT) | 
|  | 151 | << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) | 
|  | 152 | << ";\t.endef\n"; | 
|  | 153 | } | 
|  | 154 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 155 | O << CurrentFnName << ":\n"; | 
| Anton Korobeynikov | 24b7ac3 | 2006-10-18 09:12:29 +0000 | [diff] [blame] | 156 | // Add some workaround for linkonce linkage on Cygwin\MinGW | 
| Anton Korobeynikov | 4efbbc9 | 2007-01-03 11:43:14 +0000 | [diff] [blame] | 157 | if (Subtarget->isTargetCygMing() && | 
| Anton Korobeynikov | 24b7ac3 | 2006-10-18 09:12:29 +0000 | [diff] [blame] | 158 | (F->getLinkage() == Function::LinkOnceLinkage || | 
|  | 159 | F->getLinkage() == Function::WeakLinkage)) | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 160 | O << "Lllvm$workaround$fake$stub$" << CurrentFnName << ":\n"; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 161 |  | 
| Anton Korobeynikov | 4db0090 | 2007-05-05 09:04:50 +0000 | [diff] [blame] | 162 | if (TAI->doesSupportDebugInformation()) { | 
| Jim Laskey | c0d6518 | 2006-04-07 20:44:42 +0000 | [diff] [blame] | 163 | // Emit pre-function debug information. | 
| Jim Laskey | a7b2bd5 | 2006-06-23 12:51:53 +0000 | [diff] [blame] | 164 | DW.BeginFunction(&MF); | 
| Jim Laskey | c0d6518 | 2006-04-07 20:44:42 +0000 | [diff] [blame] | 165 | } | 
|  | 166 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 167 | // Print out code for the function. | 
|  | 168 | for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); | 
|  | 169 | I != E; ++I) { | 
|  | 170 | // Print a label for the basic block. | 
| Nate Begeman | b9d4f83 | 2006-05-02 05:37:32 +0000 | [diff] [blame] | 171 | if (I->pred_begin() != I->pred_end()) { | 
|  | 172 | printBasicBlockLabel(I, true); | 
|  | 173 | O << '\n'; | 
|  | 174 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 175 | for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); | 
|  | 176 | II != E; ++II) { | 
|  | 177 | // Print the assembly for the instruction. | 
|  | 178 | O << "\t"; | 
|  | 179 | printMachineInstruction(II); | 
|  | 180 | } | 
|  | 181 | } | 
| Evan Cheng | 00884b5 | 2006-08-28 22:14:16 +0000 | [diff] [blame] | 182 |  | 
| Jim Laskey | a6211dc | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 183 | if (TAI->hasDotTypeDotSizeDirective()) | 
| Dan Gohman | d541c83 | 2007-08-01 14:42:30 +0000 | [diff] [blame] | 184 | O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << "\n"; | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 185 |  | 
| Anton Korobeynikov | 4db0090 | 2007-05-05 09:04:50 +0000 | [diff] [blame] | 186 | if (TAI->doesSupportDebugInformation()) { | 
| Evan Cheng | a4a4ceb | 2006-03-07 02:23:26 +0000 | [diff] [blame] | 187 | // Emit post-function debug information. | 
| Jim Laskey | cf0166f | 2006-03-23 18:09:44 +0000 | [diff] [blame] | 188 | DW.EndFunction(); | 
| Evan Cheng | a4a4ceb | 2006-03-07 02:23:26 +0000 | [diff] [blame] | 189 | } | 
| Evan Cheng | 30d7b70 | 2006-03-07 02:02:57 +0000 | [diff] [blame] | 190 |  | 
| Anton Korobeynikov | 4db0090 | 2007-05-05 09:04:50 +0000 | [diff] [blame] | 191 | // Print out jump tables referenced by the function. | 
|  | 192 | EmitJumpTableInfo(MF.getJumpTableInfo(), MF); | 
|  | 193 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 194 | // We didn't modify anything. | 
|  | 195 | return false; | 
|  | 196 | } | 
|  | 197 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 198 | static inline bool printGOT(TargetMachine &TM, const X86Subtarget* ST) { | 
|  | 199 | return ST->isPICStyleGOT() && TM.getRelocationModel() == Reloc::PIC_; | 
|  | 200 | } | 
|  | 201 |  | 
|  | 202 | static inline bool printStub(TargetMachine &TM, const X86Subtarget* ST) { | 
|  | 203 | return ST->isPICStyleStub() && TM.getRelocationModel() != Reloc::Static; | 
|  | 204 | } | 
|  | 205 |  | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 206 | void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, | 
| Evan Cheng | dd60ca0 | 2006-12-05 19:50:18 +0000 | [diff] [blame] | 207 | const char *Modifier, bool NotRIPRel) { | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 208 | const MachineOperand &MO = MI->getOperand(OpNo); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 209 | const MRegisterInfo &RI = *TM.getRegisterInfo(); | 
|  | 210 | switch (MO.getType()) { | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 211 | case MachineOperand::MO_Register: { | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 212 | assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) && | 
|  | 213 | "Virtual registers should not make it this far!"); | 
|  | 214 | O << '%'; | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 215 | unsigned Reg = MO.getReg(); | 
| Evan Cheng | cfaffdd | 2006-05-31 22:34:26 +0000 | [diff] [blame] | 216 | if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) { | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 217 | MVT::ValueType VT = (strcmp(Modifier+6,"64") == 0) ? | 
|  | 218 | MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 : | 
|  | 219 | ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8)); | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 220 | Reg = getX86SubSuperRegister(Reg, VT); | 
|  | 221 | } | 
|  | 222 | for (const char *Name = RI.get(Reg).Name; *Name; ++Name) | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 223 | O << (char)tolower(*Name); | 
|  | 224 | return; | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 225 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 226 |  | 
| Chris Lattner | fef7a2d | 2006-05-04 17:21:20 +0000 | [diff] [blame] | 227 | case MachineOperand::MO_Immediate: | 
| Chris Lattner | e4bf50c | 2007-01-25 02:53:24 +0000 | [diff] [blame] | 228 | if (!Modifier || | 
|  | 229 | (strcmp(Modifier, "debug") && strcmp(Modifier, "mem"))) | 
| Evan Cheng | 30d7b70 | 2006-03-07 02:02:57 +0000 | [diff] [blame] | 230 | O << '$'; | 
| Evan Cheng | 70145f2 | 2006-05-26 08:04:31 +0000 | [diff] [blame] | 231 | O << MO.getImmedValue(); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 232 | return; | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 233 | case MachineOperand::MO_MachineBasicBlock: | 
|  | 234 | printBasicBlockLabel(MO.getMachineBasicBlock()); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 235 | return; | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 236 | case MachineOperand::MO_JumpTableIndex: { | 
|  | 237 | bool isMemOp  = Modifier && !strcmp(Modifier, "mem"); | 
|  | 238 | if (!isMemOp) O << '$'; | 
| Jim Laskey | a6211dc | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 239 | O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << "_" | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 240 | << MO.getJumpTableIndex(); | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 241 |  | 
|  | 242 | if (TM.getRelocationModel() == Reloc::PIC_) { | 
|  | 243 | if (Subtarget->isPICStyleStub()) | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 244 | O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber() | 
|  | 245 | << "$pb\""; | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 246 | else if (Subtarget->isPICStyleGOT()) | 
|  | 247 | O << "@GOTOFF"; | 
|  | 248 | } | 
|  | 249 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 250 | if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel) | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 251 | O << "(%rip)"; | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 252 | return; | 
|  | 253 | } | 
| Evan Cheng | 75b8783 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 254 | case MachineOperand::MO_ConstantPoolIndex: { | 
|  | 255 | bool isMemOp  = Modifier && !strcmp(Modifier, "mem"); | 
|  | 256 | if (!isMemOp) O << '$'; | 
| Jim Laskey | a6211dc | 2006-09-06 18:34:40 +0000 | [diff] [blame] | 257 | O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" | 
| Evan Cheng | 75b8783 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 258 | << MO.getConstantPoolIndex(); | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 259 |  | 
|  | 260 | if (TM.getRelocationModel() == Reloc::PIC_) { | 
|  | 261 | if (Subtarget->isPICStyleStub()) | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 262 | O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber() | 
|  | 263 | << "$pb\""; | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 264 | else if (Subtarget->isPICStyleGOT()) | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 265 | O << "@GOTOFF"; | 
|  | 266 | } | 
|  | 267 |  | 
| Evan Cheng | 75b8783 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 268 | int Offset = MO.getOffset(); | 
|  | 269 | if (Offset > 0) | 
|  | 270 | O << "+" << Offset; | 
|  | 271 | else if (Offset < 0) | 
|  | 272 | O << Offset; | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 273 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 274 | if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel) | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 275 | O << "(%rip)"; | 
| Evan Cheng | 75b8783 | 2006-02-26 08:28:12 +0000 | [diff] [blame] | 276 | return; | 
|  | 277 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 278 | case MachineOperand::MO_GlobalAddress: { | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 279 | bool isCallOp = Modifier && !strcmp(Modifier, "call"); | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 280 | bool isMemOp  = Modifier && !strcmp(Modifier, "mem"); | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 281 | bool needCloseParen = false; | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 282 |  | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 283 | GlobalValue *GV = MO.getGlobal(); | 
| Lauro Ramos Venancio | 2518889 | 2007-04-20 21:38:10 +0000 | [diff] [blame] | 284 | GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV); | 
|  | 285 | bool isThreadLocal = GVar && GVar->isThreadLocal(); | 
|  | 286 |  | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 287 | std::string Name = Mang->getValueName(GV); | 
| Chris Lattner | 104aa5d | 2006-09-26 03:57:53 +0000 | [diff] [blame] | 288 | X86SharedAsmPrinter::decorateName(Name, GV); | 
| Anton Korobeynikov | 3c5b3df | 2006-09-20 22:03:51 +0000 | [diff] [blame] | 289 |  | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 290 | if (!isMemOp && !isCallOp) | 
|  | 291 | O << '$'; | 
|  | 292 | else if (Name[0] == '$') { | 
|  | 293 | // The name begins with a dollar-sign. In order to avoid having it look | 
|  | 294 | // like an integer immediate to the assembler, enclose it in parens. | 
|  | 295 | O << '('; | 
|  | 296 | needCloseParen = true; | 
|  | 297 | } | 
|  | 298 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 299 | if (printStub(TM, Subtarget)) { | 
| Evan Cheng | 59ca6a8 | 2007-06-04 18:54:57 +0000 | [diff] [blame] | 300 | // Link-once, declaration, or Weakly-linked global variables need | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 301 | // non-lazily-resolved stubs | 
| Reid Spencer | 5301e7c | 2007-01-30 20:08:39 +0000 | [diff] [blame] | 302 | if (GV->isDeclaration() || | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 303 | GV->hasWeakLinkage() || | 
|  | 304 | GV->hasLinkOnceLinkage()) { | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 305 | // Dynamically-resolved functions need a stub for the function. | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 306 | if (isCallOp && isa<Function>(GV)) { | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 307 | FnStubs.insert(Name); | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 308 | O << TAI->getPrivateGlobalPrefix() << Name << "$stub"; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 309 | } else { | 
|  | 310 | GVStubs.insert(Name); | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 311 | O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr"; | 
| Evan Cheng | 5a76680 | 2006-02-07 08:38:37 +0000 | [diff] [blame] | 312 | } | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 313 | } else { | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 314 | if (GV->hasDLLImportLinkage()) | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 315 | O << "__imp_"; | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 316 | O << Name; | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 317 | } | 
|  | 318 |  | 
| Chris Lattner | 9e56e5c | 2006-07-26 21:12:04 +0000 | [diff] [blame] | 319 | if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_) | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 320 | O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber() | 
|  | 321 | << "$pb\""; | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 322 | } else { | 
|  | 323 | if (GV->hasDLLImportLinkage()) { | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 324 | O << "__imp_"; | 
|  | 325 | } | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 326 | O << Name; | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 327 |  | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 328 | if (isCallOp && isa<Function>(GV)) { | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 329 | if (printGOT(TM, Subtarget)) { | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 330 | // Assemble call via PLT for non-local symbols | 
| Anton Korobeynikov | 39f3cff | 2007-04-29 18:35:00 +0000 | [diff] [blame] | 331 | if (!(GV->hasHiddenVisibility() || GV->hasProtectedVisibility()) || | 
|  | 332 | GV->isDeclaration()) | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 333 | O << "@PLT"; | 
|  | 334 | } | 
| Reid Spencer | 5301e7c | 2007-01-30 20:08:39 +0000 | [diff] [blame] | 335 | if (Subtarget->isTargetCygMing() && GV->isDeclaration()) | 
| Anton Korobeynikov | 4f01b78 | 2007-01-16 16:41:57 +0000 | [diff] [blame] | 336 | // Save function name for later type emission | 
|  | 337 | FnStubs.insert(Name); | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 338 | } | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 339 | } | 
| Anton Korobeynikov | 12c9494 | 2006-12-01 00:25:12 +0000 | [diff] [blame] | 340 |  | 
| Evan Cheng | 5b02034 | 2006-12-01 07:38:23 +0000 | [diff] [blame] | 341 | if (GV->hasExternalWeakLinkage()) | 
| Rafael Espindola | d7998d0 | 2006-12-18 03:37:18 +0000 | [diff] [blame] | 342 | ExtWeakSymbols.insert(GV); | 
| Anton Korobeynikov | d61d39e | 2006-09-14 18:23:27 +0000 | [diff] [blame] | 343 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 344 | int Offset = MO.getOffset(); | 
|  | 345 | if (Offset > 0) | 
|  | 346 | O << "+" << Offset; | 
|  | 347 | else if (Offset < 0) | 
|  | 348 | O << Offset; | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 349 |  | 
| Lauro Ramos Venancio | 2518889 | 2007-04-20 21:38:10 +0000 | [diff] [blame] | 350 | if (isThreadLocal) { | 
|  | 351 | if (TM.getRelocationModel() == Reloc::PIC_) | 
|  | 352 | O << "@TLSGD"; // general dynamic TLS model | 
|  | 353 | else | 
|  | 354 | if (GV->isDeclaration()) | 
|  | 355 | O << "@INDNTPOFF"; // initial exec TLS model | 
|  | 356 | else | 
|  | 357 | O << "@NTPOFF"; // local exec TLS model | 
|  | 358 | } else if (isMemOp) { | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 359 | if (printGOT(TM, Subtarget)) { | 
| Anton Korobeynikov | 3f6d528 | 2007-01-17 10:33:08 +0000 | [diff] [blame] | 360 | if (Subtarget->GVRequiresExtraLoad(GV, TM, false)) | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 361 | O << "@GOT"; | 
| Anton Korobeynikov | 3f6d528 | 2007-01-17 10:33:08 +0000 | [diff] [blame] | 362 | else | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 363 | O << "@GOTOFF"; | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 364 | } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel) { | 
| Evan Cheng | 59ca6a8 | 2007-06-04 18:54:57 +0000 | [diff] [blame] | 365 | if ((GV->isDeclaration() || | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 366 | GV->hasWeakLinkage() || | 
|  | 367 | GV->hasLinkOnceLinkage()) && | 
|  | 368 | TM.getRelocationModel() != Reloc::Static) | 
|  | 369 | O << "@GOTPCREL"; | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 370 |  | 
|  | 371 | if (needCloseParen) { | 
|  | 372 | needCloseParen = false; | 
|  | 373 | O << ')'; | 
|  | 374 | } | 
|  | 375 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 376 | // Use rip when possible to reduce code size, except when | 
|  | 377 | // index or base register are also part of the address. e.g. | 
|  | 378 | // foo(%rip)(%rcx,%rax,4) is not legal | 
|  | 379 | O << "(%rip)"; | 
|  | 380 | } | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 381 | } | 
|  | 382 |  | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 383 | if (needCloseParen) | 
|  | 384 | O << ')'; | 
|  | 385 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 386 | return; | 
|  | 387 | } | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 388 | case MachineOperand::MO_ExternalSymbol: { | 
|  | 389 | bool isCallOp = Modifier && !strcmp(Modifier, "call"); | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 390 | bool needCloseParen = false; | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 391 | std::string Name(TAI->getGlobalPrefix()); | 
|  | 392 | Name += MO.getSymbolName(); | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 393 | if (isCallOp && printStub(TM, Subtarget)) { | 
| Nate Begeman | b62a4c8 | 2005-07-08 00:23:26 +0000 | [diff] [blame] | 394 | FnStubs.insert(Name); | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 395 | O << TAI->getPrivateGlobalPrefix() << Name << "$stub"; | 
| Nate Begeman | b62a4c8 | 2005-07-08 00:23:26 +0000 | [diff] [blame] | 396 | return; | 
|  | 397 | } | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 398 | if (!isCallOp) | 
|  | 399 | O << '$'; | 
|  | 400 | else if (Name[0] == '$') { | 
|  | 401 | // The name begins with a dollar-sign. In order to avoid having it look | 
|  | 402 | // like an integer immediate to the assembler, enclose it in parens. | 
|  | 403 | O << '('; | 
|  | 404 | needCloseParen = true; | 
|  | 405 | } | 
|  | 406 |  | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 407 | O << Name; | 
|  | 408 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 409 | if (printGOT(TM, Subtarget)) { | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 410 | std::string GOTName(TAI->getGlobalPrefix()); | 
|  | 411 | GOTName+="_GLOBAL_OFFSET_TABLE_"; | 
|  | 412 | if (Name == GOTName) | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 413 | // HACK! Emit extra offset to PC during printing GOT offset to | 
|  | 414 | // compensate for the size of popl instruction. The resulting code | 
|  | 415 | // should look like: | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 416 | //   call .piclabel | 
|  | 417 | // piclabel: | 
|  | 418 | //   popl %some_register | 
|  | 419 | //   addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 420 | O << " + [.-" | 
|  | 421 | << computePICLabel(getFunctionNumber(), TAI, Subtarget) << "]"; | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 422 |  | 
|  | 423 | if (isCallOp) | 
|  | 424 | O << "@PLT"; | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 425 | } | 
|  | 426 |  | 
| Dan Gohman | a30eabd | 2007-04-26 21:07:05 +0000 | [diff] [blame] | 427 | if (needCloseParen) | 
|  | 428 | O << ')'; | 
|  | 429 |  | 
| Evan Cheng | 97057f3 | 2007-01-18 22:27:12 +0000 | [diff] [blame] | 430 | if (!isCallOp && Subtarget->isPICStyleRIPRel()) | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 431 | O << "(%rip)"; | 
|  | 432 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 433 | return; | 
| Chris Lattner | d62a3bf | 2006-02-06 23:41:19 +0000 | [diff] [blame] | 434 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 435 | default: | 
|  | 436 | O << "<unknown operand type>"; return; | 
|  | 437 | } | 
|  | 438 | } | 
|  | 439 |  | 
| Nate Begeman | 6f8c1ac | 2005-11-30 18:54:35 +0000 | [diff] [blame] | 440 | void X86ATTAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) { | 
| Nate Begeman | 0f38dc4 | 2005-07-14 22:52:25 +0000 | [diff] [blame] | 441 | unsigned char value = MI->getOperand(Op).getImmedValue(); | 
|  | 442 | assert(value <= 7 && "Invalid ssecc argument!"); | 
|  | 443 | switch (value) { | 
|  | 444 | case 0: O << "eq"; break; | 
|  | 445 | case 1: O << "lt"; break; | 
|  | 446 | case 2: O << "le"; break; | 
|  | 447 | case 3: O << "unord"; break; | 
|  | 448 | case 4: O << "neq"; break; | 
|  | 449 | case 5: O << "nlt"; break; | 
|  | 450 | case 6: O << "nle"; break; | 
|  | 451 | case 7: O << "ord"; break; | 
|  | 452 | } | 
|  | 453 | } | 
|  | 454 |  | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 455 | void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op, | 
|  | 456 | const char *Modifier){ | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 457 | assert(isMem(MI, Op) && "Invalid memory reference!"); | 
| Chris Lattner | 5544e17 | 2007-01-14 00:13:07 +0000 | [diff] [blame] | 458 | MachineOperand BaseReg  = MI->getOperand(Op); | 
|  | 459 | MachineOperand IndexReg = MI->getOperand(Op+2); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 460 | const MachineOperand &DispSpec = MI->getOperand(Op+3); | 
|  | 461 |  | 
| Evan Cheng | dd60ca0 | 2006-12-05 19:50:18 +0000 | [diff] [blame] | 462 | bool NotRIPRel = IndexReg.getReg() || BaseReg.getReg(); | 
| Evan Cheng | 6d46414 | 2006-08-29 22:14:48 +0000 | [diff] [blame] | 463 | if (DispSpec.isGlobalAddress() || | 
|  | 464 | DispSpec.isConstantPoolIndex() || | 
|  | 465 | DispSpec.isJumpTableIndex()) { | 
| Evan Cheng | dd60ca0 | 2006-12-05 19:50:18 +0000 | [diff] [blame] | 466 | printOperand(MI, Op+3, "mem", NotRIPRel); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 467 | } else { | 
|  | 468 | int DispVal = DispSpec.getImmedValue(); | 
|  | 469 | if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) | 
|  | 470 | O << DispVal; | 
|  | 471 | } | 
|  | 472 |  | 
|  | 473 | if (IndexReg.getReg() || BaseReg.getReg()) { | 
| Chris Lattner | 5544e17 | 2007-01-14 00:13:07 +0000 | [diff] [blame] | 474 | unsigned ScaleVal = MI->getOperand(Op+1).getImmedValue(); | 
|  | 475 | unsigned BaseRegOperand = 0, IndexRegOperand = 2; | 
|  | 476 |  | 
|  | 477 | // There are cases where we can end up with ESP/RSP in the indexreg slot. | 
|  | 478 | // If this happens, swap the base/index register to support assemblers that | 
|  | 479 | // don't work when the index is *SP. | 
|  | 480 | if (IndexReg.getReg() == X86::ESP || IndexReg.getReg() == X86::RSP) { | 
|  | 481 | assert(ScaleVal == 1 && "Scale not supported for stack pointer!"); | 
|  | 482 | std::swap(BaseReg, IndexReg); | 
|  | 483 | std::swap(BaseRegOperand, IndexRegOperand); | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 484 | } | 
| Chris Lattner | 5544e17 | 2007-01-14 00:13:07 +0000 | [diff] [blame] | 485 |  | 
|  | 486 | O << "("; | 
|  | 487 | if (BaseReg.getReg()) | 
|  | 488 | printOperand(MI, Op+BaseRegOperand, Modifier); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 489 |  | 
|  | 490 | if (IndexReg.getReg()) { | 
|  | 491 | O << ","; | 
| Chris Lattner | 5544e17 | 2007-01-14 00:13:07 +0000 | [diff] [blame] | 492 | printOperand(MI, Op+IndexRegOperand, Modifier); | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 493 | if (ScaleVal != 1) | 
|  | 494 | O << "," << ScaleVal; | 
|  | 495 | } | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 496 | O << ")"; | 
|  | 497 | } | 
|  | 498 | } | 
|  | 499 |  | 
| Evan Cheng | 5588de9 | 2006-02-18 00:15:05 +0000 | [diff] [blame] | 500 | void X86ATTAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) { | 
| Evan Cheng | 4b8d03e | 2007-01-18 01:49:58 +0000 | [diff] [blame] | 501 | std::string label = computePICLabel(getFunctionNumber(), TAI, Subtarget); | 
| Anton Korobeynikov | a0554d9 | 2007-01-12 19:20:47 +0000 | [diff] [blame] | 502 | O << label << "\n" << label << ":"; | 
| Evan Cheng | 5588de9 | 2006-02-18 00:15:05 +0000 | [diff] [blame] | 503 | } | 
|  | 504 |  | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 505 |  | 
| Evan Cheng | d369603 | 2006-04-28 23:19:39 +0000 | [diff] [blame] | 506 | bool X86ATTAsmPrinter::printAsmMRegister(const MachineOperand &MO, | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 507 | const char Mode) { | 
|  | 508 | const MRegisterInfo &RI = *TM.getRegisterInfo(); | 
|  | 509 | unsigned Reg = MO.getReg(); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 510 | switch (Mode) { | 
|  | 511 | default: return true;  // Unknown mode. | 
|  | 512 | case 'b': // Print QImode register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 513 | Reg = getX86SubSuperRegister(Reg, MVT::i8); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 514 | break; | 
|  | 515 | case 'h': // Print QImode high register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 516 | Reg = getX86SubSuperRegister(Reg, MVT::i8, true); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 517 | break; | 
|  | 518 | case 'w': // Print HImode register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 519 | Reg = getX86SubSuperRegister(Reg, MVT::i16); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 520 | break; | 
|  | 521 | case 'k': // Print SImode register | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 522 | Reg = getX86SubSuperRegister(Reg, MVT::i32); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 523 | break; | 
|  | 524 | } | 
|  | 525 |  | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 526 | O << '%'; | 
|  | 527 | for (const char *Name = RI.get(Reg).Name; *Name; ++Name) | 
|  | 528 | O << (char)tolower(*Name); | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 529 | return false; | 
|  | 530 | } | 
|  | 531 |  | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 532 | /// PrintAsmOperand - Print out an operand for an inline asm expression. | 
|  | 533 | /// | 
|  | 534 | bool X86ATTAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, | 
|  | 535 | unsigned AsmVariant, | 
|  | 536 | const char *ExtraCode) { | 
|  | 537 | // Does this asm operand have a single letter operand modifier? | 
|  | 538 | if (ExtraCode && ExtraCode[0]) { | 
|  | 539 | if (ExtraCode[1] != 0) return true; // Unknown modifier. | 
|  | 540 |  | 
|  | 541 | switch (ExtraCode[0]) { | 
|  | 542 | default: return true;  // Unknown modifier. | 
| Chris Lattner | e4bf50c | 2007-01-25 02:53:24 +0000 | [diff] [blame] | 543 | case 'c': // Don't print "$" before a global var name or constant. | 
| Chris Lattner | 60ce558 | 2006-10-31 20:12:30 +0000 | [diff] [blame] | 544 | printOperand(MI, OpNo, "mem"); | 
|  | 545 | return false; | 
| Evan Cheng | b244b80 | 2006-04-28 23:11:40 +0000 | [diff] [blame] | 546 | case 'b': // Print QImode register | 
|  | 547 | case 'h': // Print QImode high register | 
|  | 548 | case 'w': // Print HImode register | 
|  | 549 | case 'k': // Print SImode register | 
| Chris Lattner | 927f30d | 2007-03-25 02:01:03 +0000 | [diff] [blame] | 550 | if (MI->getOperand(OpNo).isReg()) | 
|  | 551 | return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]); | 
|  | 552 | printOperand(MI, OpNo); | 
|  | 553 | return false; | 
| Chris Lattner | c8ddca7 | 2007-03-25 01:44:57 +0000 | [diff] [blame] | 554 |  | 
|  | 555 | case 'P': // Don't print @PLT, but do print as memory. | 
|  | 556 | printOperand(MI, OpNo, "mem"); | 
|  | 557 | return false; | 
| Evan Cheng | 68a44dc | 2006-04-28 21:19:05 +0000 | [diff] [blame] | 558 | } | 
|  | 559 | } | 
|  | 560 |  | 
|  | 561 | printOperand(MI, OpNo); | 
|  | 562 | return false; | 
|  | 563 | } | 
|  | 564 |  | 
|  | 565 | bool X86ATTAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, | 
|  | 566 | unsigned OpNo, | 
|  | 567 | unsigned AsmVariant, | 
|  | 568 | const char *ExtraCode) { | 
|  | 569 | if (ExtraCode && ExtraCode[0]) | 
|  | 570 | return true; // Unknown modifier. | 
|  | 571 | printMemReference(MI, OpNo); | 
|  | 572 | return false; | 
|  | 573 | } | 
|  | 574 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 575 | /// printMachineInstruction -- Print out a single X86 LLVM instruction | 
| Dan Gohman | e33c4b7 | 2007-06-25 15:11:25 +0000 | [diff] [blame] | 576 | /// MI in AT&T syntax to the current output stream. | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 577 | /// | 
|  | 578 | void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) { | 
|  | 579 | ++EmittedInsts; | 
| Evan Cheng | fcdce6d | 2006-01-26 02:27:43 +0000 | [diff] [blame] | 580 |  | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 581 | // See if a truncate instruction can be turned into a nop. | 
|  | 582 | switch (MI->getOpcode()) { | 
|  | 583 | default: break; | 
| Evan Cheng | 11b0a5d | 2006-09-08 06:48:29 +0000 | [diff] [blame] | 584 | case X86::PsMOVZX64rr32: | 
|  | 585 | O << TAI->getCommentString() << " ZERO-EXTEND " << "\n\t"; | 
|  | 586 | break; | 
| Evan Cheng | ddb6cc1 | 2006-05-05 05:40:20 +0000 | [diff] [blame] | 587 | } | 
|  | 588 |  | 
| Chris Lattner | b974046 | 2005-07-01 22:44:09 +0000 | [diff] [blame] | 589 | // Call the autogenerated instruction printer routines. | 
|  | 590 | printInstruction(MI); | 
|  | 591 | } | 
|  | 592 |  | 
|  | 593 | // Include the auto-generated portion of the assembly writer. | 
|  | 594 | #include "X86GenAsmWriter.inc" | 
|  | 595 |  |