blob: 64d523fb499693636dfac4b5db7e3c7f09b41b9b [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;
Chris Lattnerc1243062009-06-20 07:03:18 +000091 } else if (Op.isMBBLabel()) {
Chris Lattner7680e732009-06-20 19:34:09 +000092 assert(0 && "labels should only be used as pc-relative values");
Chris Lattnerc1243062009-06-20 07:03:18 +000093 // FIXME: Keep in sync with printBasicBlockLabel. printBasicBlockLabel
94 // should eventually call into this code, not the other way around.
95
96 O << TAI->getPrivateGlobalPrefix() << "BB" << Op.getMBBLabelFunction()
97 << '_' << Op.getMBBLabelBlock();
98
99 // FIXME: with verbose asm print llvm bb name, add to operand.
100 return;
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000101 }
102
103 O << "<<UNKNOWN OPERAND KIND>>";
104
105
106#if 0
107 const MachineOperand &MO = MI->getOperand(OpNo);
108 switch (MO.getType()) {
109 case MachineOperand::MO_Register: {
110 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
111 "Virtual registers should not make it this far!");
112 O << '%';
113 unsigned Reg = MO.getReg();
114 if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
115 MVT VT = (strcmp(Modifier+6,"64") == 0) ?
116 MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 :
117 ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8));
118 Reg = getX86SubSuperRegister(Reg, VT);
119 }
120 O << TRI->getAsmName(Reg);
121 return;
122 }
123
124 case MachineOperand::MO_Immediate:
125 if (!Modifier || (strcmp(Modifier, "debug") &&
126 strcmp(Modifier, "mem") &&
127 strcmp(Modifier, "call")))
128 O << '$';
129 O << MO.getImm();
130 return;
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000131 case MachineOperand::MO_JumpTableIndex: {
132 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
133 if (!isMemOp) O << '$';
134 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
135 << MO.getIndex();
136
137 if (TM.getRelocationModel() == Reloc::PIC_) {
138 if (Subtarget->isPICStyleStub())
139 O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
140 << "$pb\"";
141 else if (Subtarget->isPICStyleGOT())
142 O << "@GOTOFF";
143 }
144
145 if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel)
146 O << "(%rip)";
147 return;
148 }
149 case MachineOperand::MO_ConstantPoolIndex: {
150 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
151 if (!isMemOp) O << '$';
152 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
153 << MO.getIndex();
154
155 if (TM.getRelocationModel() == Reloc::PIC_) {
156 if (Subtarget->isPICStyleStub())
157 O << "-\"" << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
158 << "$pb\"";
159 else if (Subtarget->isPICStyleGOT())
160 O << "@GOTOFF";
161 }
162
163 printOffset(MO.getOffset());
164
165 if (isMemOp && Subtarget->isPICStyleRIPRel() && !NotRIPRel)
166 O << "(%rip)";
167 return;
168 }
169 case MachineOperand::MO_GlobalAddress: {
170 bool isCallOp = Modifier && !strcmp(Modifier, "call");
171 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
172 bool needCloseParen = false;
173
174 const GlobalValue *GV = MO.getGlobal();
175 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
176 if (!GVar) {
177 // If GV is an alias then use the aliasee for determining
178 // thread-localness.
179 if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
180 GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false));
181 }
182
183 bool isThreadLocal = GVar && GVar->isThreadLocal();
184
185 std::string Name = Mang->getValueName(GV);
186 decorateName(Name, GV);
187
188 if (!isMemOp && !isCallOp)
189 O << '$';
190 else if (Name[0] == '$') {
191 // The name begins with a dollar-sign. In order to avoid having it look
192 // like an integer immediate to the assembler, enclose it in parens.
193 O << '(';
194 needCloseParen = true;
195 }
196
197 if (shouldPrintStub(TM, Subtarget)) {
198 // Link-once, declaration, or Weakly-linked global variables need
199 // non-lazily-resolved stubs
200 if (GV->isDeclaration() || GV->isWeakForLinker()) {
201 // Dynamically-resolved functions need a stub for the function.
202 if (isCallOp && isa<Function>(GV)) {
203 // Function stubs are no longer needed for Mac OS X 10.5 and up.
204 if (Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9) {
205 O << Name;
206 } else {
207 FnStubs.insert(Name);
208 printSuffixedName(Name, "$stub");
209 }
210 } else if (GV->hasHiddenVisibility()) {
211 if (!GV->isDeclaration() && !GV->hasCommonLinkage())
212 // Definition is not definitely in the current translation unit.
213 O << Name;
214 else {
215 HiddenGVStubs.insert(Name);
216 printSuffixedName(Name, "$non_lazy_ptr");
217 }
218 } else {
219 GVStubs.insert(Name);
220 printSuffixedName(Name, "$non_lazy_ptr");
221 }
222 } else {
223 if (GV->hasDLLImportLinkage())
224 O << "__imp_";
225 O << Name;
226 }
227
228 if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_)
229 O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget);
230 } else {
231 if (GV->hasDLLImportLinkage()) {
232 O << "__imp_";
233 }
234 O << Name;
235
236 if (isCallOp) {
237 if (shouldPrintPLT(TM, Subtarget)) {
238 // Assemble call via PLT for externally visible symbols
239 if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
240 !GV->hasLocalLinkage())
241 O << "@PLT";
242 }
243 if (Subtarget->isTargetCygMing() && GV->isDeclaration())
244 // Save function name for later type emission
245 FnStubs.insert(Name);
246 }
247 }
248
249 if (GV->hasExternalWeakLinkage())
250 ExtWeakSymbols.insert(GV);
251
252 printOffset(MO.getOffset());
253
254 if (isThreadLocal) {
255 TLSModel::Model model = getTLSModel(GVar, TM.getRelocationModel());
256 switch (model) {
257 case TLSModel::GeneralDynamic:
258 O << "@TLSGD";
259 break;
260 case TLSModel::LocalDynamic:
261 // O << "@TLSLD"; // local dynamic not implemented
262 O << "@TLSGD";
263 break;
264 case TLSModel::InitialExec:
265 if (Subtarget->is64Bit()) {
266 assert (!NotRIPRel);
267 O << "@GOTTPOFF(%rip)";
268 } else {
269 O << "@INDNTPOFF";
270 }
271 break;
272 case TLSModel::LocalExec:
273 if (Subtarget->is64Bit())
274 O << "@TPOFF";
275 else
276 O << "@NTPOFF";
277 break;
278 default:
279 assert (0 && "Unknown TLS model");
280 }
281 } else if (isMemOp) {
282 if (shouldPrintGOT(TM, Subtarget)) {
283 if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
284 O << "@GOT";
285 else
286 O << "@GOTOFF";
287 } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel) {
288 if (TM.getRelocationModel() != Reloc::Static) {
289 if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
290 O << "@GOTPCREL";
291
292 if (needCloseParen) {
293 needCloseParen = false;
294 O << ')';
295 }
296 }
297
298 // Use rip when possible to reduce code size, except when
299 // index or base register are also part of the address. e.g.
300 // foo(%rip)(%rcx,%rax,4) is not legal
301 O << "(%rip)";
302 }
303 }
304
305 if (needCloseParen)
306 O << ')';
307
308 return;
309 }
310 case MachineOperand::MO_ExternalSymbol: {
311 bool isCallOp = Modifier && !strcmp(Modifier, "call");
312 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
313 bool needCloseParen = false;
314 std::string Name(TAI->getGlobalPrefix());
315 Name += MO.getSymbolName();
316 // Print function stub suffix unless it's Mac OS X 10.5 and up.
317 if (isCallOp && shouldPrintStub(TM, Subtarget) &&
318 !(Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9)) {
319 FnStubs.insert(Name);
320 printSuffixedName(Name, "$stub");
321 return;
322 }
323 if (!isMemOp && !isCallOp)
324 O << '$';
325 else if (Name[0] == '$') {
326 // The name begins with a dollar-sign. In order to avoid having it look
327 // like an integer immediate to the assembler, enclose it in parens.
328 O << '(';
329 needCloseParen = true;
330 }
331
332 O << Name;
333
334 if (shouldPrintPLT(TM, Subtarget)) {
335 std::string GOTName(TAI->getGlobalPrefix());
336 GOTName+="_GLOBAL_OFFSET_TABLE_";
337 if (Name == GOTName)
338 // HACK! Emit extra offset to PC during printing GOT offset to
339 // compensate for the size of popl instruction. The resulting code
340 // should look like:
341 // call .piclabel
342 // piclabel:
343 // popl %some_register
344 // addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register
345 O << " + [.-"
346 << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']';
347
348 if (isCallOp)
349 O << "@PLT";
350 }
351
352 if (needCloseParen)
353 O << ')';
354
355 if (!isCallOp && Subtarget->isPICStyleRIPRel())
356 O << "(%rip)";
357
358 return;
359 }
360 default:
361 O << "<unknown operand type>"; return;
362 }
363#endif
Chris Lattnerd5fb7902009-06-19 23:59:57 +0000364}
365
Chris Lattnerc1243062009-06-20 07:03:18 +0000366void X86ATTAsmPrinter::printLeaMemReference(const MCInst *MI, unsigned Op) {
Chris Lattnerc1243062009-06-20 07:03:18 +0000367 bool NotRIPRel = false;
368
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000369 const MCOperand &BaseReg = MI->getOperand(Op);
370 const MCOperand &IndexReg = MI->getOperand(Op+2);
371 const MCOperand &DispSpec = MI->getOperand(Op+3);
372
373 NotRIPRel |= IndexReg.getReg() || BaseReg.getReg();
374 if (DispSpec.isImm()) {
375 int64_t DispVal = DispSpec.getImm();
376 if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
377 O << DispVal;
378 } else {
379 abort();
380 //assert(DispSpec.isGlobal() || DispSpec.isCPI() ||
381 // DispSpec.isJTI() || DispSpec.isSymbol());
382 //printOperand(MI, Op+3, "mem", NotRIPRel);
383 }
384
385 if (IndexReg.getReg() || BaseReg.getReg()) {
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000386 // There are cases where we can end up with ESP/RSP in the indexreg slot.
387 // If this happens, swap the base/index register to support assemblers that
388 // don't work when the index is *SP.
389 // FIXME: REMOVE THIS.
Chris Lattnerdc479f62009-06-20 07:59:10 +0000390 assert(IndexReg.getReg() != X86::ESP && IndexReg.getReg() != X86::RSP);
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000391
392 O << '(';
393 if (BaseReg.getReg())
Chris Lattnerdc479f62009-06-20 07:59:10 +0000394 printOperand(MI, Op);
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000395
396 if (IndexReg.getReg()) {
397 O << ',';
Chris Lattnerdc479f62009-06-20 07:59:10 +0000398 printOperand(MI, Op+2);
Chris Lattner7f8217f2009-06-20 08:13:12 +0000399 unsigned ScaleVal = MI->getOperand(Op+1).getImm();
400 if (ScaleVal != 1)
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000401 O << ',' << ScaleVal;
402 }
403 O << ')';
404 }
Chris Lattnerd5fb7902009-06-19 23:59:57 +0000405}
406
Chris Lattnerc1243062009-06-20 07:03:18 +0000407void X86ATTAsmPrinter::printMemReference(const MCInst *MI, unsigned Op) {
Chris Lattnerad48be02009-06-20 00:50:32 +0000408 const MCOperand &Segment = MI->getOperand(Op+4);
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000409 if (Segment.getReg()) {
Chris Lattnerc1243062009-06-20 07:03:18 +0000410 printOperand(MI, Op+4);
Chris Lattnerf38c03af2009-06-20 00:49:26 +0000411 O << ':';
412 }
Chris Lattnerc1243062009-06-20 07:03:18 +0000413 printLeaMemReference(MI, Op);
Chris Lattnerd5fb7902009-06-19 23:59:57 +0000414}