Remove a couple of bogus casts.
[oota-llvm.git] / lib / Target / X86 / X86ATTAsmPrinter.cpp
1 //===-- X86ATTAsmPrinter.cpp - Convert X86 LLVM code to Intel assembly ----===//
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
16 #include "X86ATTAsmPrinter.h"
17 #include "X86.h"
18 #include "X86TargetMachine.h"
19 #include "llvm/Module.h"
20 #include "llvm/Support/Mangler.h"
21 #include "llvm/Target/TargetOptions.h"
22 #include <iostream>
23 using namespace llvm;
24
25 /// runOnMachineFunction - This uses the printMachineInstruction()
26 /// method to print assembly for each instruction.
27 ///
28 bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
29   // Let PassManager know we need debug information and relay
30   // the MachineDebugInfo address on to DwarfWriter.
31   DW.SetDebugInfo(&getAnalysis<MachineDebugInfo>());
32
33   SetupMachineFunction(MF);
34   O << "\n\n";
35
36   // Print out constants referenced by the function
37   EmitConstantPool(MF.getConstantPool());
38
39   // Print out jump tables referenced by the function
40   EmitJumpTableInfo(MF.getJumpTableInfo());
41   
42   // Print out labels for the function.
43   const Function *F = MF.getFunction();
44   switch (F->getLinkage()) {
45   default: assert(0 && "Unknown linkage type!");
46   case Function::InternalLinkage:  // Symbols default to internal.
47     SwitchToTextSection(DefaultTextSection, F);
48     EmitAlignment(4, F);     // FIXME: This should be parameterized somewhere.
49     break;
50   case Function::ExternalLinkage:
51     SwitchToTextSection(DefaultTextSection, F);
52     EmitAlignment(4, F);     // FIXME: This should be parameterized somewhere.
53     O << "\t.globl\t" << CurrentFnName << "\n";
54     break;
55   case Function::WeakLinkage:
56   case Function::LinkOnceLinkage:
57     if (Subtarget->TargetType == X86Subtarget::isDarwin) {
58       SwitchToTextSection(
59                 ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F);
60       O << "\t.globl\t" << CurrentFnName << "\n";
61       O << "\t.weak_definition\t" << CurrentFnName << "\n";
62     } else if (Subtarget->TargetType == X86Subtarget::isCygwin) {
63       EmitAlignment(4, F);     // FIXME: This should be parameterized somewhere.
64       O << "\t.section\t.llvm.linkonce.t." << CurrentFnName
65         << ",\"ax\"\n";
66       SwitchToTextSection("", F);
67       O << "\t.weak " << CurrentFnName << "\n";
68     } else {
69       EmitAlignment(4, F);     // FIXME: This should be parameterized somewhere.
70       O << "\t.section\t.llvm.linkonce.t." << CurrentFnName
71         << ",\"ax\",@progbits\n";
72       SwitchToTextSection("", F);
73       O << "\t.weak " << CurrentFnName << "\n";
74     }
75     break;
76   }
77   O << CurrentFnName << ":\n";
78
79   if (Subtarget->TargetType == X86Subtarget::isDarwin) {
80     // Emit pre-function debug information.
81     DW.BeginFunction(&MF);
82   }
83
84   // Print out code for the function.
85   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
86        I != E; ++I) {
87     // Print a label for the basic block.
88     if (I->pred_begin() != I->pred_end()) {
89       printBasicBlockLabel(I, true);
90       O << '\n';
91     }
92     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
93          II != E; ++II) {
94       // Print the assembly for the instruction.
95       O << "\t";
96       printMachineInstruction(II);
97     }
98   }
99   if (HasDotTypeDotSizeDirective)
100     O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n";
101
102   if (Subtarget->TargetType == X86Subtarget::isDarwin) {
103     // Emit post-function debug information.
104     DW.EndFunction();
105   }
106
107   // We didn't modify anything.
108   return false;
109 }
110
111 void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
112                                     const char *Modifier) {
113   const MachineOperand &MO = MI->getOperand(OpNo);
114   const MRegisterInfo &RI = *TM.getRegisterInfo();
115   switch (MO.getType()) {
116   case MachineOperand::MO_Register: {
117     assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) &&
118            "Virtual registers should not make it this far!");
119     O << '%';
120     unsigned Reg = MO.getReg();
121     if (Modifier && strncmp(Modifier, "trunc", strlen("trunc")) == 0) {
122       MVT::ValueType VT = (strcmp(Modifier,"trunc16") == 0)
123         ? MVT::i16 : MVT::i8;
124       Reg = getX86SubSuperRegister(Reg, VT);
125     }
126     for (const char *Name = RI.get(Reg).Name; *Name; ++Name)
127       O << (char)tolower(*Name);
128     return;
129   }
130
131   case MachineOperand::MO_Immediate:
132     if (!Modifier || strcmp(Modifier, "debug") != 0)
133       O << '$';
134     O << MO.getImmedValue();
135     return;
136   case MachineOperand::MO_MachineBasicBlock:
137     printBasicBlockLabel(MO.getMachineBasicBlock());
138     return;
139   case MachineOperand::MO_JumpTableIndex: {
140     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
141     if (!isMemOp) O << '$';
142     O << PrivateGlobalPrefix << "JTI" << getFunctionNumber() << "_"
143       << MO.getJumpTableIndex();
144     // FIXME: PIC relocation model
145     return;
146   }
147   case MachineOperand::MO_ConstantPoolIndex: {
148     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
149     if (!isMemOp) O << '$';
150     O << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_"
151       << MO.getConstantPoolIndex();
152     if (Subtarget->TargetType == X86Subtarget::isDarwin && 
153         TM.getRelocationModel() == Reloc::PIC)
154       O << "-\"L" << getFunctionNumber() << "$pb\"";
155     int Offset = MO.getOffset();
156     if (Offset > 0)
157       O << "+" << Offset;
158     else if (Offset < 0)
159       O << Offset;
160     return;
161   }
162   case MachineOperand::MO_GlobalAddress: {
163     bool isCallOp = Modifier && !strcmp(Modifier, "call");
164     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
165     if (!isMemOp && !isCallOp) O << '$';
166     // Darwin block shameless ripped from PPCAsmPrinter.cpp
167     if (Subtarget->TargetType == X86Subtarget::isDarwin && 
168         TM.getRelocationModel() != Reloc::Static) {
169       GlobalValue *GV = MO.getGlobal();
170       std::string Name = Mang->getValueName(GV);
171       // Link-once, External, or Weakly-linked global variables need
172       // non-lazily-resolved stubs
173       if (GV->isExternal() || GV->hasWeakLinkage() ||
174           GV->hasLinkOnceLinkage()) {
175         // Dynamically-resolved functions need a stub for the function.
176         if (isCallOp && isa<Function>(GV) && cast<Function>(GV)->isExternal()) {
177           FnStubs.insert(Name);
178           O << "L" << Name << "$stub";
179         } else {
180           GVStubs.insert(Name);
181           O << "L" << Name << "$non_lazy_ptr";
182         }
183       } else {
184         O << Mang->getValueName(GV);
185       } 
186       if (!isCallOp && TM.getRelocationModel() == Reloc::PIC)
187         O << "-\"L" << getFunctionNumber() << "$pb\"";
188    } else
189       O << Mang->getValueName(MO.getGlobal());
190     int Offset = MO.getOffset();
191     if (Offset > 0)
192       O << "+" << Offset;
193     else if (Offset < 0)
194       O << Offset;
195     return;
196   }
197   case MachineOperand::MO_ExternalSymbol: {
198     bool isCallOp = Modifier && !strcmp(Modifier, "call");
199     if (isCallOp && 
200         Subtarget->TargetType == X86Subtarget::isDarwin && 
201         TM.getRelocationModel() != Reloc::Static) {
202       std::string Name(GlobalPrefix);
203       Name += MO.getSymbolName();
204       FnStubs.insert(Name);
205       O << "L" << Name << "$stub";
206       return;
207     }
208     if (!isCallOp) O << '$';
209     O << GlobalPrefix << MO.getSymbolName();
210     return;
211   }
212   default:
213     O << "<unknown operand type>"; return;
214   }
215 }
216
217 void X86ATTAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) {
218   unsigned char value = MI->getOperand(Op).getImmedValue();
219   assert(value <= 7 && "Invalid ssecc argument!");
220   switch (value) {
221   case 0: O << "eq"; break;
222   case 1: O << "lt"; break;
223   case 2: O << "le"; break;
224   case 3: O << "unord"; break;
225   case 4: O << "neq"; break;
226   case 5: O << "nlt"; break;
227   case 6: O << "nle"; break;
228   case 7: O << "ord"; break;
229   }
230 }
231
232 void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
233   assert(isMem(MI, Op) && "Invalid memory reference!");
234
235   const MachineOperand &BaseReg  = MI->getOperand(Op);
236   int ScaleVal                   = MI->getOperand(Op+1).getImmedValue();
237   const MachineOperand &IndexReg = MI->getOperand(Op+2);
238   const MachineOperand &DispSpec = MI->getOperand(Op+3);
239
240   if (BaseReg.isFrameIndex()) {
241     O << "[frame slot #" << BaseReg.getFrameIndex();
242     if (DispSpec.getImmedValue())
243       O << " + " << DispSpec.getImmedValue();
244     O << "]";
245     return;
246   }
247
248   if (DispSpec.isGlobalAddress() || DispSpec.isConstantPoolIndex()) {
249     printOperand(MI, Op+3, "mem");
250   } else {
251     int DispVal = DispSpec.getImmedValue();
252     if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
253       O << DispVal;
254   }
255
256   if (IndexReg.getReg() || BaseReg.getReg()) {
257     O << "(";
258     if (BaseReg.getReg())
259       printOperand(MI, Op);
260
261     if (IndexReg.getReg()) {
262       O << ",";
263       printOperand(MI, Op+2);
264       if (ScaleVal != 1)
265         O << "," << ScaleVal;
266     }
267
268     O << ")";
269   }
270 }
271
272 void X86ATTAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) {
273   O << "\"L" << getFunctionNumber() << "$pb\"\n";
274   O << "\"L" << getFunctionNumber() << "$pb\":";
275 }
276
277
278 bool X86ATTAsmPrinter::printAsmMRegister(const MachineOperand &MO,
279                                          const char Mode) {
280   const MRegisterInfo &RI = *TM.getRegisterInfo();
281   unsigned Reg = MO.getReg();
282   switch (Mode) {
283   default: return true;  // Unknown mode.
284   case 'b': // Print QImode register
285     Reg = getX86SubSuperRegister(Reg, MVT::i8);
286     break;
287   case 'h': // Print QImode high register
288     Reg = getX86SubSuperRegister(Reg, MVT::i8, true);
289     break;
290   case 'w': // Print HImode register
291     Reg = getX86SubSuperRegister(Reg, MVT::i16);
292     break;
293   case 'k': // Print SImode register
294     Reg = getX86SubSuperRegister(Reg, MVT::i32);
295     break;
296   }
297
298   O << '%';
299   for (const char *Name = RI.get(Reg).Name; *Name; ++Name)
300     O << (char)tolower(*Name);
301   return false;
302 }
303
304 /// PrintAsmOperand - Print out an operand for an inline asm expression.
305 ///
306 bool X86ATTAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
307                                        unsigned AsmVariant, 
308                                        const char *ExtraCode) {
309   // Does this asm operand have a single letter operand modifier?
310   if (ExtraCode && ExtraCode[0]) {
311     if (ExtraCode[1] != 0) return true; // Unknown modifier.
312     
313     switch (ExtraCode[0]) {
314     default: return true;  // Unknown modifier.
315     case 'b': // Print QImode register
316     case 'h': // Print QImode high register
317     case 'w': // Print HImode register
318     case 'k': // Print SImode register
319       return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]);
320     }
321   }
322   
323   printOperand(MI, OpNo);
324   return false;
325 }
326
327 bool X86ATTAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
328                                              unsigned OpNo,
329                                              unsigned AsmVariant, 
330                                              const char *ExtraCode) {
331   if (ExtraCode && ExtraCode[0])
332     return true; // Unknown modifier.
333   printMemReference(MI, OpNo);
334   return false;
335 }
336
337 /// printMachineInstruction -- Print out a single X86 LLVM instruction
338 /// MI in Intel syntax to the current output stream.
339 ///
340 void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
341   ++EmittedInsts;
342   // This works around some Darwin assembler bugs.
343   if (Subtarget->TargetType == X86Subtarget::isDarwin) {
344     switch (MI->getOpcode()) {
345     case X86::REP_MOVSB:
346       O << "rep/movsb (%esi),(%edi)\n";
347       return;
348     case X86::REP_MOVSD:
349       O << "rep/movsl (%esi),(%edi)\n";
350       return;
351     case X86::REP_MOVSW:
352       O << "rep/movsw (%esi),(%edi)\n";
353       return;
354     case X86::REP_STOSB:
355       O << "rep/stosb\n";
356       return;
357     case X86::REP_STOSD:
358       O << "rep/stosl\n";
359       return;
360     case X86::REP_STOSW:
361       O << "rep/stosw\n";
362       return;
363     default:
364       break;
365     }
366   }
367
368   // See if a truncate instruction can be turned into a nop.
369   switch (MI->getOpcode()) {
370   default: break;
371   case X86::TRUNC_GR32_GR16:
372   case X86::TRUNC_GR32_GR8:
373   case X86::TRUNC_GR16_GR8: {
374     const MachineOperand &MO0 = MI->getOperand(0);
375     const MachineOperand &MO1 = MI->getOperand(1);
376     unsigned Reg0 = MO0.getReg();
377     unsigned Reg1 = MO1.getReg();
378     if (MI->getOpcode() == X86::TRUNC_GR32_GR16)
379       Reg1 = getX86SubSuperRegister(Reg1, MVT::i16);
380     else
381       Reg1 = getX86SubSuperRegister(Reg1, MVT::i8);
382     O << CommentString << " TRUNCATE ";
383     if (Reg0 != Reg1)
384       O << "\n\t";
385     break;
386   }
387   }
388
389   // Call the autogenerated instruction printer routines.
390   printInstruction(MI);
391 }
392
393 // Include the auto-generated portion of the assembly writer.
394 #include "X86GenAsmWriter.inc"
395