1 //===-- X86AsmPrinter.cpp - Convert X86 LLVM code to Intel assembly -------===//
3 // The LLVM Compiler Infrastructure
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.
8 //===----------------------------------------------------------------------===//
10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to Intel and AT&T format assembly
12 // language. This printer is the output mechanism used by `llc' and `lli
13 // -print-machineinstrs' on X86.
15 //===----------------------------------------------------------------------===//
18 #include "X86TargetMachine.h"
19 #include "llvm/Module.h"
20 #include "llvm/Type.h"
21 #include "llvm/Assembly/Writer.h"
22 #include "llvm/CodeGen/AsmPrinter.h"
23 #include "llvm/CodeGen/MachineConstantPool.h"
24 #include "llvm/CodeGen/MachineFunctionPass.h"
25 #include "llvm/CodeGen/ValueTypes.h"
26 #include "llvm/Target/TargetMachine.h"
27 #include "llvm/Support/Mangler.h"
28 #include "llvm/ADT/Statistic.h"
29 #include "llvm/Support/CommandLine.h"
33 Statistic
<> EmittedInsts("asm-printer", "Number of machine instrs printed");
34 enum AsmWriterFlavor
{ att
, intel
};
36 cl::opt
<AsmWriterFlavor
>
37 AsmWriterFlavor("x86-asm-syntax",
38 cl::desc("Choose style of code to emit from X86 backend:"),
40 clEnumVal(att
, " Emit AT&T-style assembly"),
41 clEnumVal(intel
, " Emit Intel-style assembly"),
45 struct X86SharedAsmPrinter
: public AsmPrinter
{
46 X86SharedAsmPrinter(std::ostream
&O
, TargetMachine
&TM
)
47 : AsmPrinter(O
, TM
), forCygwin(false) { }
49 bool doInitialization(Module
&M
);
50 void printConstantPool(MachineConstantPool
*MCP
);
51 bool doFinalization(Module
&M
);
56 static bool isScale(const MachineOperand
&MO
) {
57 return MO
.isImmediate() &&
58 (MO
.getImmedValue() == 1 || MO
.getImmedValue() == 2 ||
59 MO
.getImmedValue() == 4 || MO
.getImmedValue() == 8);
62 static bool isMem(const MachineInstr
*MI
, unsigned Op
) {
63 if (MI
->getOperand(Op
).isFrameIndex()) return true;
64 if (MI
->getOperand(Op
).isConstantPoolIndex()) return true;
65 return Op
+4 <= MI
->getNumOperands() &&
66 MI
->getOperand(Op
).isRegister() && isScale(MI
->getOperand(Op
+1)) &&
67 MI
->getOperand(Op
+2).isRegister() && (MI
->getOperand(Op
+3).isImmediate() ||
68 MI
->getOperand(Op
+3).isGlobalAddress());
71 // SwitchSection - Switch to the specified section of the executable if we are
74 static void SwitchSection(std::ostream
&OS
, std::string
&CurSection
,
75 const char *NewSection
) {
76 if (CurSection
!= NewSection
) {
77 CurSection
= NewSection
;
78 if (!CurSection
.empty())
79 OS
<< "\t" << NewSection
<< "\n";
83 /// doInitialization - determine
84 bool X86SharedAsmPrinter::doInitialization(Module
& M
) {
86 const std::string
& TT
= M
.getTargetTriple();
88 forCygwin
= TT
.find("cygwin") != std::string::npos
||
89 TT
.find("mingw") != std::string::npos
;
90 else if (TT
.empty()) {
91 #if defined(__CYGWIN__) || defined(__MINGW32__)
99 return AsmPrinter::doInitialization(M
);
102 /// printConstantPool - Print to the current output stream assembly
103 /// representations of the constants in the constant pool MCP. This is
104 /// used to print out constants which have been "spilled to memory" by
105 /// the code generator.
107 void X86SharedAsmPrinter::printConstantPool(MachineConstantPool
*MCP
) {
108 const std::vector
<Constant
*> &CP
= MCP
->getConstants();
109 const TargetData
&TD
= TM
.getTargetData();
111 if (CP
.empty()) return;
113 for (unsigned i
= 0, e
= CP
.size(); i
!= e
; ++i
) {
114 O
<< "\t.section .rodata\n";
115 emitAlignment(TD
.getTypeAlignmentShift(CP
[i
]->getType()));
116 O
<< ".CPI" << CurrentFnName
<< "_" << i
<< ":\t\t\t\t\t" << CommentString
118 emitGlobalConstant(CP
[i
]);
122 bool X86SharedAsmPrinter::doFinalization(Module
&M
) {
123 const TargetData
&TD
= TM
.getTargetData();
124 std::string CurSection
;
126 // Print out module-level global variables here.
127 for (Module::const_global_iterator I
= M
.global_begin(), E
= M
.global_end(); I
!= E
; ++I
)
128 if (I
->hasInitializer()) { // External global require no code
130 std::string name
= Mang
->getValueName(I
);
131 Constant
*C
= I
->getInitializer();
132 unsigned Size
= TD
.getTypeSize(C
->getType());
133 unsigned Align
= TD
.getTypeAlignmentShift(C
->getType());
135 if (C
->isNullValue() &&
136 (I
->hasLinkOnceLinkage() || I
->hasInternalLinkage() ||
137 I
->hasWeakLinkage() /* FIXME: Verify correct */)) {
138 SwitchSection(O
, CurSection
, ".data");
139 if (!forCygwin
&& I
->hasInternalLinkage())
140 O
<< "\t.local " << name
<< "\n";
142 O
<< "\t.comm " << name
<< "," << TD
.getTypeSize(C
->getType());
144 O
<< "," << (1 << Align
);
146 WriteAsOperand(O
, I
, true, true, &M
);
149 switch (I
->getLinkage()) {
150 case GlobalValue::LinkOnceLinkage
:
151 case GlobalValue::WeakLinkage
: // FIXME: Verify correct for weak.
152 // Nonnull linkonce -> weak
153 O
<< "\t.weak " << name
<< "\n";
154 SwitchSection(O
, CurSection
, "");
155 O
<< "\t.section\t.llvm.linkonce.d." << name
<< ",\"aw\",@progbits\n";
157 case GlobalValue::AppendingLinkage
:
158 // FIXME: appending linkage variables should go into a section of
159 // their name or something. For now, just emit them as external.
160 case GlobalValue::ExternalLinkage
:
161 // If external or appending, declare as a global symbol
162 O
<< "\t.globl " << name
<< "\n";
164 case GlobalValue::InternalLinkage
:
165 if (C
->isNullValue())
166 SwitchSection(O
, CurSection
, ".bss");
168 SwitchSection(O
, CurSection
, ".data");
170 case GlobalValue::GhostLinkage
:
171 std::cerr
<< "GhostLinkage cannot appear in X86AsmPrinter!\n";
175 emitAlignment(Align
);
177 O
<< "\t.type " << name
<< ",@object\n";
178 O
<< "\t.size " << name
<< "," << Size
<< "\n";
180 O
<< name
<< ":\t\t\t\t# ";
181 WriteAsOperand(O
, I
, true, true, &M
);
183 WriteAsOperand(O
, C
, false, false, &M
);
185 emitGlobalConstant(C
);
189 AsmPrinter::doFinalization(M
);
190 return false; // success
194 struct X86IntelAsmPrinter
: public X86SharedAsmPrinter
{
195 X86IntelAsmPrinter(std::ostream
&O
, TargetMachine
&TM
)
196 : X86SharedAsmPrinter(O
, TM
) { }
198 virtual const char *getPassName() const {
199 return "X86 Intel-Style Assembly Printer";
202 /// printInstruction - This method is automatically generated by tablegen
203 /// from the instruction set description. This method returns true if the
204 /// machine instruction was sufficiently described to print it, otherwise it
206 bool printInstruction(const MachineInstr
*MI
);
208 // This method is used by the tablegen'erated instruction printer.
209 void printOperand(const MachineInstr
*MI
, unsigned OpNo
, MVT::ValueType VT
){
210 const MachineOperand
&MO
= MI
->getOperand(OpNo
);
211 if (MO
.getType() == MachineOperand::MO_MachineRegister
) {
212 assert(MRegisterInfo::isPhysicalRegister(MO
.getReg())&&"Not physref??");
213 // Bug Workaround: See note in Printer::doInitialization about %.
214 O
<< "%" << TM
.getRegisterInfo()->get(MO
.getReg()).Name
;
220 void printCallOperand(const MachineInstr
*MI
, unsigned OpNo
,
222 printOp(MI
->getOperand(OpNo
), true); // Don't print "OFFSET".
225 void printMemoryOperand(const MachineInstr
*MI
, unsigned OpNo
,
228 default: assert(0 && "Unknown arg size!");
229 case MVT::i8
: O
<< "BYTE PTR "; break;
230 case MVT::i16
: O
<< "WORD PTR "; break;
232 case MVT::f32
: O
<< "DWORD PTR "; break;
234 case MVT::f64
: O
<< "QWORD PTR "; break;
235 case MVT::f80
: O
<< "XWORD PTR "; break;
237 printMemReference(MI
, OpNo
);
240 void printMachineInstruction(const MachineInstr
*MI
);
241 void printOp(const MachineOperand
&MO
, bool elideOffsetKeyword
= false);
242 void printMemReference(const MachineInstr
*MI
, unsigned Op
);
243 bool runOnMachineFunction(MachineFunction
&F
);
244 bool doInitialization(Module
&M
);
246 } // end of anonymous namespace
249 // Include the auto-generated portion of the assembly writer.
250 #include "X86GenAsmWriter1.inc"
253 /// runOnMachineFunction - This uses the printMachineInstruction()
254 /// method to print assembly for each instruction.
256 bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction
&MF
) {
257 setupMachineFunction(MF
);
260 // Print out constants referenced by the function
261 printConstantPool(MF
.getConstantPool());
263 // Print out labels for the function.
266 O
<< "\t.globl\t" << CurrentFnName
<< "\n";
268 O
<< "\t.type\t" << CurrentFnName
<< ", @function\n";
269 O
<< CurrentFnName
<< ":\n";
271 // Print out code for the function.
272 for (MachineFunction::const_iterator I
= MF
.begin(), E
= MF
.end();
274 // Print a label for the basic block if there are any predecessors.
275 if (I
->pred_begin() != I
->pred_end())
276 O
<< ".LBB" << CurrentFnName
<< "_" << I
->getNumber() << ":\t"
277 << CommentString
<< " " << I
->getBasicBlock()->getName() << "\n";
278 for (MachineBasicBlock::const_iterator II
= I
->begin(), E
= I
->end();
280 // Print the assembly for the instruction.
282 printMachineInstruction(II
);
286 // We didn't modify anything.
290 void X86IntelAsmPrinter::printOp(const MachineOperand
&MO
,
291 bool elideOffsetKeyword
/* = false */) {
292 const MRegisterInfo
&RI
= *TM
.getRegisterInfo();
293 switch (MO
.getType()) {
294 case MachineOperand::MO_VirtualRegister
:
295 if (Value
*V
= MO
.getVRegValueOrNull()) {
296 O
<< "<" << V
->getName() << ">";
300 case MachineOperand::MO_MachineRegister
:
301 if (MRegisterInfo::isPhysicalRegister(MO
.getReg()))
302 // Bug Workaround: See note in Printer::doInitialization about %.
303 O
<< "%" << RI
.get(MO
.getReg()).Name
;
305 O
<< "%reg" << MO
.getReg();
308 case MachineOperand::MO_SignExtendedImmed
:
309 case MachineOperand::MO_UnextendedImmed
:
310 O
<< (int)MO
.getImmedValue();
312 case MachineOperand::MO_MachineBasicBlock
: {
313 MachineBasicBlock
*MBBOp
= MO
.getMachineBasicBlock();
314 O
<< ".LBB" << Mang
->getValueName(MBBOp
->getParent()->getFunction())
315 << "_" << MBBOp
->getNumber () << "\t# "
316 << MBBOp
->getBasicBlock ()->getName ();
319 case MachineOperand::MO_PCRelativeDisp
:
320 std::cerr
<< "Shouldn't use addPCDisp() when building X86 MachineInstrs";
323 case MachineOperand::MO_GlobalAddress
: {
324 if (!elideOffsetKeyword
)
326 O
<< Mang
->getValueName(MO
.getGlobal());
327 int Offset
= MO
.getOffset();
329 O
<< " + " << Offset
;
331 O
<< " - " << -Offset
;
334 case MachineOperand::MO_ExternalSymbol
:
335 O
<< GlobalPrefix
<< MO
.getSymbolName();
338 O
<< "<unknown operand type>"; return;
342 void X86IntelAsmPrinter::printMemReference(const MachineInstr
*MI
, unsigned Op
){
343 assert(isMem(MI
, Op
) && "Invalid memory reference!");
345 const MachineOperand
&BaseReg
= MI
->getOperand(Op
);
346 int ScaleVal
= MI
->getOperand(Op
+1).getImmedValue();
347 const MachineOperand
&IndexReg
= MI
->getOperand(Op
+2);
348 const MachineOperand
&DispSpec
= MI
->getOperand(Op
+3);
350 if (BaseReg
.isFrameIndex()) {
351 O
<< "[frame slot #" << BaseReg
.getFrameIndex();
352 if (DispSpec
.getImmedValue())
353 O
<< " + " << DispSpec
.getImmedValue();
356 } else if (BaseReg
.isConstantPoolIndex()) {
357 O
<< "[.CPI" << CurrentFnName
<< "_"
358 << BaseReg
.getConstantPoolIndex();
360 if (IndexReg
.getReg()) {
363 O
<< ScaleVal
<< "*";
367 if (DispSpec
.getImmedValue())
368 O
<< " + " << DispSpec
.getImmedValue();
374 bool NeedPlus
= false;
375 if (BaseReg
.getReg()) {
376 printOp(BaseReg
, true);
380 if (IndexReg
.getReg()) {
381 if (NeedPlus
) O
<< " + ";
383 O
<< ScaleVal
<< "*";
388 if (DispSpec
.isGlobalAddress()) {
391 printOp(DispSpec
, true);
393 int DispVal
= DispSpec
.getImmedValue();
394 if (DispVal
|| (!BaseReg
.getReg() && !IndexReg
.getReg())) {
409 /// printMachineInstruction -- Print out a single X86 LLVM instruction
410 /// MI in Intel syntax to the current output stream.
412 void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr
*MI
) {
415 // Call the autogenerated instruction printer routines.
416 printInstruction(MI
);
419 bool X86IntelAsmPrinter::doInitialization(Module
&M
) {
420 AsmPrinter::doInitialization(M
);
421 // Tell gas we are outputting Intel syntax (not AT&T syntax) assembly.
423 // Bug: gas in `intel_syntax noprefix' mode interprets the symbol `Sp' in an
424 // instruction as a reference to the register named sp, and if you try to
425 // reference a symbol `Sp' (e.g. `mov ECX, OFFSET Sp') then it gets lowercased
426 // before being looked up in the symbol table. This creates spurious
427 // `undefined symbol' errors when linking. Workaround: Do not use `noprefix'
428 // mode, and decorate all register names with percent signs.
429 O
<< "\t.intel_syntax\n";
436 struct X86ATTAsmPrinter
: public X86SharedAsmPrinter
{
437 X86ATTAsmPrinter(std::ostream
&O
, TargetMachine
&TM
)
438 : X86SharedAsmPrinter(O
, TM
) { }
440 virtual const char *getPassName() const {
441 return "X86 AT&T-Style Assembly Printer";
444 /// printInstruction - This method is automatically generated by tablegen
445 /// from the instruction set description. This method returns true if the
446 /// machine instruction was sufficiently described to print it, otherwise it
448 bool printInstruction(const MachineInstr
*MI
);
450 // This method is used by the tablegen'erated instruction printer.
451 void printOperand(const MachineInstr
*MI
, unsigned OpNo
, MVT::ValueType VT
){
452 printOp(MI
->getOperand(OpNo
));
455 void printCallOperand(const MachineInstr
*MI
, unsigned OpNo
,
457 printOp(MI
->getOperand(OpNo
), true); // Don't print '$' prefix.
460 void printMemoryOperand(const MachineInstr
*MI
, unsigned OpNo
,
462 printMemReference(MI
, OpNo
);
465 void printMachineInstruction(const MachineInstr
*MI
);
466 void printOp(const MachineOperand
&MO
, bool isCallOperand
= false);
467 void printMemReference(const MachineInstr
*MI
, unsigned Op
);
468 bool runOnMachineFunction(MachineFunction
&F
);
470 } // end of anonymous namespace
473 // Include the auto-generated portion of the assembly writer.
474 #include "X86GenAsmWriter.inc"
477 /// runOnMachineFunction - This uses the printMachineInstruction()
478 /// method to print assembly for each instruction.
480 bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction
&MF
) {
481 setupMachineFunction(MF
);
484 // Print out constants referenced by the function
485 printConstantPool(MF
.getConstantPool());
487 // Print out labels for the function.
490 O
<< "\t.globl\t" << CurrentFnName
<< "\n";
492 O
<< "\t.type\t" << CurrentFnName
<< ", @function\n";
493 O
<< CurrentFnName
<< ":\n";
495 // Print out code for the function.
496 for (MachineFunction::const_iterator I
= MF
.begin(), E
= MF
.end();
498 // Print a label for the basic block.
499 if (I
->pred_begin() != I
->pred_end())
500 O
<< ".LBB" << CurrentFnName
<< "_" << I
->getNumber() << ":\t"
501 << CommentString
<< " " << I
->getBasicBlock()->getName() << "\n";
502 for (MachineBasicBlock::const_iterator II
= I
->begin(), E
= I
->end();
504 // Print the assembly for the instruction.
506 printMachineInstruction(II
);
510 // We didn't modify anything.
514 void X86ATTAsmPrinter::printOp(const MachineOperand
&MO
, bool isCallOp
) {
515 const MRegisterInfo
&RI
= *TM
.getRegisterInfo();
516 switch (MO
.getType()) {
517 case MachineOperand::MO_VirtualRegister
:
518 case MachineOperand::MO_MachineRegister
:
519 assert(MRegisterInfo::isPhysicalRegister(MO
.getReg()) &&
520 "Virtual registers should not make it this far!");
522 for (const char *Name
= RI
.get(MO
.getReg()).Name
; *Name
; ++Name
)
523 O
<< (char)tolower(*Name
);
526 case MachineOperand::MO_SignExtendedImmed
:
527 case MachineOperand::MO_UnextendedImmed
:
528 O
<< '$' << (int)MO
.getImmedValue();
530 case MachineOperand::MO_MachineBasicBlock
: {
531 MachineBasicBlock
*MBBOp
= MO
.getMachineBasicBlock();
532 O
<< ".LBB" << Mang
->getValueName(MBBOp
->getParent()->getFunction())
533 << "_" << MBBOp
->getNumber () << "\t# "
534 << MBBOp
->getBasicBlock ()->getName ();
537 case MachineOperand::MO_PCRelativeDisp
:
538 std::cerr
<< "Shouldn't use addPCDisp() when building X86 MachineInstrs";
541 case MachineOperand::MO_GlobalAddress
: {
542 if (!isCallOp
) O
<< '$';
543 O
<< Mang
->getValueName(MO
.getGlobal());
544 int Offset
= MO
.getOffset();
551 case MachineOperand::MO_ExternalSymbol
:
552 if (!isCallOp
) O
<< '$';
553 O
<< GlobalPrefix
<< MO
.getSymbolName();
556 O
<< "<unknown operand type>"; return;
560 void X86ATTAsmPrinter::printMemReference(const MachineInstr
*MI
, unsigned Op
){
561 assert(isMem(MI
, Op
) && "Invalid memory reference!");
563 const MachineOperand
&BaseReg
= MI
->getOperand(Op
);
564 int ScaleVal
= MI
->getOperand(Op
+1).getImmedValue();
565 const MachineOperand
&IndexReg
= MI
->getOperand(Op
+2);
566 const MachineOperand
&DispSpec
= MI
->getOperand(Op
+3);
568 if (BaseReg
.isFrameIndex()) {
569 O
<< "[frame slot #" << BaseReg
.getFrameIndex();
570 if (DispSpec
.getImmedValue())
571 O
<< " + " << DispSpec
.getImmedValue();
574 } else if (BaseReg
.isConstantPoolIndex()) {
575 O
<< ".CPI" << CurrentFnName
<< "_"
576 << BaseReg
.getConstantPoolIndex();
577 if (DispSpec
.getImmedValue())
578 O
<< "+" << DispSpec
.getImmedValue();
579 if (IndexReg
.getReg()) {
583 O
<< "," << ScaleVal
;
589 if (DispSpec
.isGlobalAddress()) {
590 printOp(DispSpec
, true);
592 int DispVal
= DispSpec
.getImmedValue();
593 if (DispVal
|| (!IndexReg
.getReg() && !BaseReg
.getReg()))
597 if (IndexReg
.getReg() || BaseReg
.getReg()) {
599 if (BaseReg
.getReg())
602 if (IndexReg
.getReg()) {
606 O
<< "," << ScaleVal
;
614 /// printMachineInstruction -- Print out a single X86 LLVM instruction
615 /// MI in Intel syntax to the current output stream.
617 void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr
*MI
) {
619 // Call the autogenerated instruction printer routines.
620 printInstruction(MI
);
624 /// createX86CodePrinterPass - Returns a pass that prints the X86 assembly code
625 /// for a MachineFunction to the given output stream, using the given target
626 /// machine description.
628 FunctionPass
*llvm::createX86CodePrinterPass(std::ostream
&o
,TargetMachine
&tm
){
629 switch (AsmWriterFlavor
) {
631 assert(0 && "Unknown asm flavor!");
633 return new X86IntelAsmPrinter(o
, tm
);
635 return new X86ATTAsmPrinter(o
, tm
);