blob: 7be50e7fa8cad1abbfc4ca8aa19f1f0324ec1dd6 [file] [log] [blame]
Chris Lattnerb36cbd02005-07-01 22:44:09 +00001//===-- 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"
Jeff Cohenc884db42006-05-02 01:16:28 +000018#include "llvm/Constants.h"
Chris Lattnerb36cbd02005-07-01 22:44:09 +000019#include "llvm/Module.h"
20#include "llvm/Assembly/Writer.h"
21#include "llvm/Support/Mangler.h"
Evan Cheng7ccced62006-02-18 00:15:05 +000022#include "llvm/Target/TargetOptions.h"
Chris Lattnerb36cbd02005-07-01 22:44:09 +000023using namespace llvm;
Chris Lattnerb36cbd02005-07-01 22:44:09 +000024
25/// runOnMachineFunction - This uses the printMachineInstruction()
26/// method to print assembly for each instruction.
27///
28bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
Chris Lattner8b8b9512005-11-21 07:51:23 +000029 SetupMachineFunction(MF);
Chris Lattnerb36cbd02005-07-01 22:44:09 +000030 O << "\n\n";
31
32 // Print out constants referenced by the function
Chris Lattnerd939f6c2005-11-21 08:32:23 +000033 EmitConstantPool(MF.getConstantPool());
Chris Lattnerb36cbd02005-07-01 22:44:09 +000034
35 // Print out labels for the function.
Chris Lattnerdad9c5a2006-05-09 05:12:53 +000036 SwitchToTextSection("_text", MF.getFunction());
Chris Lattner8b8b9512005-11-21 07:51:23 +000037 EmitAlignment(4);
Jeff Cohenc884db42006-05-02 01:16:28 +000038 if (MF.getFunction()->getLinkage() == GlobalValue::ExternalLinkage)
39 O << "\tpublic " << CurrentFnName << "\n";
40 O << CurrentFnName << "\tproc near\n";
Jim Laskey6b92b8e2006-04-07 20:44:42 +000041
Chris Lattnerb36cbd02005-07-01 22:44:09 +000042 // Print out code for the function.
43 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
44 I != E; ++I) {
45 // Print a label for the basic block if there are any predecessors.
Nate Begemancdf38c42006-05-02 05:37:32 +000046 if (I->pred_begin() != I->pred_end()) {
47 printBasicBlockLabel(I, true);
48 O << '\n';
49 }
Chris Lattnerb36cbd02005-07-01 22:44:09 +000050 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
51 II != E; ++II) {
52 // Print the assembly for the instruction.
53 O << "\t";
54 printMachineInstruction(II);
55 }
56 }
57
Jeff Cohenc884db42006-05-02 01:16:28 +000058 O << CurrentFnName << "\tendp\n";
59
Chris Lattnerb36cbd02005-07-01 22:44:09 +000060 // We didn't modify anything.
61 return false;
62}
63
Nate Begeman391c5d22005-11-30 18:54:35 +000064void X86IntelAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) {
Nate Begeman6c7cb292005-07-14 22:52:25 +000065 unsigned char value = MI->getOperand(Op).getImmedValue();
66 assert(value <= 7 && "Invalid ssecc argument!");
67 switch (value) {
68 case 0: O << "eq"; break;
69 case 1: O << "lt"; break;
70 case 2: O << "le"; break;
71 case 3: O << "unord"; break;
72 case 4: O << "neq"; break;
73 case 5: O << "nlt"; break;
74 case 6: O << "nle"; break;
75 case 7: O << "ord"; break;
76 }
77}
78
Chris Lattnera3b8c572006-02-06 23:41:19 +000079void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
80 const char *Modifier) {
Chris Lattnerb36cbd02005-07-01 22:44:09 +000081 const MRegisterInfo &RI = *TM.getRegisterInfo();
82 switch (MO.getType()) {
Chris Lattner2d90ac72006-05-04 18:05:43 +000083 case MachineOperand::MO_Register:
Evan Cheng8f7f7122006-05-05 05:40:20 +000084 if (MRegisterInfo::isPhysicalRegister(MO.getReg())) {
85 unsigned Reg = MO.getReg();
Evan Chengcbe70e12006-05-31 22:34:26 +000086 if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
87 MVT::ValueType VT = (strcmp(Modifier,"subreg16") == 0)
Evan Cheng403be7e2006-05-08 08:01:26 +000088 ? MVT::i16 : MVT::i8;
Evan Cheng8f7f7122006-05-05 05:40:20 +000089 Reg = getX86SubSuperRegister(Reg, VT);
90 }
91 O << RI.get(Reg).Name;
92 } else
Chris Lattner99f26322006-05-01 05:53:50 +000093 O << "reg" << MO.getReg();
Chris Lattnerb36cbd02005-07-01 22:44:09 +000094 return;
95
Chris Lattner63b3d712006-05-04 17:21:20 +000096 case MachineOperand::MO_Immediate:
Evan Cheng138a24e2006-05-26 08:04:31 +000097 O << MO.getImmedValue();
Chris Lattnerb36cbd02005-07-01 22:44:09 +000098 return;
Nate Begeman37efe672006-04-22 18:53:45 +000099 case MachineOperand::MO_MachineBasicBlock:
100 printBasicBlockLabel(MO.getMachineBasicBlock());
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000101 return;
Evan Chenga09bd812006-02-26 08:28:12 +0000102 case MachineOperand::MO_ConstantPoolIndex: {
103 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
104 if (!isMemOp) O << "OFFSET ";
Jim Laskey563321a2006-09-06 18:34:40 +0000105 O << "[" << TAI->getPrivateGlobalPrefix() << "CPI"
106 << getFunctionNumber() << "_" << MO.getConstantPoolIndex();
Evan Chenga09bd812006-02-26 08:28:12 +0000107 int Offset = MO.getOffset();
108 if (Offset > 0)
109 O << " + " << Offset;
110 else if (Offset < 0)
111 O << Offset;
112 O << "]";
113 return;
114 }
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000115 case MachineOperand::MO_GlobalAddress: {
Evan Cheng7ccced62006-02-18 00:15:05 +0000116 bool isCallOp = Modifier && !strcmp(Modifier, "call");
117 bool isMemOp = Modifier && !strcmp(Modifier, "mem");
118 if (!isMemOp && !isCallOp) O << "OFFSET ";
Jeff Cohend43b18d2006-05-06 21:27:14 +0000119 O << Mang->getValueName(MO.getGlobal());
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000120 int Offset = MO.getOffset();
121 if (Offset > 0)
122 O << " + " << Offset;
123 else if (Offset < 0)
Evan Cheng345c3f32005-11-30 01:59:00 +0000124 O << Offset;
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000125 return;
126 }
Evan Cheng7ccced62006-02-18 00:15:05 +0000127 case MachineOperand::MO_ExternalSymbol: {
128 bool isCallOp = Modifier && !strcmp(Modifier, "call");
Evan Cheng4c1aa862006-02-22 20:19:42 +0000129 if (!isCallOp) O << "OFFSET ";
Jim Laskey563321a2006-09-06 18:34:40 +0000130 O << TAI->getGlobalPrefix() << MO.getSymbolName();
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000131 return;
Evan Cheng7ccced62006-02-18 00:15:05 +0000132 }
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000133 default:
134 O << "<unknown operand type>"; return;
135 }
136}
137
138void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
139 assert(isMem(MI, Op) && "Invalid memory reference!");
140
141 const MachineOperand &BaseReg = MI->getOperand(Op);
142 int ScaleVal = MI->getOperand(Op+1).getImmedValue();
143 const MachineOperand &IndexReg = MI->getOperand(Op+2);
144 const MachineOperand &DispSpec = MI->getOperand(Op+3);
145
146 if (BaseReg.isFrameIndex()) {
147 O << "[frame slot #" << BaseReg.getFrameIndex();
148 if (DispSpec.getImmedValue())
149 O << " + " << DispSpec.getImmedValue();
150 O << "]";
151 return;
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000152 }
153
154 O << "[";
155 bool NeedPlus = false;
156 if (BaseReg.getReg()) {
Evan Cheng2338c5c2006-02-07 08:38:37 +0000157 printOp(BaseReg, "mem");
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000158 NeedPlus = true;
159 }
160
161 if (IndexReg.getReg()) {
162 if (NeedPlus) O << " + ";
163 if (ScaleVal != 1)
164 O << ScaleVal << "*";
165 printOp(IndexReg);
166 NeedPlus = true;
167 }
168
Evan Chenga09bd812006-02-26 08:28:12 +0000169 if (DispSpec.isGlobalAddress() || DispSpec.isConstantPoolIndex()) {
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000170 if (NeedPlus)
171 O << " + ";
Evan Cheng2338c5c2006-02-07 08:38:37 +0000172 printOp(DispSpec, "mem");
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000173 } else {
174 int DispVal = DispSpec.getImmedValue();
175 if (DispVal || (!BaseReg.getReg() && !IndexReg.getReg())) {
176 if (NeedPlus)
177 if (DispVal > 0)
178 O << " + ";
179 else {
180 O << " - ";
181 DispVal = -DispVal;
182 }
183 O << DispVal;
184 }
185 }
186 O << "]";
187}
188
Evan Cheng7ccced62006-02-18 00:15:05 +0000189void X86IntelAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) {
190 O << "\"L" << getFunctionNumber() << "$pb\"\n";
191 O << "\"L" << getFunctionNumber() << "$pb\":";
192}
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000193
Evan Cheng55c25f22006-04-28 23:19:39 +0000194bool X86IntelAsmPrinter::printAsmMRegister(const MachineOperand &MO,
Evan Cheng62f27002006-04-28 23:11:40 +0000195 const char Mode) {
196 const MRegisterInfo &RI = *TM.getRegisterInfo();
197 unsigned Reg = MO.getReg();
Evan Cheng62f27002006-04-28 23:11:40 +0000198 switch (Mode) {
199 default: return true; // Unknown mode.
200 case 'b': // Print QImode register
Evan Cheng8f7f7122006-05-05 05:40:20 +0000201 Reg = getX86SubSuperRegister(Reg, MVT::i8);
Evan Cheng62f27002006-04-28 23:11:40 +0000202 break;
203 case 'h': // Print QImode high register
Evan Cheng8f7f7122006-05-05 05:40:20 +0000204 Reg = getX86SubSuperRegister(Reg, MVT::i8, true);
Evan Cheng62f27002006-04-28 23:11:40 +0000205 break;
206 case 'w': // Print HImode register
Evan Cheng8f7f7122006-05-05 05:40:20 +0000207 Reg = getX86SubSuperRegister(Reg, MVT::i16);
Evan Cheng62f27002006-04-28 23:11:40 +0000208 break;
209 case 'k': // Print SImode register
Evan Cheng8f7f7122006-05-05 05:40:20 +0000210 Reg = getX86SubSuperRegister(Reg, MVT::i32);
Evan Cheng62f27002006-04-28 23:11:40 +0000211 break;
212 }
213
Evan Cheng8f7f7122006-05-05 05:40:20 +0000214 O << '%' << RI.get(Reg).Name;
Evan Cheng62f27002006-04-28 23:11:40 +0000215 return false;
216}
217
Evan Cheng3d48a902006-04-28 21:19:05 +0000218/// PrintAsmOperand - Print out an operand for an inline asm expression.
219///
220bool X86IntelAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
221 unsigned AsmVariant,
222 const char *ExtraCode) {
223 // Does this asm operand have a single letter operand modifier?
224 if (ExtraCode && ExtraCode[0]) {
225 if (ExtraCode[1] != 0) return true; // Unknown modifier.
226
227 switch (ExtraCode[0]) {
228 default: return true; // Unknown modifier.
Evan Cheng62f27002006-04-28 23:11:40 +0000229 case 'b': // Print QImode register
230 case 'h': // Print QImode high register
231 case 'w': // Print HImode register
232 case 'k': // Print SImode register
Evan Cheng55c25f22006-04-28 23:19:39 +0000233 return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]);
Evan Cheng3d48a902006-04-28 21:19:05 +0000234 }
235 }
236
237 printOperand(MI, OpNo);
238 return false;
239}
240
241bool X86IntelAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
242 unsigned OpNo,
243 unsigned AsmVariant,
244 const char *ExtraCode) {
245 if (ExtraCode && ExtraCode[0])
246 return true; // Unknown modifier.
247 printMemReference(MI, OpNo);
248 return false;
249}
250
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000251/// printMachineInstruction -- Print out a single X86 LLVM instruction
252/// MI in Intel syntax to the current output stream.
253///
254void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
255 ++EmittedInsts;
256
Evan Cheng8f7f7122006-05-05 05:40:20 +0000257 // See if a truncate instruction can be turned into a nop.
258 switch (MI->getOpcode()) {
259 default: break;
Evan Cheng069287d2006-05-16 07:21:53 +0000260 case X86::TRUNC_GR32_GR16:
261 case X86::TRUNC_GR32_GR8:
262 case X86::TRUNC_GR16_GR8: {
Evan Cheng8f7f7122006-05-05 05:40:20 +0000263 const MachineOperand &MO0 = MI->getOperand(0);
264 const MachineOperand &MO1 = MI->getOperand(1);
265 unsigned Reg0 = MO0.getReg();
266 unsigned Reg1 = MO1.getReg();
Evan Cheng069287d2006-05-16 07:21:53 +0000267 if (MI->getOpcode() == X86::TRUNC_GR32_GR16)
Evan Cheng403be7e2006-05-08 08:01:26 +0000268 Reg1 = getX86SubSuperRegister(Reg1, MVT::i16);
Evan Cheng8f7f7122006-05-05 05:40:20 +0000269 else
Evan Cheng403be7e2006-05-08 08:01:26 +0000270 Reg1 = getX86SubSuperRegister(Reg1, MVT::i8);
Jim Laskey563321a2006-09-06 18:34:40 +0000271 O << TAI->getCommentString() << " TRUNCATE ";
Evan Cheng403be7e2006-05-08 08:01:26 +0000272 if (Reg0 != Reg1)
273 O << "\n\t";
Evan Cheng8f7f7122006-05-05 05:40:20 +0000274 break;
275 }
276 }
277
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000278 // Call the autogenerated instruction printer routines.
279 printInstruction(MI);
280}
281
282bool X86IntelAsmPrinter::doInitialization(Module &M) {
Jeff Cohend43b18d2006-05-06 21:27:14 +0000283 X86SharedAsmPrinter::doInitialization(M);
Chris Lattnerdad9c5a2006-05-09 05:12:53 +0000284
Jim Laskey563321a2006-09-06 18:34:40 +0000285 Mang->markCharUnacceptable('.');
Jeff Cohen10efcfa2006-05-04 16:20:22 +0000286
Jeff Cohen4f1ea1e2006-05-02 03:11:50 +0000287 O << "\t.686\n\t.model flat\n\n";
288
289 // Emit declarations for external functions.
290 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
291 if (I->isExternal())
292 O << "\textern " << Mang->getValueName(I) << ":near\n";
293
Jeff Cohend43b18d2006-05-06 21:27:14 +0000294 // Emit declarations for external globals. Note that VC++ always declares
295 // external globals to have type byte, and if that's good enough for VC++...
Jeff Cohen4f1ea1e2006-05-02 03:11:50 +0000296 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
297 I != E; ++I) {
298 if (I->isExternal())
299 O << "\textern " << Mang->getValueName(I) << ":byte\n";
300 }
301
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000302 return false;
303}
304
Jeff Cohen4f1ea1e2006-05-02 03:11:50 +0000305bool X86IntelAsmPrinter::doFinalization(Module &M) {
Jeff Cohend43b18d2006-05-06 21:27:14 +0000306 const TargetData *TD = TM.getTargetData();
307
308 // Print out module-level global variables here.
309 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
310 I != E; ++I) {
311 if (I->isExternal()) continue; // External global require no code
312
313 // Check to see if this is a special global used by LLVM, if so, emit it.
314 if (EmitSpecialLLVMGlobal(I))
315 continue;
316
317 std::string name = Mang->getValueName(I);
318 Constant *C = I->getInitializer();
319 unsigned Size = TD->getTypeSize(C->getType());
320 unsigned Align = getPreferredAlignmentLog(I);
321 bool bCustomSegment = false;
322
323 switch (I->getLinkage()) {
324 case GlobalValue::LinkOnceLinkage:
325 case GlobalValue::WeakLinkage:
Chris Lattner4632d7a2006-05-09 04:59:56 +0000326 SwitchToDataSection("", 0);
Jeff Cohend43b18d2006-05-06 21:27:14 +0000327 O << name << "?\tsegment common 'COMMON'\n";
328 bCustomSegment = true;
329 // FIXME: the default alignment is 16 bytes, but 1, 2, 4, and 256
330 // are also available.
331 break;
332 case GlobalValue::AppendingLinkage:
Chris Lattner4632d7a2006-05-09 04:59:56 +0000333 SwitchToDataSection("", 0);
Jeff Cohend43b18d2006-05-06 21:27:14 +0000334 O << name << "?\tsegment public 'DATA'\n";
335 bCustomSegment = true;
336 // FIXME: the default alignment is 16 bytes, but 1, 2, 4, and 256
337 // are also available.
338 break;
339 case GlobalValue::ExternalLinkage:
340 O << "\tpublic " << name << "\n";
341 // FALL THROUGH
342 case GlobalValue::InternalLinkage:
Jim Laskey563321a2006-09-06 18:34:40 +0000343 SwitchToDataSection(TAI->getDataSection(), I);
Jeff Cohend43b18d2006-05-06 21:27:14 +0000344 break;
345 default:
346 assert(0 && "Unknown linkage type!");
347 }
348
349 if (!bCustomSegment)
350 EmitAlignment(Align, I);
351
Jim Laskey563321a2006-09-06 18:34:40 +0000352 O << name << ":\t\t\t\t" << TAI->getCommentString()
353 << " " << I->getName() << '\n';
Jeff Cohend43b18d2006-05-06 21:27:14 +0000354
355 EmitGlobalConstant(C);
356
357 if (bCustomSegment)
358 O << name << "?\tends\n";
359 }
360
361 // Bypass X86SharedAsmPrinter::doFinalization().
362 AsmPrinter::doFinalization(M);
Chris Lattnere7027d52006-05-09 05:15:24 +0000363 SwitchToDataSection("", 0);
Jeff Cohen4f1ea1e2006-05-02 03:11:50 +0000364 O << "\tend\n";
Jeff Cohend43b18d2006-05-06 21:27:14 +0000365 return false; // success
Jeff Cohen4f1ea1e2006-05-02 03:11:50 +0000366}
367
Jeff Cohenc884db42006-05-02 01:16:28 +0000368void X86IntelAsmPrinter::EmitString(const ConstantArray *CVA) const {
369 unsigned NumElts = CVA->getNumOperands();
370 if (NumElts) {
371 // ML does not have escape sequences except '' for '. It also has a maximum
372 // string length of 255.
373 unsigned len = 0;
374 bool inString = false;
375 for (unsigned i = 0; i < NumElts; i++) {
376 int n = cast<ConstantInt>(CVA->getOperand(i))->getRawValue() & 255;
377 if (len == 0)
378 O << "\tdb ";
379
380 if (n >= 32 && n <= 127) {
381 if (!inString) {
382 if (len > 0) {
383 O << ",'";
384 len += 2;
385 } else {
386 O << "'";
387 len++;
388 }
389 inString = true;
390 }
391 if (n == '\'') {
392 O << "'";
393 len++;
394 }
395 O << char(n);
396 } else {
397 if (inString) {
398 O << "'";
399 len++;
400 inString = false;
401 }
402 if (len > 0) {
403 O << ",";
404 len++;
405 }
406 O << n;
407 len += 1 + (n > 9) + (n > 99);
408 }
409
410 if (len > 60) {
411 if (inString) {
412 O << "'";
413 inString = false;
414 }
415 O << "\n";
416 len = 0;
417 }
418 }
419
420 if (len > 0) {
421 if (inString)
422 O << "'";
423 O << "\n";
424 }
425 }
426}
427
Chris Lattnerb36cbd02005-07-01 22:44:09 +0000428// Include the auto-generated portion of the assembly writer.
429#include "X86GenAsmWriter1.inc"