blob: b6f4cd1cb1481856a3becf013955485f18a8e29c [file] [log] [blame]
Misha Brukman91b5ca82004-07-26 18:45:48 +00001//===-- X86AsmPrinter.cpp - Convert X86 LLVM code to Intel assembly -------===//
John Criswellb576c942003-10-20 19:43:21 +00002//
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//===----------------------------------------------------------------------===//
Chris Lattner72614082002-10-25 22:55:53 +00009//
Misha Brukman538607f2004-03-01 23:53:11 +000010// This file contains a printer that converts from our internal representation
11// of machine-dependent LLVM code to Intel-format assembly language. This
12// printer is the output mechanism used by `llc' and `lli -print-machineinstrs'
13// on X86.
Chris Lattner72614082002-10-25 22:55:53 +000014//
15//===----------------------------------------------------------------------===//
16
17#include "X86.h"
Brian Gaeke6559bb92002-11-14 22:32:30 +000018#include "X86InstrInfo.h"
Alkis Evlogimenos03090662004-03-09 03:35:34 +000019#include "X86TargetMachine.h"
Chris Lattnere0121322003-08-03 23:37:09 +000020#include "llvm/Constants.h"
21#include "llvm/DerivedTypes.h"
Chris Lattnerd59414f2003-08-11 20:06:16 +000022#include "llvm/Module.h"
23#include "llvm/Assembly/Writer.h"
Chris Lattner055acae2004-08-16 23:16:06 +000024#include "llvm/CodeGen/AsmPrinter.h"
Alkis Evlogimenos03090662004-03-09 03:35:34 +000025#include "llvm/CodeGen/MachineCodeEmitter.h"
Chris Lattnerb7089442003-01-13 00:35:03 +000026#include "llvm/CodeGen/MachineConstantPool.h"
Alkis Evlogimenos03090662004-03-09 03:35:34 +000027#include "llvm/CodeGen/MachineFunctionPass.h"
Chris Lattnerdbb61c62002-11-17 22:53:13 +000028#include "llvm/CodeGen/MachineInstr.h"
Chris Lattnerb12ee502004-08-01 07:43:46 +000029#include "llvm/CodeGen/ValueTypes.h"
Chris Lattnerd59414f2003-08-11 20:06:16 +000030#include "llvm/Target/TargetMachine.h"
Brian Gaeked9fb37a2003-07-24 20:20:44 +000031#include "llvm/Support/Mangler.h"
Reid Spencer551ccae2004-09-01 22:55:40 +000032#include "llvm/ADT/Statistic.h"
33#include "llvm/ADT/StringExtras.h"
34#include "llvm/Support/CommandLine.h"
Chris Lattner300d0ed2004-02-14 06:00:36 +000035using namespace llvm;
Brian Gaeked0fde302003-11-11 22:41:34 +000036
Chris Lattnerb4f68ed2002-10-29 22:37:54 +000037namespace {
Brian Gaeke2c9b9132003-10-06 15:41:21 +000038 Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
Chris Lattner9a3e49a2004-10-03 20:36:57 +000039 enum AsmWriterFlavor { att, intel };
40
41 cl::opt<AsmWriterFlavor>
42 AsmWriterFlavor("x86-asm-syntax",
43 cl::desc("Choose style of code to emit from X86 backend:"),
44 cl::values(
45 clEnumVal(att, " Emit AT&T Style"),
46 clEnumVal(intel, " Emit Intel Style"),
47 clEnumValEnd),
48 cl::init(intel));
Brian Gaeke2c9b9132003-10-06 15:41:21 +000049
Alkis Evlogimenos03090662004-03-09 03:35:34 +000050 struct GasBugWorkaroundEmitter : public MachineCodeEmitter {
Misha Brukman8606aea2004-07-26 18:48:58 +000051 GasBugWorkaroundEmitter(std::ostream& o)
52 : O(o), OldFlags(O.flags()), firstByte(true) {
53 O << std::hex;
54 }
Alkis Evlogimenos03090662004-03-09 03:35:34 +000055
Misha Brukman8606aea2004-07-26 18:48:58 +000056 ~GasBugWorkaroundEmitter() {
57 O.flags(OldFlags);
Misha Brukman8606aea2004-07-26 18:48:58 +000058 }
Alkis Evlogimenos03090662004-03-09 03:35:34 +000059
Misha Brukman8606aea2004-07-26 18:48:58 +000060 virtual void emitByte(unsigned char B) {
61 if (!firstByte) O << "\n\t";
62 firstByte = false;
63 O << ".byte 0x" << (unsigned) B;
64 }
Alkis Evlogimenos03090662004-03-09 03:35:34 +000065
Misha Brukman8606aea2004-07-26 18:48:58 +000066 // These should never be called
67 virtual void emitWord(unsigned W) { assert(0); }
68 virtual uint64_t getGlobalValueAddress(GlobalValue *V) { abort(); }
69 virtual uint64_t getGlobalValueAddress(const std::string &Name) { abort(); }
70 virtual uint64_t getConstantPoolEntryAddress(unsigned Index) { abort(); }
71 virtual uint64_t getCurrentPCValue() { abort(); }
72 virtual uint64_t forceCompilationOf(Function *F) { abort(); }
Alkis Evlogimenos03090662004-03-09 03:35:34 +000073
74 private:
Misha Brukman8606aea2004-07-26 18:48:58 +000075 std::ostream& O;
76 std::ios::fmtflags OldFlags;
77 bool firstByte;
Alkis Evlogimenos03090662004-03-09 03:35:34 +000078 };
79
Chris Lattner9a3e49a2004-10-03 20:36:57 +000080 struct X86IntelAsmPrinter : public AsmPrinter {
81 X86IntelAsmPrinter(std::ostream &O, TargetMachine &TM) : AsmPrinter(O, TM) { }
Brian Gaeke92bdfe62003-07-23 18:37:06 +000082
Chris Lattnerf0eb7be2002-12-15 21:13:40 +000083 virtual const char *getPassName() const {
84 return "X86 Assembly Printer";
85 }
86
Chris Lattner3fa861a2004-08-01 06:02:08 +000087 /// printInstruction - This method is automatically generated by tablegen
88 /// from the instruction set description. This method returns true if the
89 /// machine instruction was sufficiently described to print it, otherwise it
90 /// returns false.
91 bool printInstruction(const MachineInstr *MI);
92
Chris Lattnerb12ee502004-08-01 07:43:46 +000093 // This method is used by the tablegen'erated instruction printer.
Chris Lattner055acae2004-08-16 23:16:06 +000094 void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){
Chris Lattner66fa1dc2004-08-11 02:25:00 +000095 const MachineOperand &MO = MI->getOperand(OpNo);
Chris Lattner25369cf2004-08-01 08:12:41 +000096 if (MO.getType() == MachineOperand::MO_MachineRegister) {
97 assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physref??");
98 // Bug Workaround: See note in Printer::doInitialization about %.
99 O << "%" << TM.getRegisterInfo()->get(MO.getReg()).Name;
100 } else {
101 printOp(MO);
102 }
Chris Lattnerb12ee502004-08-01 07:43:46 +0000103 }
104
Chris Lattner055acae2004-08-16 23:16:06 +0000105 void printCallOperand(const MachineInstr *MI, unsigned OpNo,
106 MVT::ValueType VT) {
Chris Lattnere4ead0c2004-08-11 06:59:12 +0000107 printOp(MI->getOperand(OpNo), true); // Don't print "OFFSET".
108 }
109
Chris Lattner66fa1dc2004-08-11 02:25:00 +0000110 void printMemoryOperand(const MachineInstr *MI, unsigned OpNo,
111 MVT::ValueType VT) {
112 switch (VT) {
113 default: assert(0 && "Unknown arg size!");
114 case MVT::i8: O << "BYTE PTR "; break;
115 case MVT::i16: O << "WORD PTR "; break;
116 case MVT::i32:
117 case MVT::f32: O << "DWORD PTR "; break;
118 case MVT::i64:
119 case MVT::f64: O << "QWORD PTR "; break;
120 case MVT::f80: O << "XWORD PTR "; break;
121 }
122 printMemReference(MI, OpNo);
123 }
124
Brian Gaeked9fb37a2003-07-24 20:20:44 +0000125 void printMachineInstruction(const MachineInstr *MI);
Misha Brukmane8d8fb22004-06-29 19:28:53 +0000126 void printOp(const MachineOperand &MO, bool elideOffsetKeyword = false);
Brian Gaeked9fb37a2003-07-24 20:20:44 +0000127 void printMemReference(const MachineInstr *MI, unsigned Op);
128 void printConstantPool(MachineConstantPool *MCP);
Brian Gaeke01d79ff2003-06-25 18:01:07 +0000129 bool runOnMachineFunction(MachineFunction &F);
Brian Gaeke9e474c42003-06-19 19:32:32 +0000130 bool doInitialization(Module &M);
131 bool doFinalization(Module &M);
Chris Lattnerb4f68ed2002-10-29 22:37:54 +0000132 };
Brian Gaeked7908f62003-06-27 00:00:48 +0000133} // end of anonymous namespace
Chris Lattnerb4f68ed2002-10-29 22:37:54 +0000134
Brian Gaeke92bdfe62003-07-23 18:37:06 +0000135/// createX86CodePrinterPass - Returns a pass that prints the X86
Brian Gaekede420ae2003-07-23 20:25:08 +0000136/// assembly code for a MachineFunction to the given output stream,
137/// using the given target machine description. This should work
138/// regardless of whether the function is in SSA form.
Chris Lattnerdbb61c62002-11-17 22:53:13 +0000139///
Chris Lattner300d0ed2004-02-14 06:00:36 +0000140FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){
Chris Lattner9a3e49a2004-10-03 20:36:57 +0000141 if (AsmWriterFlavor != intel) {
142 std::cerr << "AT&T syntax not fully implemented yet!\n";
143 abort();
144 }
145
146 return new X86IntelAsmPrinter(o, tm);
Chris Lattnerdbb61c62002-11-17 22:53:13 +0000147}
148
Chris Lattner3fa861a2004-08-01 06:02:08 +0000149
150// Include the auto-generated portion of the assembly writer.
Chris Lattner9a3e49a2004-10-03 20:36:57 +0000151#include "X86GenIntelAsmWriter.inc"
Chris Lattner3fa861a2004-08-01 06:02:08 +0000152
153
Brian Gaeke92bdfe62003-07-23 18:37:06 +0000154/// printConstantPool - Print to the current output stream assembly
155/// representations of the constants in the constant pool MCP. This is
156/// used to print out constants which have been "spilled to memory" by
157/// the code generator.
158///
Chris Lattner9a3e49a2004-10-03 20:36:57 +0000159void X86IntelAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
Chris Lattnerb7089442003-01-13 00:35:03 +0000160 const std::vector<Constant*> &CP = MCP->getConstants();
Brian Gaekede420ae2003-07-23 20:25:08 +0000161 const TargetData &TD = TM.getTargetData();
Brian Gaeke92bdfe62003-07-23 18:37:06 +0000162
Chris Lattnerb7089442003-01-13 00:35:03 +0000163 if (CP.empty()) return;
164
165 for (unsigned i = 0, e = CP.size(); i != e; ++i) {
166 O << "\t.section .rodata\n";
Chris Lattnerc6393f82004-08-17 19:25:42 +0000167 emitAlignment(TD.getTypeAlignmentShift(CP[i]->getType()));
Chris Lattnerf746a7d2004-08-18 02:22:55 +0000168 O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t" << CommentString
Brian Gaeked7908f62003-06-27 00:00:48 +0000169 << *CP[i] << "\n";
Chris Lattnerac662d12003-11-03 20:19:49 +0000170 emitGlobalConstant(CP[i]);
Chris Lattnerb7089442003-01-13 00:35:03 +0000171 }
Chris Lattnerb7089442003-01-13 00:35:03 +0000172}
173
Brian Gaeke92bdfe62003-07-23 18:37:06 +0000174/// runOnMachineFunction - This uses the printMachineInstruction()
175/// method to print assembly for each instruction.
176///
Chris Lattner9a3e49a2004-10-03 20:36:57 +0000177bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
Chris Lattner055acae2004-08-16 23:16:06 +0000178 setupMachineFunction(MF);
Chris Lattnere0121322003-08-03 23:37:09 +0000179 O << "\n\n";
Brian Gaeked7908f62003-06-27 00:00:48 +0000180
Chris Lattnerb7089442003-01-13 00:35:03 +0000181 // Print out constants referenced by the function
Brian Gaeke01d79ff2003-06-25 18:01:07 +0000182 printConstantPool(MF.getConstantPool());
Chris Lattnerb7089442003-01-13 00:35:03 +0000183
Brian Gaeke6559bb92002-11-14 22:32:30 +0000184 // Print out labels for the function.
Chris Lattnerb7089442003-01-13 00:35:03 +0000185 O << "\t.text\n";
Chris Lattnerc6393f82004-08-17 19:25:42 +0000186 emitAlignment(4);
Brian Gaeked7908f62003-06-27 00:00:48 +0000187 O << "\t.globl\t" << CurrentFnName << "\n";
Chris Lattner055acae2004-08-16 23:16:06 +0000188 O << "\t.type\t" << CurrentFnName << ", @function\n";
Brian Gaeked7908f62003-06-27 00:00:48 +0000189 O << CurrentFnName << ":\n";
Brian Gaeke6559bb92002-11-14 22:32:30 +0000190
191 // Print out code for the function.
Chris Lattner0285a332002-12-28 20:25:38 +0000192 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
193 I != E; ++I) {
194 // Print a label for the basic block.
Chris Lattnerc6393f82004-08-17 19:25:42 +0000195 O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t"
Chris Lattnerf746a7d2004-08-18 02:22:55 +0000196 << CommentString << " " << I->getBasicBlock()->getName() << "\n";
Chris Lattner0285a332002-12-28 20:25:38 +0000197 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
Misha Brukmane8d8fb22004-06-29 19:28:53 +0000198 II != E; ++II) {
Chris Lattner0285a332002-12-28 20:25:38 +0000199 // Print the assembly for the instruction.
200 O << "\t";
Alkis Evlogimenosc0b9dc52004-02-12 02:27:10 +0000201 printMachineInstruction(II);
Brian Gaeke6559bb92002-11-14 22:32:30 +0000202 }
Chris Lattner0285a332002-12-28 20:25:38 +0000203 }
Brian Gaeke6559bb92002-11-14 22:32:30 +0000204
205 // We didn't modify anything.
Chris Lattnerb4f68ed2002-10-29 22:37:54 +0000206 return false;
207}
208
Chris Lattner3d3067b2002-11-21 20:44:15 +0000209static bool isScale(const MachineOperand &MO) {
Chris Lattnerd9096832002-12-15 08:01:39 +0000210 return MO.isImmediate() &&
Brian Gaeke01d79ff2003-06-25 18:01:07 +0000211 (MO.getImmedValue() == 1 || MO.getImmedValue() == 2 ||
212 MO.getImmedValue() == 4 || MO.getImmedValue() == 8);
Chris Lattner3d3067b2002-11-21 20:44:15 +0000213}
214
215static bool isMem(const MachineInstr *MI, unsigned Op) {
Chris Lattnerb7089442003-01-13 00:35:03 +0000216 if (MI->getOperand(Op).isFrameIndex()) return true;
217 if (MI->getOperand(Op).isConstantPoolIndex()) return true;
Chris Lattner3d3067b2002-11-21 20:44:15 +0000218 return Op+4 <= MI->getNumOperands() &&
Chris Lattner2a998bd2004-08-11 07:02:04 +0000219 MI->getOperand(Op ).isRegister() && isScale(MI->getOperand(Op+1)) &&
220 MI->getOperand(Op+2).isRegister() && MI->getOperand(Op+3).isImmediate();
Chris Lattner3d3067b2002-11-21 20:44:15 +0000221}
222
Brian Gaeke2a098772003-08-11 19:05:46 +0000223
224
Chris Lattner9a3e49a2004-10-03 20:36:57 +0000225void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
Chris Lattner3fa861a2004-08-01 06:02:08 +0000226 bool elideOffsetKeyword /* = false */) {
Brian Gaekede420ae2003-07-23 20:25:08 +0000227 const MRegisterInfo &RI = *TM.getRegisterInfo();
Chris Lattnerf9f60882002-11-18 06:56:51 +0000228 switch (MO.getType()) {
229 case MachineOperand::MO_VirtualRegister:
Chris Lattnerac573f62002-12-04 17:32:52 +0000230 if (Value *V = MO.getVRegValueOrNull()) {
Chris Lattnerdbf30f72002-12-04 06:45:19 +0000231 O << "<" << V->getName() << ">";
232 return;
233 }
Chris Lattnerb7089442003-01-13 00:35:03 +0000234 // FALLTHROUGH
Misha Brukmane1f0d812002-11-20 18:56:41 +0000235 case MachineOperand::MO_MachineRegister:
Alkis Evlogimenos859a18b2004-02-15 21:37:17 +0000236 if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
Brian Gaeke2a098772003-08-11 19:05:46 +0000237 // Bug Workaround: See note in Printer::doInitialization about %.
Brian Gaeke9d99b432003-08-13 18:15:15 +0000238 O << "%" << RI.get(MO.getReg()).Name;
239 else
Chris Lattnerf9f60882002-11-18 06:56:51 +0000240 O << "%reg" << MO.getReg();
241 return;
Chris Lattner77875d82002-11-21 02:00:20 +0000242
243 case MachineOperand::MO_SignExtendedImmed:
244 case MachineOperand::MO_UnextendedImmed:
245 O << (int)MO.getImmedValue();
246 return;
Brian Gaeke3fb5d1a2004-05-14 06:54:57 +0000247 case MachineOperand::MO_MachineBasicBlock: {
248 MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
249 O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
250 << "_" << MBBOp->getNumber () << "\t# "
251 << MBBOp->getBasicBlock ()->getName ();
Chris Lattnerf8bafe82002-12-01 23:25:59 +0000252 return;
Chris Lattnerad200712003-09-09 16:23:36 +0000253 }
Brian Gaeke3fb5d1a2004-05-14 06:54:57 +0000254 case MachineOperand::MO_PCRelativeDisp:
255 std::cerr << "Shouldn't use addPCDisp() when building X86 MachineInstrs";
256 abort ();
257 return;
Chris Lattnerb7089442003-01-13 00:35:03 +0000258 case MachineOperand::MO_GlobalAddress:
Brian Gaeke002a50a2003-07-31 17:38:52 +0000259 if (!elideOffsetKeyword)
260 O << "OFFSET ";
261 O << Mang->getValueName(MO.getGlobal());
Chris Lattnerb7089442003-01-13 00:35:03 +0000262 return;
263 case MachineOperand::MO_ExternalSymbol:
Brian Gaeke9e474c42003-06-19 19:32:32 +0000264 O << MO.getSymbolName();
Chris Lattnerb7089442003-01-13 00:35:03 +0000265 return;
Chris Lattnerf9f60882002-11-18 06:56:51 +0000266 default:
Brian Gaeke01d79ff2003-06-25 18:01:07 +0000267 O << "<unknown operand type>"; return;
Chris Lattnerf9f60882002-11-18 06:56:51 +0000268 }
269}
270
Chris Lattner9a3e49a2004-10-03 20:36:57 +0000271void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op) {
Chris Lattner3d3067b2002-11-21 20:44:15 +0000272 assert(isMem(MI, Op) && "Invalid memory reference!");
Chris Lattnerb7089442003-01-13 00:35:03 +0000273
274 if (MI->getOperand(Op).isFrameIndex()) {
275 O << "[frame slot #" << MI->getOperand(Op).getFrameIndex();
276 if (MI->getOperand(Op+3).getImmedValue())
277 O << " + " << MI->getOperand(Op+3).getImmedValue();
278 O << "]";
279 return;
280 } else if (MI->getOperand(Op).isConstantPoolIndex()) {
Brian Gaeked7908f62003-06-27 00:00:48 +0000281 O << "[.CPI" << CurrentFnName << "_"
Brian Gaeke5e001572003-06-26 18:02:30 +0000282 << MI->getOperand(Op).getConstantPoolIndex();
Chris Lattnerb7089442003-01-13 00:35:03 +0000283 if (MI->getOperand(Op+3).getImmedValue())
284 O << " + " << MI->getOperand(Op+3).getImmedValue();
285 O << "]";
286 return;
287 }
288
Chris Lattner3d3067b2002-11-21 20:44:15 +0000289 const MachineOperand &BaseReg = MI->getOperand(Op);
Chris Lattner0285a332002-12-28 20:25:38 +0000290 int ScaleVal = MI->getOperand(Op+1).getImmedValue();
Chris Lattner3d3067b2002-11-21 20:44:15 +0000291 const MachineOperand &IndexReg = MI->getOperand(Op+2);
Chris Lattner0285a332002-12-28 20:25:38 +0000292 int DispVal = MI->getOperand(Op+3).getImmedValue();
Chris Lattner3d3067b2002-11-21 20:44:15 +0000293
294 O << "[";
295 bool NeedPlus = false;
296 if (BaseReg.getReg()) {
Brian Gaekede420ae2003-07-23 20:25:08 +0000297 printOp(BaseReg);
Chris Lattner3d3067b2002-11-21 20:44:15 +0000298 NeedPlus = true;
299 }
300
301 if (IndexReg.getReg()) {
302 if (NeedPlus) O << " + ";
Chris Lattner0285a332002-12-28 20:25:38 +0000303 if (ScaleVal != 1)
304 O << ScaleVal << "*";
Brian Gaekede420ae2003-07-23 20:25:08 +0000305 printOp(IndexReg);
Chris Lattner3d3067b2002-11-21 20:44:15 +0000306 NeedPlus = true;
307 }
308
Chris Lattner0285a332002-12-28 20:25:38 +0000309 if (DispVal) {
310 if (NeedPlus)
311 if (DispVal > 0)
Misha Brukmane8d8fb22004-06-29 19:28:53 +0000312 O << " + ";
Chris Lattner0285a332002-12-28 20:25:38 +0000313 else {
Misha Brukmane8d8fb22004-06-29 19:28:53 +0000314 O << " - ";
315 DispVal = -DispVal;
Chris Lattner0285a332002-12-28 20:25:38 +0000316 }
317 O << DispVal;
Chris Lattner3d3067b2002-11-21 20:44:15 +0000318 }
319 O << "]";
320}
321
John Criswell4ffff9e2004-04-08 20:31:47 +0000322
Brian Gaeke92bdfe62003-07-23 18:37:06 +0000323/// printMachineInstruction -- Print out a single X86 LLVM instruction
Brian Gaekede420ae2003-07-23 20:25:08 +0000324/// MI in Intel syntax to the current output stream.
Brian Gaeked7908f62003-06-27 00:00:48 +0000325///
Chris Lattner9a3e49a2004-10-03 20:36:57 +0000326void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
Chris Lattner3fa861a2004-08-01 06:02:08 +0000327 ++EmittedInsts;
Chris Lattner85494292004-08-11 06:09:55 +0000328
329 // gas bugs:
330 //
331 // The 80-bit FP store-pop instruction "fstp XWORD PTR [...]" is misassembled
332 // by gas in intel_syntax mode as its 32-bit equivalent "fstp DWORD PTR
333 // [...]". Workaround: Output the raw opcode bytes instead of the instruction.
334 //
335 // The 80-bit FP load instruction "fld XWORD PTR [...]" is misassembled by gas
336 // in intel_syntax mode as its 32-bit equivalent "fld DWORD PTR
337 // [...]". Workaround: Output the raw opcode bytes instead of the instruction.
338 //
339 // gas intel_syntax mode treats "fild QWORD PTR [...]" as an invalid opcode,
340 // saying "64 bit operations are only supported in 64 bit modes." libopcodes
341 // disassembles it as "fild DWORD PTR [...]", which is wrong. Workaround:
342 // Output the raw opcode bytes instead of the instruction.
343 //
344 // gas intel_syntax mode treats "fistp QWORD PTR [...]" as an invalid opcode,
345 // saying "64 bit operations are only supported in 64 bit modes." libopcodes
346 // disassembles it as "fistpll DWORD PTR [...]", which is wrong. Workaround:
347 // Output the raw opcode bytes instead of the instruction.
348 switch (MI->getOpcode()) {
349 case X86::FSTP80m:
350 case X86::FLD80m:
351 case X86::FILD64m:
352 case X86::FISTP64m:
353 GasBugWorkaroundEmitter gwe(O);
354 X86::emitInstruction(gwe, (X86InstrInfo&)*TM.getInstrInfo(), *MI);
355 O << "\t# ";
356 }
357
Chris Lattner2a998bd2004-08-11 07:02:04 +0000358 // Call the autogenerated instruction printer routines.
359 bool Handled = printInstruction(MI);
360 if (!Handled) {
361 MI->dump();
362 assert(0 && "Do not know how to print this instruction!");
363 abort();
Chris Lattnerf9f60882002-11-18 06:56:51 +0000364 }
Chris Lattner72614082002-10-25 22:55:53 +0000365}
Brian Gaeke9e474c42003-06-19 19:32:32 +0000366
Chris Lattner9a3e49a2004-10-03 20:36:57 +0000367bool X86IntelAsmPrinter::doInitialization(Module &M) {
Chris Lattner055acae2004-08-16 23:16:06 +0000368 AsmPrinter::doInitialization(M);
Chris Lattner93c1afa2003-08-11 19:35:26 +0000369 // Tell gas we are outputting Intel syntax (not AT&T syntax) assembly.
Brian Gaeke2a098772003-08-11 19:05:46 +0000370 //
Chris Lattner93c1afa2003-08-11 19:35:26 +0000371 // Bug: gas in `intel_syntax noprefix' mode interprets the symbol `Sp' in an
372 // instruction as a reference to the register named sp, and if you try to
373 // reference a symbol `Sp' (e.g. `mov ECX, OFFSET Sp') then it gets lowercased
374 // before being looked up in the symbol table. This creates spurious
375 // `undefined symbol' errors when linking. Workaround: Do not use `noprefix'
376 // mode, and decorate all register names with percent signs.
Chris Lattner67488a92003-08-11 20:04:57 +0000377 O << "\t.intel_syntax\n";
Chris Lattner055acae2004-08-16 23:16:06 +0000378 return false;
Brian Gaeke9e474c42003-06-19 19:32:32 +0000379}
380
Chris Lattnerad200712003-09-09 16:23:36 +0000381// SwitchSection - Switch to the specified section of the executable if we are
382// not already in it!
383//
384static void SwitchSection(std::ostream &OS, std::string &CurSection,
385 const char *NewSection) {
386 if (CurSection != NewSection) {
387 CurSection = NewSection;
388 if (!CurSection.empty())
389 OS << "\t" << NewSection << "\n";
390 }
Brian Gaeke0517c5a2003-07-11 21:57:01 +0000391}
392
Chris Lattner9a3e49a2004-10-03 20:36:57 +0000393bool X86IntelAsmPrinter::doFinalization(Module &M) {
Brian Gaekede420ae2003-07-23 20:25:08 +0000394 const TargetData &TD = TM.getTargetData();
Chris Lattnerad200712003-09-09 16:23:36 +0000395 std::string CurSection;
396
Brian Gaeke01d79ff2003-06-25 18:01:07 +0000397 // Print out module-level global variables here.
Chris Lattnerad200712003-09-09 16:23:36 +0000398 for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
399 if (I->hasInitializer()) { // External global require no code
400 O << "\n\n";
401 std::string name = Mang->getValueName(I);
Brian Gaeke01d79ff2003-06-25 18:01:07 +0000402 Constant *C = I->getInitializer();
Chris Lattnerad200712003-09-09 16:23:36 +0000403 unsigned Size = TD.getTypeSize(C->getType());
Chris Lattnerc6393f82004-08-17 19:25:42 +0000404 unsigned Align = TD.getTypeAlignmentShift(C->getType());
Chris Lattnerad200712003-09-09 16:23:36 +0000405
406 if (C->isNullValue() &&
Chris Lattner72ac148d2003-10-16 18:29:00 +0000407 (I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
408 I->hasWeakLinkage() /* FIXME: Verify correct */)) {
Chris Lattnerad200712003-09-09 16:23:36 +0000409 SwitchSection(O, CurSection, ".data");
410 if (I->hasInternalLinkage())
411 O << "\t.local " << name << "\n";
412
413 O << "\t.comm " << name << "," << TD.getTypeSize(C->getType())
Chris Lattnerc6393f82004-08-17 19:25:42 +0000414 << "," << (1 << Align);
Chris Lattnere0121322003-08-03 23:37:09 +0000415 O << "\t\t# ";
416 WriteAsOperand(O, I, true, true, &M);
417 O << "\n";
Brian Gaeke0517c5a2003-07-11 21:57:01 +0000418 } else {
Chris Lattnerad200712003-09-09 16:23:36 +0000419 switch (I->getLinkage()) {
420 case GlobalValue::LinkOnceLinkage:
Chris Lattner72ac148d2003-10-16 18:29:00 +0000421 case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
Chris Lattnerad200712003-09-09 16:23:36 +0000422 // Nonnull linkonce -> weak
423 O << "\t.weak " << name << "\n";
424 SwitchSection(O, CurSection, "");
425 O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
426 break;
Chris Lattnerad200712003-09-09 16:23:36 +0000427 case GlobalValue::AppendingLinkage:
428 // FIXME: appending linkage variables should go into a section of
429 // their name or something. For now, just emit them as external.
430 case GlobalValue::ExternalLinkage:
431 // If external or appending, declare as a global symbol
432 O << "\t.globl " << name << "\n";
433 // FALL THROUGH
434 case GlobalValue::InternalLinkage:
435 if (C->isNullValue())
436 SwitchSection(O, CurSection, ".bss");
437 else
438 SwitchSection(O, CurSection, ".data");
439 break;
440 }
441
Chris Lattnerc6393f82004-08-17 19:25:42 +0000442 emitAlignment(Align);
Chris Lattnere0121322003-08-03 23:37:09 +0000443 O << "\t.type " << name << ",@object\n";
Chris Lattnerad200712003-09-09 16:23:36 +0000444 O << "\t.size " << name << "," << Size << "\n";
Chris Lattnere0121322003-08-03 23:37:09 +0000445 O << name << ":\t\t\t\t# ";
446 WriteAsOperand(O, I, true, true, &M);
447 O << " = ";
448 WriteAsOperand(O, C, false, false, &M);
449 O << "\n";
Chris Lattnerac662d12003-11-03 20:19:49 +0000450 emitGlobalConstant(C);
Brian Gaeke0517c5a2003-07-11 21:57:01 +0000451 }
Brian Gaeke01d79ff2003-06-25 18:01:07 +0000452 }
Chris Lattnerad200712003-09-09 16:23:36 +0000453
Chris Lattner055acae2004-08-16 23:16:06 +0000454 AsmPrinter::doFinalization(M);
Brian Gaeke9e474c42003-06-19 19:32:32 +0000455 return false; // success
456}