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