| Misha Brukman | cf7d3af | 2004-07-26 18:45:48 +0000 | [diff] [blame] | 1 | //===-- X86AsmPrinter.cpp - Convert X86 LLVM code to Intel assembly -------===// | 
| John Criswell | 482202a | 2003-10-20 19:43:21 +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 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | d92fb00 | 2002-10-25 22:55:53 +0000 | [diff] [blame] | 9 | // | 
| Misha Brukman | a6025e6 | 2004-03-01 23:53:11 +0000 | [diff] [blame] | 10 | // This file contains a printer that converts from our internal representation | 
| Chris Lattner | d1ab378 | 2004-10-04 07:31:08 +0000 | [diff] [blame] | 11 | // of machine-dependent LLVM code to Intel and AT&T format assembly | 
|  | 12 | // language. This printer is the output mechanism used by `llc' and `lli | 
|  | 13 | // -print-machineinstrs' on X86. | 
| Chris Lattner | d92fb00 | 2002-10-25 22:55:53 +0000 | [diff] [blame] | 14 | // | 
|  | 15 | //===----------------------------------------------------------------------===// | 
|  | 16 |  | 
|  | 17 | #include "X86.h" | 
| Alkis Evlogimenos | 8ac958b | 2004-03-09 03:35:34 +0000 | [diff] [blame] | 18 | #include "X86TargetMachine.h" | 
| Chris Lattner | 1a2e6f7 | 2003-08-11 20:06:16 +0000 | [diff] [blame] | 19 | #include "llvm/Module.h" | 
| Chris Lattner | 7b9020a | 2005-03-17 15:38:16 +0000 | [diff] [blame^] | 20 | #include "llvm/Type.h" | 
| Chris Lattner | 1a2e6f7 | 2003-08-11 20:06:16 +0000 | [diff] [blame] | 21 | #include "llvm/Assembly/Writer.h" | 
| Chris Lattner | 9cf4645 | 2004-08-16 23:16:06 +0000 | [diff] [blame] | 22 | #include "llvm/CodeGen/AsmPrinter.h" | 
| Chris Lattner | 956e837 | 2003-01-13 00:35:03 +0000 | [diff] [blame] | 23 | #include "llvm/CodeGen/MachineConstantPool.h" | 
| Alkis Evlogimenos | 8ac958b | 2004-03-09 03:35:34 +0000 | [diff] [blame] | 24 | #include "llvm/CodeGen/MachineFunctionPass.h" | 
| Chris Lattner | d554002 | 2004-08-01 07:43:46 +0000 | [diff] [blame] | 25 | #include "llvm/CodeGen/ValueTypes.h" | 
| Chris Lattner | 1a2e6f7 | 2003-08-11 20:06:16 +0000 | [diff] [blame] | 26 | #include "llvm/Target/TargetMachine.h" | 
| Brian Gaeke | 46f8b71 | 2003-07-24 20:20:44 +0000 | [diff] [blame] | 27 | #include "llvm/Support/Mangler.h" | 
| Reid Spencer | 7c16caa | 2004-09-01 22:55:40 +0000 | [diff] [blame] | 28 | #include "llvm/ADT/Statistic.h" | 
| Reid Spencer | 7c16caa | 2004-09-01 22:55:40 +0000 | [diff] [blame] | 29 | #include "llvm/Support/CommandLine.h" | 
| Chris Lattner | 9f75a55 | 2004-02-14 06:00:36 +0000 | [diff] [blame] | 30 | using namespace llvm; | 
| Brian Gaeke | 960707c | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 31 |  | 
| Chris Lattner | d1ab378 | 2004-10-04 07:31:08 +0000 | [diff] [blame] | 32 | namespace { | 
|  | 33 | Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed"); | 
|  | 34 | enum AsmWriterFlavor { att, intel }; | 
|  | 35 |  | 
|  | 36 | cl::opt<AsmWriterFlavor> | 
|  | 37 | AsmWriterFlavor("x86-asm-syntax", | 
|  | 38 | cl::desc("Choose style of code to emit from X86 backend:"), | 
|  | 39 | cl::values( | 
|  | 40 | clEnumVal(att,   "  Emit AT&T-style assembly"), | 
|  | 41 | clEnumVal(intel, "  Emit Intel-style assembly"), | 
|  | 42 | clEnumValEnd), | 
|  | 43 | cl::init(att)); | 
|  | 44 |  | 
|  | 45 | struct X86SharedAsmPrinter : public AsmPrinter { | 
|  | 46 | X86SharedAsmPrinter(std::ostream &O, TargetMachine &TM) | 
| Reid Spencer | 30226da | 2005-01-23 03:52:14 +0000 | [diff] [blame] | 47 | : AsmPrinter(O, TM), forCygwin(false) { } | 
| Chris Lattner | d1ab378 | 2004-10-04 07:31:08 +0000 | [diff] [blame] | 48 |  | 
| Reid Spencer | 30226da | 2005-01-23 03:52:14 +0000 | [diff] [blame] | 49 | bool doInitialization(Module &M); | 
| Chris Lattner | d1ab378 | 2004-10-04 07:31:08 +0000 | [diff] [blame] | 50 | void printConstantPool(MachineConstantPool *MCP); | 
|  | 51 | bool doFinalization(Module &M); | 
| Reid Spencer | 30226da | 2005-01-23 03:52:14 +0000 | [diff] [blame] | 52 | bool forCygwin; | 
| Chris Lattner | d1ab378 | 2004-10-04 07:31:08 +0000 | [diff] [blame] | 53 | }; | 
|  | 54 | } | 
|  | 55 |  | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 56 | static bool isScale(const MachineOperand &MO) { | 
|  | 57 | return MO.isImmediate() && | 
|  | 58 | (MO.getImmedValue() == 1 || MO.getImmedValue() == 2 || | 
|  | 59 | MO.getImmedValue() == 4 || MO.getImmedValue() == 8); | 
|  | 60 | } | 
|  | 61 |  | 
|  | 62 | static bool isMem(const MachineInstr *MI, unsigned Op) { | 
|  | 63 | if (MI->getOperand(Op).isFrameIndex()) return true; | 
|  | 64 | if (MI->getOperand(Op).isConstantPoolIndex()) return true; | 
|  | 65 | return Op+4 <= MI->getNumOperands() && | 
|  | 66 | MI->getOperand(Op  ).isRegister() && isScale(MI->getOperand(Op+1)) && | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 67 | MI->getOperand(Op+2).isRegister() && (MI->getOperand(Op+3).isImmediate() || | 
|  | 68 | MI->getOperand(Op+3).isGlobalAddress()); | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 69 | } | 
|  | 70 |  | 
|  | 71 | // SwitchSection - Switch to the specified section of the executable if we are | 
|  | 72 | // not already in it! | 
|  | 73 | // | 
|  | 74 | static void SwitchSection(std::ostream &OS, std::string &CurSection, | 
|  | 75 | const char *NewSection) { | 
|  | 76 | if (CurSection != NewSection) { | 
|  | 77 | CurSection = NewSection; | 
|  | 78 | if (!CurSection.empty()) | 
|  | 79 | OS << "\t" << NewSection << "\n"; | 
|  | 80 | } | 
|  | 81 | } | 
|  | 82 |  | 
| Reid Spencer | 30226da | 2005-01-23 03:52:14 +0000 | [diff] [blame] | 83 | /// doInitialization - determine | 
|  | 84 | bool X86SharedAsmPrinter::doInitialization(Module& M) { | 
|  | 85 | forCygwin = false; | 
|  | 86 | const std::string& TT = M.getTargetTriple(); | 
|  | 87 | if (TT.length() > 5) | 
| Reid Spencer | 00658b8 | 2005-03-08 17:02:05 +0000 | [diff] [blame] | 88 | forCygwin = TT.find("cygwin") != std::string::npos || | 
|  | 89 | TT.find("mingw")  != std::string::npos; | 
| Reid Spencer | 30226da | 2005-01-23 03:52:14 +0000 | [diff] [blame] | 90 | else if (TT.empty()) { | 
| Reid Spencer | 00658b8 | 2005-03-08 17:02:05 +0000 | [diff] [blame] | 91 | #if defined(__CYGWIN__) || defined(__MINGW32__) | 
| Reid Spencer | 30226da | 2005-01-23 03:52:14 +0000 | [diff] [blame] | 92 | forCygwin = true; | 
|  | 93 | #else | 
|  | 94 | forCygwin = false; | 
|  | 95 | #endif | 
|  | 96 | } | 
|  | 97 | if (forCygwin) | 
|  | 98 | GlobalPrefix = "_"; | 
|  | 99 | return AsmPrinter::doInitialization(M); | 
|  | 100 | } | 
|  | 101 |  | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 102 | /// printConstantPool - Print to the current output stream assembly | 
|  | 103 | /// representations of the constants in the constant pool MCP. This is | 
|  | 104 | /// used to print out constants which have been "spilled to memory" by | 
|  | 105 | /// the code generator. | 
|  | 106 | /// | 
|  | 107 | void X86SharedAsmPrinter::printConstantPool(MachineConstantPool *MCP) { | 
|  | 108 | const std::vector<Constant*> &CP = MCP->getConstants(); | 
|  | 109 | const TargetData &TD = TM.getTargetData(); | 
|  | 110 |  | 
|  | 111 | if (CP.empty()) return; | 
|  | 112 |  | 
|  | 113 | for (unsigned i = 0, e = CP.size(); i != e; ++i) { | 
|  | 114 | O << "\t.section .rodata\n"; | 
|  | 115 | emitAlignment(TD.getTypeAlignmentShift(CP[i]->getType())); | 
|  | 116 | O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t" << CommentString | 
|  | 117 | << *CP[i] << "\n"; | 
|  | 118 | emitGlobalConstant(CP[i]); | 
|  | 119 | } | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | bool X86SharedAsmPrinter::doFinalization(Module &M) { | 
|  | 123 | const TargetData &TD = TM.getTargetData(); | 
|  | 124 | std::string CurSection; | 
|  | 125 |  | 
|  | 126 | // Print out module-level global variables here. | 
| Chris Lattner | 531f9e9 | 2005-03-15 04:54:21 +0000 | [diff] [blame] | 127 | for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 128 | if (I->hasInitializer()) {   // External global require no code | 
|  | 129 | O << "\n\n"; | 
|  | 130 | std::string name = Mang->getValueName(I); | 
|  | 131 | Constant *C = I->getInitializer(); | 
|  | 132 | unsigned Size = TD.getTypeSize(C->getType()); | 
|  | 133 | unsigned Align = TD.getTypeAlignmentShift(C->getType()); | 
|  | 134 |  | 
|  | 135 | if (C->isNullValue() && | 
|  | 136 | (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || | 
|  | 137 | I->hasWeakLinkage() /* FIXME: Verify correct */)) { | 
|  | 138 | SwitchSection(O, CurSection, ".data"); | 
| Reid Spencer | 30226da | 2005-01-23 03:52:14 +0000 | [diff] [blame] | 139 | if (!forCygwin && I->hasInternalLinkage()) | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 140 | O << "\t.local " << name << "\n"; | 
|  | 141 |  | 
| Reid Spencer | 30226da | 2005-01-23 03:52:14 +0000 | [diff] [blame] | 142 | O << "\t.comm " << name << "," << TD.getTypeSize(C->getType()); | 
|  | 143 | if (!forCygwin) | 
|  | 144 | O << "," << (1 << Align); | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 145 | O << "\t\t# "; | 
|  | 146 | WriteAsOperand(O, I, true, true, &M); | 
|  | 147 | O << "\n"; | 
|  | 148 | } else { | 
|  | 149 | switch (I->getLinkage()) { | 
|  | 150 | case GlobalValue::LinkOnceLinkage: | 
|  | 151 | case GlobalValue::WeakLinkage:   // FIXME: Verify correct for weak. | 
|  | 152 | // Nonnull linkonce -> weak | 
|  | 153 | O << "\t.weak " << name << "\n"; | 
|  | 154 | SwitchSection(O, CurSection, ""); | 
|  | 155 | O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"; | 
|  | 156 | break; | 
|  | 157 | case GlobalValue::AppendingLinkage: | 
|  | 158 | // FIXME: appending linkage variables should go into a section of | 
|  | 159 | // their name or something.  For now, just emit them as external. | 
|  | 160 | case GlobalValue::ExternalLinkage: | 
|  | 161 | // If external or appending, declare as a global symbol | 
|  | 162 | O << "\t.globl " << name << "\n"; | 
|  | 163 | // FALL THROUGH | 
|  | 164 | case GlobalValue::InternalLinkage: | 
|  | 165 | if (C->isNullValue()) | 
|  | 166 | SwitchSection(O, CurSection, ".bss"); | 
|  | 167 | else | 
|  | 168 | SwitchSection(O, CurSection, ".data"); | 
|  | 169 | break; | 
| Misha Brukman | 7f245d4 | 2004-11-14 21:03:49 +0000 | [diff] [blame] | 170 | case GlobalValue::GhostLinkage: | 
|  | 171 | std::cerr << "GhostLinkage cannot appear in X86AsmPrinter!\n"; | 
|  | 172 | abort(); | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 173 | } | 
|  | 174 |  | 
|  | 175 | emitAlignment(Align); | 
| Reid Spencer | 30226da | 2005-01-23 03:52:14 +0000 | [diff] [blame] | 176 | if (!forCygwin) { | 
|  | 177 | O << "\t.type " << name << ",@object\n"; | 
|  | 178 | O << "\t.size " << name << "," << Size << "\n"; | 
|  | 179 | } | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 180 | O << name << ":\t\t\t\t# "; | 
|  | 181 | WriteAsOperand(O, I, true, true, &M); | 
|  | 182 | O << " = "; | 
|  | 183 | WriteAsOperand(O, C, false, false, &M); | 
|  | 184 | O << "\n"; | 
|  | 185 | emitGlobalConstant(C); | 
|  | 186 | } | 
|  | 187 | } | 
|  | 188 |  | 
|  | 189 | AsmPrinter::doFinalization(M); | 
|  | 190 | return false; // success | 
|  | 191 | } | 
|  | 192 |  | 
| Chris Lattner | 02a3d83 | 2002-10-29 22:37:54 +0000 | [diff] [blame] | 193 | namespace { | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 194 | struct X86IntelAsmPrinter : public X86SharedAsmPrinter { | 
|  | 195 | X86IntelAsmPrinter(std::ostream &O, TargetMachine &TM) | 
|  | 196 | : X86SharedAsmPrinter(O, TM) { } | 
| Brian Gaeke | c3998cb | 2003-07-23 18:37:06 +0000 | [diff] [blame] | 197 |  | 
| Chris Lattner | d06650a | 2002-12-15 21:13:40 +0000 | [diff] [blame] | 198 | virtual const char *getPassName() const { | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 199 | return "X86 Intel-Style Assembly Printer"; | 
| Chris Lattner | d06650a | 2002-12-15 21:13:40 +0000 | [diff] [blame] | 200 | } | 
|  | 201 |  | 
| Chris Lattner | 9520d20 | 2004-08-01 06:02:08 +0000 | [diff] [blame] | 202 | /// printInstruction - This method is automatically generated by tablegen | 
|  | 203 | /// from the instruction set description.  This method returns true if the | 
|  | 204 | /// machine instruction was sufficiently described to print it, otherwise it | 
|  | 205 | /// returns false. | 
|  | 206 | bool printInstruction(const MachineInstr *MI); | 
|  | 207 |  | 
| Chris Lattner | d554002 | 2004-08-01 07:43:46 +0000 | [diff] [blame] | 208 | // This method is used by the tablegen'erated instruction printer. | 
| Chris Lattner | 9cf4645 | 2004-08-16 23:16:06 +0000 | [diff] [blame] | 209 | void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){ | 
| Chris Lattner | 09ee05b | 2004-08-11 02:25:00 +0000 | [diff] [blame] | 210 | const MachineOperand &MO = MI->getOperand(OpNo); | 
| Chris Lattner | 06cf67e | 2004-08-01 08:12:41 +0000 | [diff] [blame] | 211 | if (MO.getType() == MachineOperand::MO_MachineRegister) { | 
|  | 212 | assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physref??"); | 
|  | 213 | // Bug Workaround: See note in Printer::doInitialization about %. | 
|  | 214 | O << "%" << TM.getRegisterInfo()->get(MO.getReg()).Name; | 
|  | 215 | } else { | 
|  | 216 | printOp(MO); | 
|  | 217 | } | 
| Chris Lattner | d554002 | 2004-08-01 07:43:46 +0000 | [diff] [blame] | 218 | } | 
|  | 219 |  | 
| Chris Lattner | 9cf4645 | 2004-08-16 23:16:06 +0000 | [diff] [blame] | 220 | void printCallOperand(const MachineInstr *MI, unsigned OpNo, | 
|  | 221 | MVT::ValueType VT) { | 
| Chris Lattner | a0bafce | 2004-08-11 06:59:12 +0000 | [diff] [blame] | 222 | printOp(MI->getOperand(OpNo), true); // Don't print "OFFSET". | 
|  | 223 | } | 
|  | 224 |  | 
| Chris Lattner | 09ee05b | 2004-08-11 02:25:00 +0000 | [diff] [blame] | 225 | void printMemoryOperand(const MachineInstr *MI, unsigned OpNo, | 
|  | 226 | MVT::ValueType VT) { | 
|  | 227 | switch (VT) { | 
|  | 228 | default: assert(0 && "Unknown arg size!"); | 
|  | 229 | case MVT::i8:   O << "BYTE PTR "; break; | 
|  | 230 | case MVT::i16:  O << "WORD PTR "; break; | 
|  | 231 | case MVT::i32: | 
|  | 232 | case MVT::f32:  O << "DWORD PTR "; break; | 
|  | 233 | case MVT::i64: | 
|  | 234 | case MVT::f64:  O << "QWORD PTR "; break; | 
|  | 235 | case MVT::f80:  O << "XWORD PTR "; break; | 
|  | 236 | } | 
|  | 237 | printMemReference(MI, OpNo); | 
|  | 238 | } | 
|  | 239 |  | 
| Brian Gaeke | 46f8b71 | 2003-07-24 20:20:44 +0000 | [diff] [blame] | 240 | void printMachineInstruction(const MachineInstr *MI); | 
| Misha Brukman | c968b87 | 2004-06-29 19:28:53 +0000 | [diff] [blame] | 241 | void printOp(const MachineOperand &MO, bool elideOffsetKeyword = false); | 
| Brian Gaeke | 46f8b71 | 2003-07-24 20:20:44 +0000 | [diff] [blame] | 242 | void printMemReference(const MachineInstr *MI, unsigned Op); | 
| Brian Gaeke | 25e766a | 2003-06-25 18:01:07 +0000 | [diff] [blame] | 243 | bool runOnMachineFunction(MachineFunction &F); | 
| Brian Gaeke | 259fdbc | 2003-06-19 19:32:32 +0000 | [diff] [blame] | 244 | bool doInitialization(Module &M); | 
| Chris Lattner | 02a3d83 | 2002-10-29 22:37:54 +0000 | [diff] [blame] | 245 | }; | 
| Brian Gaeke | c1e4ee0 | 2003-06-27 00:00:48 +0000 | [diff] [blame] | 246 | } // end of anonymous namespace | 
| Chris Lattner | 02a3d83 | 2002-10-29 22:37:54 +0000 | [diff] [blame] | 247 |  | 
| Chris Lattner | 9520d20 | 2004-08-01 06:02:08 +0000 | [diff] [blame] | 248 |  | 
|  | 249 | // Include the auto-generated portion of the assembly writer. | 
| Chris Lattner | 20d74fd | 2004-12-16 17:33:24 +0000 | [diff] [blame] | 250 | #include "X86GenAsmWriter1.inc" | 
| Chris Lattner | 9520d20 | 2004-08-01 06:02:08 +0000 | [diff] [blame] | 251 |  | 
|  | 252 |  | 
| Brian Gaeke | c3998cb | 2003-07-23 18:37:06 +0000 | [diff] [blame] | 253 | /// runOnMachineFunction - This uses the printMachineInstruction() | 
|  | 254 | /// method to print assembly for each instruction. | 
|  | 255 | /// | 
| Chris Lattner | 5683260 | 2004-10-03 20:36:57 +0000 | [diff] [blame] | 256 | bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) { | 
| Chris Lattner | 9cf4645 | 2004-08-16 23:16:06 +0000 | [diff] [blame] | 257 | setupMachineFunction(MF); | 
| Chris Lattner | 5dcb654 | 2003-08-03 23:37:09 +0000 | [diff] [blame] | 258 | O << "\n\n"; | 
| Brian Gaeke | c1e4ee0 | 2003-06-27 00:00:48 +0000 | [diff] [blame] | 259 |  | 
| Chris Lattner | 956e837 | 2003-01-13 00:35:03 +0000 | [diff] [blame] | 260 | // Print out constants referenced by the function | 
| Brian Gaeke | 25e766a | 2003-06-25 18:01:07 +0000 | [diff] [blame] | 261 | printConstantPool(MF.getConstantPool()); | 
| Chris Lattner | 956e837 | 2003-01-13 00:35:03 +0000 | [diff] [blame] | 262 |  | 
| Brian Gaeke | e745435 | 2002-11-14 22:32:30 +0000 | [diff] [blame] | 263 | // Print out labels for the function. | 
| Chris Lattner | 956e837 | 2003-01-13 00:35:03 +0000 | [diff] [blame] | 264 | O << "\t.text\n"; | 
| Chris Lattner | 866b58d | 2004-08-17 19:25:42 +0000 | [diff] [blame] | 265 | emitAlignment(4); | 
| Brian Gaeke | c1e4ee0 | 2003-06-27 00:00:48 +0000 | [diff] [blame] | 266 | O << "\t.globl\t" << CurrentFnName << "\n"; | 
| Reid Spencer | 30226da | 2005-01-23 03:52:14 +0000 | [diff] [blame] | 267 | if (!forCygwin) | 
|  | 268 | O << "\t.type\t" << CurrentFnName << ", @function\n"; | 
| Brian Gaeke | c1e4ee0 | 2003-06-27 00:00:48 +0000 | [diff] [blame] | 269 | O << CurrentFnName << ":\n"; | 
| Brian Gaeke | e745435 | 2002-11-14 22:32:30 +0000 | [diff] [blame] | 270 |  | 
|  | 271 | // Print out code for the function. | 
| Chris Lattner | 1520c5a | 2002-12-28 20:25:38 +0000 | [diff] [blame] | 272 | for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); | 
|  | 273 | I != E; ++I) { | 
| Chris Lattner | 56c4c99 | 2004-11-13 23:27:11 +0000 | [diff] [blame] | 274 | // Print a label for the basic block if there are any predecessors. | 
|  | 275 | if (I->pred_begin() != I->pred_end()) | 
|  | 276 | O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t" | 
|  | 277 | << CommentString << " " << I->getBasicBlock()->getName() << "\n"; | 
| Chris Lattner | 1520c5a | 2002-12-28 20:25:38 +0000 | [diff] [blame] | 278 | for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); | 
| Misha Brukman | c968b87 | 2004-06-29 19:28:53 +0000 | [diff] [blame] | 279 | II != E; ++II) { | 
| Chris Lattner | 1520c5a | 2002-12-28 20:25:38 +0000 | [diff] [blame] | 280 | // Print the assembly for the instruction. | 
|  | 281 | O << "\t"; | 
| Alkis Evlogimenos | 80da865 | 2004-02-12 02:27:10 +0000 | [diff] [blame] | 282 | printMachineInstruction(II); | 
| Brian Gaeke | e745435 | 2002-11-14 22:32:30 +0000 | [diff] [blame] | 283 | } | 
| Chris Lattner | 1520c5a | 2002-12-28 20:25:38 +0000 | [diff] [blame] | 284 | } | 
| Brian Gaeke | e745435 | 2002-11-14 22:32:30 +0000 | [diff] [blame] | 285 |  | 
|  | 286 | // We didn't modify anything. | 
| Chris Lattner | 02a3d83 | 2002-10-29 22:37:54 +0000 | [diff] [blame] | 287 | return false; | 
|  | 288 | } | 
|  | 289 |  | 
| Chris Lattner | 5683260 | 2004-10-03 20:36:57 +0000 | [diff] [blame] | 290 | void X86IntelAsmPrinter::printOp(const MachineOperand &MO, | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 291 | bool elideOffsetKeyword /* = false */) { | 
| Brian Gaeke | a92dce4 | 2003-07-23 20:25:08 +0000 | [diff] [blame] | 292 | const MRegisterInfo &RI = *TM.getRegisterInfo(); | 
| Chris Lattner | 5812f06 | 2002-11-18 06:56:51 +0000 | [diff] [blame] | 293 | switch (MO.getType()) { | 
|  | 294 | case MachineOperand::MO_VirtualRegister: | 
| Chris Lattner | fb8032d | 2002-12-04 17:32:52 +0000 | [diff] [blame] | 295 | if (Value *V = MO.getVRegValueOrNull()) { | 
| Chris Lattner | 6425a50 | 2002-12-04 06:45:19 +0000 | [diff] [blame] | 296 | O << "<" << V->getName() << ">"; | 
|  | 297 | return; | 
|  | 298 | } | 
| Chris Lattner | 956e837 | 2003-01-13 00:35:03 +0000 | [diff] [blame] | 299 | // FALLTHROUGH | 
| Misha Brukman | 6e5d493 | 2002-11-20 18:56:41 +0000 | [diff] [blame] | 300 | case MachineOperand::MO_MachineRegister: | 
| Alkis Evlogimenos | bbf5393 | 2004-02-15 21:37:17 +0000 | [diff] [blame] | 301 | if (MRegisterInfo::isPhysicalRegister(MO.getReg())) | 
| Brian Gaeke | 12b3253 | 2003-08-11 19:05:46 +0000 | [diff] [blame] | 302 | // Bug Workaround: See note in Printer::doInitialization about %. | 
| Brian Gaeke | 1600c4a | 2003-08-13 18:15:15 +0000 | [diff] [blame] | 303 | O << "%" << RI.get(MO.getReg()).Name; | 
|  | 304 | else | 
| Chris Lattner | 5812f06 | 2002-11-18 06:56:51 +0000 | [diff] [blame] | 305 | O << "%reg" << MO.getReg(); | 
|  | 306 | return; | 
| Chris Lattner | 177e928 | 2002-11-21 02:00:20 +0000 | [diff] [blame] | 307 |  | 
|  | 308 | case MachineOperand::MO_SignExtendedImmed: | 
|  | 309 | case MachineOperand::MO_UnextendedImmed: | 
|  | 310 | O << (int)MO.getImmedValue(); | 
|  | 311 | return; | 
| Brian Gaeke | 2b3a81c | 2004-05-14 06:54:57 +0000 | [diff] [blame] | 312 | case MachineOperand::MO_MachineBasicBlock: { | 
|  | 313 | MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); | 
|  | 314 | O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction()) | 
|  | 315 | << "_" << MBBOp->getNumber () << "\t# " | 
|  | 316 | << MBBOp->getBasicBlock ()->getName (); | 
| Chris Lattner | 08cd1ed | 2002-12-01 23:25:59 +0000 | [diff] [blame] | 317 | return; | 
| Chris Lattner | 230cffb | 2003-09-09 16:23:36 +0000 | [diff] [blame] | 318 | } | 
| Brian Gaeke | 2b3a81c | 2004-05-14 06:54:57 +0000 | [diff] [blame] | 319 | case MachineOperand::MO_PCRelativeDisp: | 
|  | 320 | std::cerr << "Shouldn't use addPCDisp() when building X86 MachineInstrs"; | 
|  | 321 | abort (); | 
|  | 322 | return; | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 323 | case MachineOperand::MO_GlobalAddress: { | 
| Brian Gaeke | a2d9f40 | 2003-07-31 17:38:52 +0000 | [diff] [blame] | 324 | if (!elideOffsetKeyword) | 
|  | 325 | O << "OFFSET "; | 
|  | 326 | O << Mang->getValueName(MO.getGlobal()); | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 327 | int Offset = MO.getOffset(); | 
|  | 328 | if (Offset > 0) | 
|  | 329 | O << " + " << Offset; | 
|  | 330 | else if (Offset < 0) | 
|  | 331 | O << " - " << -Offset; | 
| Chris Lattner | 956e837 | 2003-01-13 00:35:03 +0000 | [diff] [blame] | 332 | return; | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 333 | } | 
| Chris Lattner | 956e837 | 2003-01-13 00:35:03 +0000 | [diff] [blame] | 334 | case MachineOperand::MO_ExternalSymbol: | 
| Reid Spencer | 30226da | 2005-01-23 03:52:14 +0000 | [diff] [blame] | 335 | O << GlobalPrefix << MO.getSymbolName(); | 
| Chris Lattner | 956e837 | 2003-01-13 00:35:03 +0000 | [diff] [blame] | 336 | return; | 
| Chris Lattner | 5812f06 | 2002-11-18 06:56:51 +0000 | [diff] [blame] | 337 | default: | 
| Brian Gaeke | 25e766a | 2003-06-25 18:01:07 +0000 | [diff] [blame] | 338 | O << "<unknown operand type>"; return; | 
| Chris Lattner | 5812f06 | 2002-11-18 06:56:51 +0000 | [diff] [blame] | 339 | } | 
|  | 340 | } | 
|  | 341 |  | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 342 | void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){ | 
| Chris Lattner | 61fafd35 | 2002-11-21 20:44:15 +0000 | [diff] [blame] | 343 | assert(isMem(MI, Op) && "Invalid memory reference!"); | 
| Chris Lattner | 956e837 | 2003-01-13 00:35:03 +0000 | [diff] [blame] | 344 |  | 
| Chris Lattner | 61fafd35 | 2002-11-21 20:44:15 +0000 | [diff] [blame] | 345 | const MachineOperand &BaseReg  = MI->getOperand(Op); | 
| Chris Lattner | 1520c5a | 2002-12-28 20:25:38 +0000 | [diff] [blame] | 346 | int ScaleVal                   = MI->getOperand(Op+1).getImmedValue(); | 
| Chris Lattner | 61fafd35 | 2002-11-21 20:44:15 +0000 | [diff] [blame] | 347 | const MachineOperand &IndexReg = MI->getOperand(Op+2); | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 348 | const MachineOperand &DispSpec = MI->getOperand(Op+3); | 
| Chris Lattner | 61fafd35 | 2002-11-21 20:44:15 +0000 | [diff] [blame] | 349 |  | 
| Chris Lattner | af19d39 | 2004-10-17 07:16:32 +0000 | [diff] [blame] | 350 | if (BaseReg.isFrameIndex()) { | 
|  | 351 | O << "[frame slot #" << BaseReg.getFrameIndex(); | 
|  | 352 | if (DispSpec.getImmedValue()) | 
|  | 353 | O << " + " << DispSpec.getImmedValue(); | 
|  | 354 | O << "]"; | 
|  | 355 | return; | 
|  | 356 | } else if (BaseReg.isConstantPoolIndex()) { | 
|  | 357 | O << "[.CPI" << CurrentFnName << "_" | 
|  | 358 | << BaseReg.getConstantPoolIndex(); | 
|  | 359 |  | 
|  | 360 | if (IndexReg.getReg()) { | 
|  | 361 | O << " + "; | 
|  | 362 | if (ScaleVal != 1) | 
|  | 363 | O << ScaleVal << "*"; | 
|  | 364 | printOp(IndexReg); | 
|  | 365 | } | 
|  | 366 |  | 
|  | 367 | if (DispSpec.getImmedValue()) | 
|  | 368 | O << " + " << DispSpec.getImmedValue(); | 
|  | 369 | O << "]"; | 
|  | 370 | return; | 
|  | 371 | } | 
|  | 372 |  | 
| Chris Lattner | 61fafd35 | 2002-11-21 20:44:15 +0000 | [diff] [blame] | 373 | O << "["; | 
|  | 374 | bool NeedPlus = false; | 
|  | 375 | if (BaseReg.getReg()) { | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 376 | printOp(BaseReg, true); | 
| Chris Lattner | 61fafd35 | 2002-11-21 20:44:15 +0000 | [diff] [blame] | 377 | NeedPlus = true; | 
|  | 378 | } | 
|  | 379 |  | 
|  | 380 | if (IndexReg.getReg()) { | 
|  | 381 | if (NeedPlus) O << " + "; | 
| Chris Lattner | 1520c5a | 2002-12-28 20:25:38 +0000 | [diff] [blame] | 382 | if (ScaleVal != 1) | 
|  | 383 | O << ScaleVal << "*"; | 
| Brian Gaeke | a92dce4 | 2003-07-23 20:25:08 +0000 | [diff] [blame] | 384 | printOp(IndexReg); | 
| Chris Lattner | 61fafd35 | 2002-11-21 20:44:15 +0000 | [diff] [blame] | 385 | NeedPlus = true; | 
|  | 386 | } | 
|  | 387 |  | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 388 | if (DispSpec.isGlobalAddress()) { | 
| Chris Lattner | 1520c5a | 2002-12-28 20:25:38 +0000 | [diff] [blame] | 389 | if (NeedPlus) | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 390 | O << " + "; | 
|  | 391 | printOp(DispSpec, true); | 
|  | 392 | } else { | 
|  | 393 | int DispVal = DispSpec.getImmedValue(); | 
| Chris Lattner | bb4c14f | 2005-01-12 04:07:11 +0000 | [diff] [blame] | 394 | if (DispVal || (!BaseReg.getReg() && !IndexReg.getReg())) { | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 395 | if (NeedPlus) | 
|  | 396 | if (DispVal > 0) | 
|  | 397 | O << " + "; | 
|  | 398 | else { | 
|  | 399 | O << " - "; | 
|  | 400 | DispVal = -DispVal; | 
|  | 401 | } | 
|  | 402 | O << DispVal; | 
|  | 403 | } | 
| Chris Lattner | 61fafd35 | 2002-11-21 20:44:15 +0000 | [diff] [blame] | 404 | } | 
|  | 405 | O << "]"; | 
|  | 406 | } | 
|  | 407 |  | 
| John Criswell | 10db062 | 2004-04-08 20:31:47 +0000 | [diff] [blame] | 408 |  | 
| Brian Gaeke | c3998cb | 2003-07-23 18:37:06 +0000 | [diff] [blame] | 409 | /// printMachineInstruction -- Print out a single X86 LLVM instruction | 
| Brian Gaeke | a92dce4 | 2003-07-23 20:25:08 +0000 | [diff] [blame] | 410 | /// MI in Intel syntax to the current output stream. | 
| Brian Gaeke | c1e4ee0 | 2003-06-27 00:00:48 +0000 | [diff] [blame] | 411 | /// | 
| Chris Lattner | 5683260 | 2004-10-03 20:36:57 +0000 | [diff] [blame] | 412 | void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) { | 
| Chris Lattner | 9520d20 | 2004-08-01 06:02:08 +0000 | [diff] [blame] | 413 | ++EmittedInsts; | 
| Chris Lattner | b975636 | 2004-08-11 06:09:55 +0000 | [diff] [blame] | 414 |  | 
| Chris Lattner | d1bee6e | 2004-08-11 07:02:04 +0000 | [diff] [blame] | 415 | // Call the autogenerated instruction printer routines. | 
| Chris Lattner | d1ab378 | 2004-10-04 07:31:08 +0000 | [diff] [blame] | 416 | printInstruction(MI); | 
| Chris Lattner | d92fb00 | 2002-10-25 22:55:53 +0000 | [diff] [blame] | 417 | } | 
| Brian Gaeke | 259fdbc | 2003-06-19 19:32:32 +0000 | [diff] [blame] | 418 |  | 
| Chris Lattner | 5683260 | 2004-10-03 20:36:57 +0000 | [diff] [blame] | 419 | bool X86IntelAsmPrinter::doInitialization(Module &M) { | 
| Chris Lattner | 9cf4645 | 2004-08-16 23:16:06 +0000 | [diff] [blame] | 420 | AsmPrinter::doInitialization(M); | 
| Chris Lattner | 9a59f58 | 2003-08-11 19:35:26 +0000 | [diff] [blame] | 421 | // Tell gas we are outputting Intel syntax (not AT&T syntax) assembly. | 
| Brian Gaeke | 12b3253 | 2003-08-11 19:05:46 +0000 | [diff] [blame] | 422 | // | 
| Chris Lattner | 9a59f58 | 2003-08-11 19:35:26 +0000 | [diff] [blame] | 423 | // Bug: gas in `intel_syntax noprefix' mode interprets the symbol `Sp' in an | 
|  | 424 | // instruction as a reference to the register named sp, and if you try to | 
|  | 425 | // reference a symbol `Sp' (e.g. `mov ECX, OFFSET Sp') then it gets lowercased | 
|  | 426 | // before being looked up in the symbol table. This creates spurious | 
|  | 427 | // `undefined symbol' errors when linking. Workaround: Do not use `noprefix' | 
|  | 428 | // mode, and decorate all register names with percent signs. | 
| Chris Lattner | 262c832 | 2003-08-11 20:04:57 +0000 | [diff] [blame] | 429 | O << "\t.intel_syntax\n"; | 
| Chris Lattner | 9cf4645 | 2004-08-16 23:16:06 +0000 | [diff] [blame] | 430 | return false; | 
| Brian Gaeke | 259fdbc | 2003-06-19 19:32:32 +0000 | [diff] [blame] | 431 | } | 
|  | 432 |  | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 433 |  | 
|  | 434 |  | 
|  | 435 | namespace { | 
|  | 436 | struct X86ATTAsmPrinter : public X86SharedAsmPrinter { | 
|  | 437 | X86ATTAsmPrinter(std::ostream &O, TargetMachine &TM) | 
|  | 438 | : X86SharedAsmPrinter(O, TM) { } | 
|  | 439 |  | 
|  | 440 | virtual const char *getPassName() const { | 
|  | 441 | return "X86 AT&T-Style Assembly Printer"; | 
|  | 442 | } | 
|  | 443 |  | 
|  | 444 | /// printInstruction - This method is automatically generated by tablegen | 
|  | 445 | /// from the instruction set description.  This method returns true if the | 
|  | 446 | /// machine instruction was sufficiently described to print it, otherwise it | 
|  | 447 | /// returns false. | 
|  | 448 | bool printInstruction(const MachineInstr *MI); | 
|  | 449 |  | 
|  | 450 | // This method is used by the tablegen'erated instruction printer. | 
|  | 451 | void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){ | 
|  | 452 | printOp(MI->getOperand(OpNo)); | 
|  | 453 | } | 
|  | 454 |  | 
|  | 455 | void printCallOperand(const MachineInstr *MI, unsigned OpNo, | 
|  | 456 | MVT::ValueType VT) { | 
|  | 457 | printOp(MI->getOperand(OpNo), true); // Don't print '$' prefix. | 
|  | 458 | } | 
|  | 459 |  | 
|  | 460 | void printMemoryOperand(const MachineInstr *MI, unsigned OpNo, | 
|  | 461 | MVT::ValueType VT) { | 
|  | 462 | printMemReference(MI, OpNo); | 
|  | 463 | } | 
|  | 464 |  | 
|  | 465 | void printMachineInstruction(const MachineInstr *MI); | 
|  | 466 | void printOp(const MachineOperand &MO, bool isCallOperand = false); | 
|  | 467 | void printMemReference(const MachineInstr *MI, unsigned Op); | 
|  | 468 | bool runOnMachineFunction(MachineFunction &F); | 
|  | 469 | }; | 
|  | 470 | } // end of anonymous namespace | 
|  | 471 |  | 
|  | 472 |  | 
|  | 473 | // Include the auto-generated portion of the assembly writer. | 
| Chris Lattner | 20d74fd | 2004-12-16 17:33:24 +0000 | [diff] [blame] | 474 | #include "X86GenAsmWriter.inc" | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 475 |  | 
|  | 476 |  | 
|  | 477 | /// runOnMachineFunction - This uses the printMachineInstruction() | 
|  | 478 | /// method to print assembly for each instruction. | 
|  | 479 | /// | 
|  | 480 | bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) { | 
|  | 481 | setupMachineFunction(MF); | 
|  | 482 | O << "\n\n"; | 
|  | 483 |  | 
|  | 484 | // Print out constants referenced by the function | 
|  | 485 | printConstantPool(MF.getConstantPool()); | 
|  | 486 |  | 
|  | 487 | // Print out labels for the function. | 
|  | 488 | O << "\t.text\n"; | 
|  | 489 | emitAlignment(4); | 
|  | 490 | O << "\t.globl\t" << CurrentFnName << "\n"; | 
| Reid Spencer | 30226da | 2005-01-23 03:52:14 +0000 | [diff] [blame] | 491 | if (!forCygwin) | 
|  | 492 | O << "\t.type\t" << CurrentFnName << ", @function\n"; | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 493 | O << CurrentFnName << ":\n"; | 
|  | 494 |  | 
|  | 495 | // Print out code for the function. | 
|  | 496 | for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); | 
|  | 497 | I != E; ++I) { | 
|  | 498 | // Print a label for the basic block. | 
| Chris Lattner | 56c4c99 | 2004-11-13 23:27:11 +0000 | [diff] [blame] | 499 | if (I->pred_begin() != I->pred_end()) | 
|  | 500 | O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t" | 
|  | 501 | << CommentString << " " << I->getBasicBlock()->getName() << "\n"; | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 502 | for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); | 
|  | 503 | II != E; ++II) { | 
|  | 504 | // Print the assembly for the instruction. | 
|  | 505 | O << "\t"; | 
|  | 506 | printMachineInstruction(II); | 
|  | 507 | } | 
|  | 508 | } | 
|  | 509 |  | 
|  | 510 | // We didn't modify anything. | 
|  | 511 | return false; | 
|  | 512 | } | 
|  | 513 |  | 
|  | 514 | void X86ATTAsmPrinter::printOp(const MachineOperand &MO, bool isCallOp) { | 
|  | 515 | const MRegisterInfo &RI = *TM.getRegisterInfo(); | 
|  | 516 | switch (MO.getType()) { | 
|  | 517 | case MachineOperand::MO_VirtualRegister: | 
|  | 518 | case MachineOperand::MO_MachineRegister: | 
|  | 519 | assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) && | 
|  | 520 | "Virtual registers should not make it this far!"); | 
|  | 521 | O << '%'; | 
|  | 522 | for (const char *Name = RI.get(MO.getReg()).Name; *Name; ++Name) | 
|  | 523 | O << (char)tolower(*Name); | 
|  | 524 | return; | 
|  | 525 |  | 
|  | 526 | case MachineOperand::MO_SignExtendedImmed: | 
|  | 527 | case MachineOperand::MO_UnextendedImmed: | 
|  | 528 | O << '$' << (int)MO.getImmedValue(); | 
|  | 529 | return; | 
|  | 530 | case MachineOperand::MO_MachineBasicBlock: { | 
|  | 531 | MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); | 
|  | 532 | O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction()) | 
|  | 533 | << "_" << MBBOp->getNumber () << "\t# " | 
|  | 534 | << MBBOp->getBasicBlock ()->getName (); | 
|  | 535 | return; | 
|  | 536 | } | 
|  | 537 | case MachineOperand::MO_PCRelativeDisp: | 
|  | 538 | std::cerr << "Shouldn't use addPCDisp() when building X86 MachineInstrs"; | 
|  | 539 | abort (); | 
|  | 540 | return; | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 541 | case MachineOperand::MO_GlobalAddress: { | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 542 | if (!isCallOp) O << '$'; | 
|  | 543 | O << Mang->getValueName(MO.getGlobal()); | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 544 | int Offset = MO.getOffset(); | 
|  | 545 | if (Offset > 0) | 
|  | 546 | O << "+" << Offset; | 
|  | 547 | else if (Offset < 0) | 
|  | 548 | O << Offset; | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 549 | return; | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 550 | } | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 551 | case MachineOperand::MO_ExternalSymbol: | 
|  | 552 | if (!isCallOp) O << '$'; | 
| Reid Spencer | 30226da | 2005-01-23 03:52:14 +0000 | [diff] [blame] | 553 | O << GlobalPrefix << MO.getSymbolName(); | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 554 | return; | 
|  | 555 | default: | 
|  | 556 | O << "<unknown operand type>"; return; | 
| Chris Lattner | 230cffb | 2003-09-09 16:23:36 +0000 | [diff] [blame] | 557 | } | 
| Brian Gaeke | b99d684 | 2003-07-11 21:57:01 +0000 | [diff] [blame] | 558 | } | 
|  | 559 |  | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 560 | void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){ | 
|  | 561 | assert(isMem(MI, Op) && "Invalid memory reference!"); | 
| Chris Lattner | 230cffb | 2003-09-09 16:23:36 +0000 | [diff] [blame] | 562 |  | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 563 | const MachineOperand &BaseReg  = MI->getOperand(Op); | 
|  | 564 | int ScaleVal                   = MI->getOperand(Op+1).getImmedValue(); | 
|  | 565 | const MachineOperand &IndexReg = MI->getOperand(Op+2); | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 566 | const MachineOperand &DispSpec = MI->getOperand(Op+3); | 
| Chris Lattner | 230cffb | 2003-09-09 16:23:36 +0000 | [diff] [blame] | 567 |  | 
| Chris Lattner | af19d39 | 2004-10-17 07:16:32 +0000 | [diff] [blame] | 568 | if (BaseReg.isFrameIndex()) { | 
|  | 569 | O << "[frame slot #" << BaseReg.getFrameIndex(); | 
|  | 570 | if (DispSpec.getImmedValue()) | 
|  | 571 | O << " + " << DispSpec.getImmedValue(); | 
|  | 572 | O << "]"; | 
|  | 573 | return; | 
|  | 574 | } else if (BaseReg.isConstantPoolIndex()) { | 
|  | 575 | O << ".CPI" << CurrentFnName << "_" | 
|  | 576 | << BaseReg.getConstantPoolIndex(); | 
|  | 577 | if (DispSpec.getImmedValue()) | 
|  | 578 | O << "+" << DispSpec.getImmedValue(); | 
|  | 579 | if (IndexReg.getReg()) { | 
|  | 580 | O << "(,"; | 
|  | 581 | printOp(IndexReg); | 
|  | 582 | if (ScaleVal != 1) | 
|  | 583 | O << "," << ScaleVal; | 
|  | 584 | O << ")"; | 
|  | 585 | } | 
|  | 586 | return; | 
|  | 587 | } | 
|  | 588 |  | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 589 | if (DispSpec.isGlobalAddress()) { | 
|  | 590 | printOp(DispSpec, true); | 
|  | 591 | } else { | 
|  | 592 | int DispVal = DispSpec.getImmedValue(); | 
| Chris Lattner | b372fab | 2005-01-12 04:05:19 +0000 | [diff] [blame] | 593 | if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 594 | O << DispVal; | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 595 | } | 
|  | 596 |  | 
| Chris Lattner | 19025d5 | 2004-10-15 04:44:53 +0000 | [diff] [blame] | 597 | if (IndexReg.getReg() || BaseReg.getReg()) { | 
|  | 598 | O << "("; | 
|  | 599 | if (BaseReg.getReg()) | 
|  | 600 | printOp(BaseReg); | 
|  | 601 |  | 
|  | 602 | if (IndexReg.getReg()) { | 
|  | 603 | O << ","; | 
|  | 604 | printOp(IndexReg); | 
|  | 605 | if (ScaleVal != 1) | 
|  | 606 | O << "," << ScaleVal; | 
|  | 607 | } | 
|  | 608 |  | 
|  | 609 | O << ")"; | 
|  | 610 | } | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 611 | } | 
|  | 612 |  | 
|  | 613 |  | 
|  | 614 | /// printMachineInstruction -- Print out a single X86 LLVM instruction | 
|  | 615 | /// MI in Intel syntax to the current output stream. | 
|  | 616 | /// | 
|  | 617 | void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) { | 
|  | 618 | ++EmittedInsts; | 
|  | 619 | // Call the autogenerated instruction printer routines. | 
| Chris Lattner | d1ab378 | 2004-10-04 07:31:08 +0000 | [diff] [blame] | 620 | printInstruction(MI); | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 621 | } | 
|  | 622 |  | 
|  | 623 |  | 
|  | 624 | /// createX86CodePrinterPass - Returns a pass that prints the X86 assembly code | 
|  | 625 | /// for a MachineFunction to the given output stream, using the given target | 
|  | 626 | /// machine description. | 
|  | 627 | /// | 
|  | 628 | FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){ | 
|  | 629 | switch (AsmWriterFlavor) { | 
| Reid Spencer | 30226da | 2005-01-23 03:52:14 +0000 | [diff] [blame] | 630 | default: | 
|  | 631 | assert(0 && "Unknown asm flavor!"); | 
| Chris Lattner | 68ab0be | 2004-10-04 07:24:48 +0000 | [diff] [blame] | 632 | case intel: | 
|  | 633 | return new X86IntelAsmPrinter(o, tm); | 
|  | 634 | case att: | 
|  | 635 | return new X86ATTAsmPrinter(o, tm); | 
|  | 636 | } | 
| Brian Gaeke | 259fdbc | 2003-06-19 19:32:32 +0000 | [diff] [blame] | 637 | } |