Remove a bunch more SparcV9 specific stuff
[oota-llvm.git] / lib / Target / X86 / X86IntelAsmPrinter.cpp
1 //===-- X86IntelAsmPrinter.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 Intel format assembly language.
12 // This printer is the output mechanism used by `llc'.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "X86IntelAsmPrinter.h"
17 #include "X86.h"
18 #include "llvm/Constants.h"
19 #include "llvm/Module.h"
20 #include "llvm/Assembly/Writer.h"
21 #include "llvm/Support/Mangler.h"
22 #include "llvm/Target/TargetOptions.h"
23 using namespace llvm;
24
25 X86IntelAsmPrinter::X86IntelAsmPrinter(std::ostream &O, X86TargetMachine &TM)
26     : X86SharedAsmPrinter(O, TM) {
27   CommentString = ";";
28   GlobalPrefix = "_";
29   PrivateGlobalPrefix = "$";
30   AlignDirective = "\talign\t";
31   MLSections = true;
32   ZeroDirective = "\tdb\t";
33   ZeroDirectiveSuffix = " dup(0)";
34   AsciiDirective = "\tdb\t";
35   AscizDirective = 0;
36   Data8bitsDirective = "\t.db\t";
37   Data16bitsDirective = "\t.dw\t";
38   Data32bitsDirective = "\t.dd\t";
39   Data64bitsDirective = "\t.dq\t";
40   HasDotTypeDotSizeDirective = false;
41 }
42
43 /// runOnMachineFunction - This uses the printMachineInstruction()
44 /// method to print assembly for each instruction.
45 ///
46 bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
47   if (forDarwin) {
48     // Let PassManager know we need debug information and relay
49     // the MachineDebugInfo address on to DwarfWriter.
50     DW.SetDebugInfo(&getAnalysis<MachineDebugInfo>());
51   }
52
53   SetupMachineFunction(MF);
54   O << "\n\n";
55
56   // Print out constants referenced by the function
57   EmitConstantPool(MF.getConstantPool());
58
59   // Print out labels for the function.
60   SwitchSection(".code", MF.getFunction());
61   EmitAlignment(4);
62   if (MF.getFunction()->getLinkage() == GlobalValue::ExternalLinkage)
63     O << "\tpublic " << CurrentFnName << "\n";
64   O << CurrentFnName << "\tproc near\n";
65   
66   if (forDarwin) {
67     // Emit pre-function debug information.
68     DW.BeginFunction(&MF);
69   }
70
71   // Print out code for the function.
72   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
73        I != E; ++I) {
74     // Print a label for the basic block if there are any predecessors.
75     if (I->pred_begin() != I->pred_end()) {
76       printBasicBlockLabel(I, true);
77       O << '\n';
78     }
79     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
80          II != E; ++II) {
81       // Print the assembly for the instruction.
82       O << "\t";
83       printMachineInstruction(II);
84     }
85   }
86
87   if (forDarwin) {
88     // Emit post-function debug information.
89     DW.EndFunction();
90   }
91
92   O << CurrentFnName << "\tendp\n";
93
94   // We didn't modify anything.
95   return false;
96 }
97
98 void X86IntelAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) {
99   unsigned char value = MI->getOperand(Op).getImmedValue();
100   assert(value <= 7 && "Invalid ssecc argument!");
101   switch (value) {
102   case 0: O << "eq"; break;
103   case 1: O << "lt"; break;
104   case 2: O << "le"; break;
105   case 3: O << "unord"; break;
106   case 4: O << "neq"; break;
107   case 5: O << "nlt"; break;
108   case 6: O << "nle"; break;
109   case 7: O << "ord"; break;
110   }
111 }
112
113 void X86IntelAsmPrinter::printOp(const MachineOperand &MO, 
114                                  const char *Modifier) {
115   const MRegisterInfo &RI = *TM.getRegisterInfo();
116   switch (MO.getType()) {
117   case MachineOperand::MO_VirtualRegister:
118     if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
119       O << RI.get(MO.getReg()).Name;
120     else
121       O << "reg" << MO.getReg();
122     return;
123
124   case MachineOperand::MO_SignExtendedImmed:
125   case MachineOperand::MO_UnextendedImmed:
126     O << (int)MO.getImmedValue();
127     return;
128   case MachineOperand::MO_MachineBasicBlock:
129     printBasicBlockLabel(MO.getMachineBasicBlock());
130     return;
131   case MachineOperand::MO_ConstantPoolIndex: {
132     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
133     if (!isMemOp) O << "OFFSET ";
134     O << "[" << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_"
135       << MO.getConstantPoolIndex();
136     if (forDarwin && TM.getRelocationModel() == Reloc::PIC)
137       O << "-\"L" << getFunctionNumber() << "$pb\"";
138     int Offset = MO.getOffset();
139     if (Offset > 0)
140       O << " + " << Offset;
141     else if (Offset < 0)
142       O << Offset;
143     O << "]";
144     return;
145   }
146   case MachineOperand::MO_GlobalAddress: {
147     bool isCallOp = Modifier && !strcmp(Modifier, "call");
148     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
149     if (!isMemOp && !isCallOp) O << "OFFSET ";
150     if (forDarwin && TM.getRelocationModel() != Reloc::Static) {
151       GlobalValue *GV = MO.getGlobal();
152       std::string Name = Mang->getValueName(GV);
153       if (!isMemOp && !isCallOp) O << '$';
154       // Link-once, External, or Weakly-linked global variables need
155       // non-lazily-resolved stubs
156       if (GV->isExternal() || GV->hasWeakLinkage() ||
157           GV->hasLinkOnceLinkage()) {
158         // Dynamically-resolved functions need a stub for the function.
159         if (isCallOp && isa<Function>(GV) && cast<Function>(GV)->isExternal()) {
160           FnStubs.insert(Name);
161           O << "L" << Name << "$stub";
162         } else {
163           GVStubs.insert(Name);
164           O << "L" << Name << "$non_lazy_ptr";
165         }
166       } else {
167         O << Mang->getValueName(GV);
168       }
169       if (!isCallOp && TM.getRelocationModel() == Reloc::PIC)
170         O << "-\"L" << getFunctionNumber() << "$pb\"";
171     } else
172       O << Mang->getValueName(MO.getGlobal());
173     int Offset = MO.getOffset();
174     if (Offset > 0)
175       O << " + " << Offset;
176     else if (Offset < 0)
177       O << Offset;
178     return;
179   }
180   case MachineOperand::MO_ExternalSymbol: {
181     bool isCallOp = Modifier && !strcmp(Modifier, "call");
182     if (isCallOp && forDarwin && TM.getRelocationModel() != Reloc::Static) {
183       std::string Name(GlobalPrefix);
184       Name += MO.getSymbolName();
185       FnStubs.insert(Name);
186       O << "L" << Name << "$stub";
187       return;
188     }
189     if (!isCallOp) O << "OFFSET ";
190     O << GlobalPrefix << MO.getSymbolName();
191     return;
192   }
193   default:
194     O << "<unknown operand type>"; return;
195   }
196 }
197
198 void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
199   assert(isMem(MI, Op) && "Invalid memory reference!");
200
201   const MachineOperand &BaseReg  = MI->getOperand(Op);
202   int ScaleVal                   = MI->getOperand(Op+1).getImmedValue();
203   const MachineOperand &IndexReg = MI->getOperand(Op+2);
204   const MachineOperand &DispSpec = MI->getOperand(Op+3);
205
206   if (BaseReg.isFrameIndex()) {
207     O << "[frame slot #" << BaseReg.getFrameIndex();
208     if (DispSpec.getImmedValue())
209       O << " + " << DispSpec.getImmedValue();
210     O << "]";
211     return;
212   }
213
214   O << "[";
215   bool NeedPlus = false;
216   if (BaseReg.getReg()) {
217     printOp(BaseReg, "mem");
218     NeedPlus = true;
219   }
220
221   if (IndexReg.getReg()) {
222     if (NeedPlus) O << " + ";
223     if (ScaleVal != 1)
224       O << ScaleVal << "*";
225     printOp(IndexReg);
226     NeedPlus = true;
227   }
228
229   if (DispSpec.isGlobalAddress() || DispSpec.isConstantPoolIndex()) {
230     if (NeedPlus)
231       O << " + ";
232     printOp(DispSpec, "mem");
233   } else {
234     int DispVal = DispSpec.getImmedValue();
235     if (DispVal || (!BaseReg.getReg() && !IndexReg.getReg())) {
236       if (NeedPlus)
237         if (DispVal > 0)
238           O << " + ";
239         else {
240           O << " - ";
241           DispVal = -DispVal;
242         }
243       O << DispVal;
244     }
245   }
246   O << "]";
247 }
248
249 void X86IntelAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) {
250   O << "\"L" << getFunctionNumber() << "$pb\"\n";
251   O << "\"L" << getFunctionNumber() << "$pb\":";
252 }
253
254 bool X86IntelAsmPrinter::printAsmMRegister(const MachineOperand &MO,
255                                            const char Mode) {
256   const MRegisterInfo &RI = *TM.getRegisterInfo();
257   unsigned Reg = MO.getReg();
258   const char *Name = RI.get(Reg).Name;
259   switch (Mode) {
260   default: return true;  // Unknown mode.
261   case 'b': // Print QImode register
262     switch (Reg) {
263     default: return true;
264     case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
265       Name = "AL";
266       break;
267     case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
268       Name = "DL";
269       break;
270     case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
271       Name = "CL";
272       break;
273     case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
274       Name = "BL";
275       break;
276     case X86::ESI:
277       Name = "SIL";
278       break;
279     case X86::EDI:
280       Name = "DIL";
281       break;
282     case X86::EBP:
283       Name = "BPL";
284       break;
285     case X86::ESP:
286       Name = "SPL";
287       break;
288     }
289     break;
290   case 'h': // Print QImode high register
291     switch (Reg) {
292     default: return true;
293     case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
294       Name = "AL";
295       break;
296     case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
297       Name = "DL";
298       break;
299     case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
300       Name = "CL";
301       break;
302     case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
303       Name = "BL";
304       break;
305     }
306     break;
307   case 'w': // Print HImode register
308     switch (Reg) {
309     default: return true;
310     case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
311       Name = "AX";
312       break;
313     case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
314       Name = "DX";
315       break;
316     case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
317       Name = "CX";
318       break;
319     case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
320       Name = "BX";
321       break;
322     case X86::ESI:
323       Name = "SI";
324       break;
325     case X86::EDI:
326       Name = "DI";
327       break;
328     case X86::EBP:
329       Name = "BP";
330       break;
331     case X86::ESP:
332       Name = "SP";
333       break;
334     }
335     break;
336   case 'k': // Print SImode register
337     switch (Reg) {
338     default: return true;
339     case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
340       Name = "EAX";
341       break;
342     case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
343       Name = "EDX";
344       break;
345     case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
346       Name = "ECX";
347       break;
348     case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
349       Name = "EBX";
350       break;
351     case X86::ESI:
352       Name = "ESI";
353       break;
354     case X86::EDI:
355       Name = "EDI";
356       break;
357     case X86::EBP:
358       Name = "EBP";
359       break;
360     case X86::ESP:
361       Name = "ESP";
362       break;
363     }
364     break;
365   }
366
367   O << Name;
368   return false;
369 }
370
371 /// PrintAsmOperand - Print out an operand for an inline asm expression.
372 ///
373 bool X86IntelAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
374                                          unsigned AsmVariant, 
375                                          const char *ExtraCode) {
376   // Does this asm operand have a single letter operand modifier?
377   if (ExtraCode && ExtraCode[0]) {
378     if (ExtraCode[1] != 0) return true; // Unknown modifier.
379     
380     switch (ExtraCode[0]) {
381     default: return true;  // Unknown modifier.
382     case 'b': // Print QImode register
383     case 'h': // Print QImode high register
384     case 'w': // Print HImode register
385     case 'k': // Print SImode register
386       return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]);
387     }
388   }
389   
390   printOperand(MI, OpNo);
391   return false;
392 }
393
394 bool X86IntelAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
395                                                unsigned OpNo,
396                                                unsigned AsmVariant, 
397                                                const char *ExtraCode) {
398   if (ExtraCode && ExtraCode[0])
399     return true; // Unknown modifier.
400   printMemReference(MI, OpNo);
401   return false;
402 }
403
404 /// printMachineInstruction -- Print out a single X86 LLVM instruction
405 /// MI in Intel syntax to the current output stream.
406 ///
407 void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
408   ++EmittedInsts;
409
410   // Call the autogenerated instruction printer routines.
411   printInstruction(MI);
412 }
413
414 bool X86IntelAsmPrinter::doInitialization(Module &M) {
415   X86SharedAsmPrinter::doInitialization(M);
416   Mang->markCharUnacceptable('.');
417   PrivateGlobalPrefix = "$";  // need this here too :(
418   O << "\t.686\n\t.model flat\n\n";
419
420   // Emit declarations for external functions.
421   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
422     if (I->isExternal())
423       O << "\textern " << Mang->getValueName(I) << ":near\n";
424
425   // Emit declarations for external globals.
426   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
427        I != E; ++I) {
428     if (I->isExternal())
429       O << "\textern " << Mang->getValueName(I) << ":byte\n";
430   }
431
432   return false;
433 }
434
435 bool X86IntelAsmPrinter::doFinalization(Module &M) {
436   X86SharedAsmPrinter::doFinalization(M);
437   SwitchSection("", 0);
438   O << "\tend\n";
439   return false;
440 }
441
442 void X86IntelAsmPrinter::EmitString(const ConstantArray *CVA) const {
443   unsigned NumElts = CVA->getNumOperands();
444   if (NumElts) {
445     // ML does not have escape sequences except '' for '.  It also has a maximum
446     // string length of 255.
447     unsigned len = 0;
448     bool inString = false;
449     for (unsigned i = 0; i < NumElts; i++) {
450       int n = cast<ConstantInt>(CVA->getOperand(i))->getRawValue() & 255;
451       if (len == 0)
452         O << "\tdb ";
453
454       if (n >= 32 && n <= 127) {
455         if (!inString) {
456           if (len > 0) {
457             O << ",'";
458             len += 2;
459           } else {
460             O << "'";
461             len++;
462           }
463           inString = true;
464         }
465         if (n == '\'') {
466           O << "'";
467           len++;
468         }
469         O << char(n);
470       } else {
471         if (inString) {
472           O << "'";
473           len++;
474           inString = false;
475         }
476         if (len > 0) {
477           O << ",";
478           len++;
479         }
480         O << n;
481         len += 1 + (n > 9) + (n > 99);
482       }
483
484       if (len > 60) {
485         if (inString) {
486           O << "'";
487           inString = false;
488         }
489         O << "\n";
490         len = 0;
491       }
492     }
493
494     if (len > 0) {
495       if (inString)
496         O << "'";
497       O << "\n";
498     }
499   }
500 }
501
502 // Include the auto-generated portion of the assembly writer.
503 #include "X86GenAsmWriter1.inc"