blob: d6545d6281f8b6723da66a9084d87d3650c7a9f5 [file] [log] [blame]
Chris Lattnerfadc83c2009-06-19 00:47:59 +00001//===-- X86ATTInstPrinter.cpp - AT&T assembly instruction printing --------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file includes code for rendering MCInst instances as AT&T-style
11// assembly.
12//
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "asm-printer"
16#include "llvm/MC/MCInst.h"
17#include "X86ATTAsmPrinter.h"
Chris Lattnerc1243062009-06-20 07:03:18 +000018#include "llvm/Target/TargetAsmInfo.h"
Chris Lattnerd5fb7902009-06-19 23:59:57 +000019#include "llvm/Support/raw_ostream.h"
Chris Lattnerfadc83c2009-06-19 00:47:59 +000020using namespace llvm;
21
Chris Lattnerd5fb7902009-06-19 23:59:57 +000022// Include the auto-generated portion of the assembly writer.
23#define MachineInstr MCInst
24#define NO_ASM_WRITER_BOILERPLATE
25#include "X86GenAsmWriter.inc"
26#undef MachineInstr
27
28void X86ATTAsmPrinter::printSSECC(const MCInst *MI, unsigned Op) {
Chris Lattnerc1243062009-06-20 07:03:18 +000029 switch (MI->getOperand(Op).getImm()) {
30 default: assert(0 && "Invalid ssecc argument!");
Chris Lattnerf38c03af2009-06-20 00:49:26 +000031 case 0: O << "eq"; break;
32 case 1: O << "lt"; break;
33 case 2: O << "le"; break;
34 case 3: O << "unord"; break;
35 case 4: O << "neq"; break;
36 case 5: O << "nlt"; break;
37 case 6: O << "nle"; break;
38 case 7: O << "ord"; break;
Chris Lattnerd5fb7902009-06-19 23:59:57 +000039 }
40}
41
42
43void X86ATTAsmPrinter::printPICLabel(const MCInst *MI, unsigned Op) {
44 assert(0 &&
45 "This is only used for MOVPC32r, should lower before asm printing!");
46}
47
48
Chris Lattner7680e732009-06-20 19:34:09 +000049/// print_pcrel_imm - This is used to print an immediate value that ends up
50/// being encoded as a pc-relative value. These print slightly differently, for
51/// example, a $ is not emitted.
52void X86ATTAsmPrinter::print_pcrel_imm(const MCInst *MI, unsigned OpNo) {
53 const MCOperand &Op = MI->getOperand(OpNo);
54
55 if (Op.isImm())
56 O << Op.getImm();
57 else if (Op.isMBBLabel())
58 // FIXME: Keep in sync with printBasicBlockLabel. printBasicBlockLabel
59 // should eventually call into this code, not the other way around.
60 O << TAI->getPrivateGlobalPrefix() << "BB" << Op.getMBBLabelFunction()
61 << '_' << Op.getMBBLabelBlock();
62 else
63 assert(0 && "Unknown pcrel immediate operand");
64}
65
66
Chris Lattnerd5fb7902009-06-19 23:59:57 +000067void X86ATTAsmPrinter::printOperand(const MCInst *MI, unsigned OpNo,
68 const char *Modifier, bool NotRIPRel) {
Chris Lattnerc1243062009-06-20 07:03:18 +000069 assert(Modifier == 0 && "Modifiers should not be used");
Chris Lattnerf38c03af2009-06-20 00:49:26 +000070
71 const MCOperand &Op = MI->getOperand(OpNo);
72 if (Op.isReg()) {
73 O << '%';
74 unsigned Reg = Op.getReg();
75#if 0
76 if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
77 MVT VT = (strcmp(Modifier+6,"64") == 0) ?
78 MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 :
79 ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8));
80 Reg = getX86SubSuperRegister(Reg, VT);
81 }
82#endif
83 O << TRI->getAsmName(Reg);
84 return;
85 } else if (Op.isImm()) {
86 //if (!Modifier || (strcmp(Modifier, "debug") && strcmp(Modifier, "mem") &&
87 // strcmp(Modifier, "call")))
88 O << '$';
89 O << Op.getImm();
90 return;
91 }
92
93 O << "<<UNKNOWN OPERAND KIND>>";
94
95
96#if 0
97 const MachineOperand &MO = MI->getOperand(OpNo);
98 switch (MO.getType()) {
99 case MachineOperand::MO_Register: {
100 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
101 "Virtual registers should not make it this far!");
102 O << '%';
103 unsigned Reg = MO.getReg();
104 if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
105 MVT VT = (strcmp(Modifier+6,"64") == 0) ?
106 MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 :
107 ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8));
108 Reg = getX86SubSuperRegister(Reg, VT);
109 }
110 O << TRI->getAsmName(Reg);
111 return;
112 }
113
114 case MachineOperand::MO_Immediate:
115 if (!Modifier || (strcmp(Modifier, "debug") &&
116 strcmp(Modifier, "mem") &&
117 strcmp(Modifier, "call")))
118 O << '$';
119 O << MO.getImm();
120 return;
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000121 case MachineOperand::MO_JumpTableIndex: {
122 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
123 if (!isMemOp) O << '$';
124 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
125 << MO.getIndex();
126
127 if (TM.getRelocationModel() == Reloc::PIC_) {
128 if (Subtarget->isPICStyleStub())
129 O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
130 << "$pb\"";
131 else if (Subtarget->isPICStyleGOT())
132 O << "@GOTOFF";
133 }
134
135 if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel)
136 O << "(%rip)";
137 return;
138 }
139 case MachineOperand::MO_ConstantPoolIndex: {
140 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
141 if (!isMemOp) O << '$';
142 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
143 << MO.getIndex();
144
145 if (TM.getRelocationModel() == Reloc::PIC_) {
146 if (Subtarget->isPICStyleStub())
147 O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
148 << "$pb\"";
149 else if (Subtarget->isPICStyleGOT())
150 O << "@GOTOFF";
151 }
152
153 printOffset(MO.getOffset());
154
155 if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel)
156 O << "(%rip)";
157 return;
158 }
159 case MachineOperand::MO_GlobalAddress: {
160 bool isCallOp = Modifier && !strcmp(Modifier, "call");
161 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
162 bool needCloseParen = false;
163
164 const GlobalValue *GV = MO.getGlobal();
165 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
166 if (!GVar) {
167 // If GV is an alias then use the aliasee for determining
168 // thread-localness.
169 if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
170 GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false));
171 }
172
173 bool isThreadLocal = GVar && GVar->isThreadLocal();
174
175 std::string Name = Mang->getValueName(GV);
176 decorateName(Name, GV);
177
178 if (!isMemOp && !isCallOp)
179 O << '$';
180 else if (Name[0] == '$') {
181 // The name begins with a dollar-sign. In order to avoid having it look
182 // like an integer immediate to the assembler, enclose it in parens.
183 O << '(';
184 needCloseParen = true;
185 }
186
187 if (shouldPrintStub(TM, Subtarget)) {
188 // Link-once, declaration, or Weakly-linked global variables need
189 // non-lazily-resolved stubs
190 if (GV->isDeclaration() || GV->isWeakForLinker()) {
191 // Dynamically-resolved functions need a stub for the function.
192 if (isCallOp && isa<Function>(GV)) {
193 // Function stubs are no longer needed for Mac OS X 10.5 and up.
194 if (Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9) {
195 O << Name;
196 } else {
197 FnStubs.insert(Name);
198 printSuffixedName(Name, "$stub");
199 }
200 } else if (GV->hasHiddenVisibility()) {
201 if (!GV->isDeclaration() && !GV->hasCommonLinkage())
202 // Definition is not definitely in the current translation unit.
203 O << Name;
204 else {
205 HiddenGVStubs.insert(Name);
206 printSuffixedName(Name, "$non_lazy_ptr");
207 }
208 } else {
209 GVStubs.insert(Name);
210 printSuffixedName(Name, "$non_lazy_ptr");
211 }
212 } else {
213 if (GV->hasDLLImportLinkage())
214 O << "__imp_";
215 O << Name;
216 }
217
218 if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_)
219 O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget);
220 } else {
221 if (GV->hasDLLImportLinkage()) {
222 O << "__imp_";
223 }
224 O << Name;
225
226 if (isCallOp) {
227 if (shouldPrintPLT(TM, Subtarget)) {
228 // Assemble call via PLT for externally visible symbols
229 if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
230 !GV->hasLocalLinkage())
231 O << "@PLT";
232 }
233 if (Subtarget->isTargetCygMing() && GV->isDeclaration())
234 // Save function name for later type emission
235 FnStubs.insert(Name);
236 }
237 }
238
239 if (GV->hasExternalWeakLinkage())
240 ExtWeakSymbols.insert(GV);
241
242 printOffset(MO.getOffset());
243
244 if (isThreadLocal) {
245 TLSModel::Model model = getTLSModel(GVar, TM.getRelocationModel());
246 switch (model) {
247 case TLSModel::GeneralDynamic:
248 O << "@TLSGD";
249 break;
250 case TLSModel::LocalDynamic:
251 // O << "@TLSLD"; // local dynamic not implemented
252 O << "@TLSGD";
253 break;
254 case TLSModel::InitialExec:
255 if (Subtarget->is64Bit()) {
256 assert (!NotRIPRel);
257 O << "@GOTTPOFF(%rip)";
258 } else {
259 O << "@INDNTPOFF";
260 }
261 break;
262 case TLSModel::LocalExec:
263 if (Subtarget->is64Bit())
264 O << "@TPOFF";
265 else
266 O << "@NTPOFF";
267 break;
268 default:
269 assert (0 && "Unknown TLS model");
270 }
271 } else if (isMemOp) {
272 if (shouldPrintGOT(TM, Subtarget)) {
273 if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
274 O << "@GOT";
275 else
276 O << "@GOTOFF";
277 } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel) {
278 if (TM.getRelocationModel() != Reloc::Static) {
279 if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
280 O << "@GOTPCREL";
281
282 if (needCloseParen) {
283 needCloseParen = false;
284 O << ')';
285 }
286 }
287
288 // Use rip when possible to reduce code size, except when
289 // index or base register are also part of the address. e.g.
290 // foo(%rip)(%rcx,%rax,4) is not legal
291 O << "(%rip)";
292 }
293 }
294
295 if (needCloseParen)
296 O << ')';
297
298 return;
299 }
300 case MachineOperand::MO_ExternalSymbol: {
301 bool isCallOp = Modifier && !strcmp(Modifier, "call");
302 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
303 bool needCloseParen = false;
304 std::string Name(TAI->getGlobalPrefix());
305 Name += MO.getSymbolName();
306 // Print function stub suffix unless it's Mac OS X 10.5 and up.
307 if (isCallOp && shouldPrintStub(TM, Subtarget) &&
308 !(Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9)) {
309 FnStubs.insert(Name);
310 printSuffixedName(Name, "$stub");
311 return;
312 }
313 if (!isMemOp && !isCallOp)
314 O << '$';
315 else if (Name[0] == '$') {
316 // The name begins with a dollar-sign. In order to avoid having it look
317 // like an integer immediate to the assembler, enclose it in parens.
318 O << '(';
319 needCloseParen = true;
320 }
321
322 O << Name;
323
324 if (shouldPrintPLT(TM, Subtarget)) {
325 std::string GOTName(TAI->getGlobalPrefix());
326 GOTName+="_GLOBAL_OFFSET_TABLE_";
327 if (Name == GOTName)
328 // HACK! Emit extra offset to PC during printing GOT offset to
329 // compensate for the size of popl instruction. The resulting code
330 // should look like:
331 // call .piclabel
332 // piclabel:
333 // popl %some_register
334 // addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register
335 O << " + [.-"
336 << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']';
337
338 if (isCallOp)
339 O << "@PLT";
340 }
341
342 if (needCloseParen)
343 O << ')';
344
345 if (!isCallOp && Subtarget->isPICStyleRIPRel())
346 O << "(%rip)";
347
348 return;
349 }
350 default:
351 O << "<unknown operand type>"; return;
352 }
353#endif
Chris Lattnerd5fb7902009-06-19 23:59:57 +0000354}
355
Chris Lattnerc1243062009-06-20 07:03:18 +0000356void X86ATTAsmPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) {
Chris Lattnerc1243062009-06-20 07:03:18 +0000357 bool NotRIPRel = false;
358
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000359 const MCOperand &BaseReg = MI->getOperand(Op);
360 const MCOperand &IndexReg = MI->getOperand(Op+2);
361 const MCOperand &DispSpec = MI->getOperand(Op+3);
362
363 NotRIPRel |= IndexReg.getReg() || BaseReg.getReg();
364 if (DispSpec.isImm()) {
365 int64_t DispVal = DispSpec.getImm();
366 if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
367 O << DispVal;
368 } else {
369 abort();
370 //assert(DispSpec.isGlobal() || DispSpec.isCPI() ||
371 // DispSpec.isJTI() || DispSpec.isSymbol());
372 //printOperand(MI, Op+3, "mem", NotRIPRel);
373 }
374
375 if (IndexReg.getReg() || BaseReg.getReg()) {
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000376 // There are cases where we can end up with ESP/RSP in the indexreg slot.
377 // If this happens, swap the base/index register to support assemblers that
378 // don't work when the index is *SP.
379 // FIXME: REMOVE THIS.
Chris Lattnerdc479f62009-06-20 07:59:10 +0000380 assert(IndexReg.getReg() != X86::ESP && IndexReg.getReg() != X86::RSP);
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000381
382 O << '(';
383 if (BaseReg.getReg())
Chris Lattnerdc479f62009-06-20 07:59:10 +0000384 printOperand(MI, Op);
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000385
386 if (IndexReg.getReg()) {
387 O << ',';
Chris Lattnerdc479f62009-06-20 07:59:10 +0000388 printOperand(MI, Op+2);
Chris Lattner7f8217f2009-06-20 08:13:12 +0000389 unsigned ScaleVal = MI->getOperand(Op+1).getImm();
390 if (ScaleVal != 1)
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000391 O << ',' << ScaleVal;
392 }
393 O << ')';
394 }
Chris Lattnerd5fb7902009-06-19 23:59:57 +0000395}
396
Chris Lattnerc1243062009-06-20 07:03:18 +0000397void X86ATTAsmPrinter::printMemReference(const MCInst *MI, unsigned Op) {
Chris Lattnerad48be02009-06-20 00:50:32 +0000398 const MCOperand &Segment = MI->getOperand(Op+4);
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000399 if (Segment.getReg()) {
Chris Lattnerc1243062009-06-20 07:03:18 +0000400 printOperand(MI, Op+4);
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000401 O << ':';
402 }
Chris Lattnerc1243062009-06-20 07:03:18 +0000403 printLeaMemReference(MI, Op);
Chris Lattnerd5fb7902009-06-19 23:59:57 +0000404}