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