blob: e13727707fad2f745d44d5b9bd483ab4f39f786a [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"
Brian Gaeke2c9b9132003-10-06 15:41:21 +000032#include "Support/Statistic.h"
Chris Lattnere0121322003-08-03 23:37:09 +000033#include "Support/StringExtras.h"
Chris Lattner93c1afa2003-08-11 19:35:26 +000034#include "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");
39
Alkis Evlogimenos03090662004-03-09 03:35:34 +000040 struct GasBugWorkaroundEmitter : public MachineCodeEmitter {
Misha Brukman8606aea2004-07-26 18:48:58 +000041 GasBugWorkaroundEmitter(std::ostream& o)
42 : O(o), OldFlags(O.flags()), firstByte(true) {
43 O << std::hex;
44 }
Alkis Evlogimenos03090662004-03-09 03:35:34 +000045
Misha Brukman8606aea2004-07-26 18:48:58 +000046 ~GasBugWorkaroundEmitter() {
47 O.flags(OldFlags);
Misha Brukman8606aea2004-07-26 18:48:58 +000048 }
Alkis Evlogimenos03090662004-03-09 03:35:34 +000049
Misha Brukman8606aea2004-07-26 18:48:58 +000050 virtual void emitByte(unsigned char B) {
51 if (!firstByte) O << "\n\t";
52 firstByte = false;
53 O << ".byte 0x" << (unsigned) B;
54 }
Alkis Evlogimenos03090662004-03-09 03:35:34 +000055
Misha Brukman8606aea2004-07-26 18:48:58 +000056 // These should never be called
57 virtual void emitWord(unsigned W) { assert(0); }
58 virtual uint64_t getGlobalValueAddress(GlobalValue *V) { abort(); }
59 virtual uint64_t getGlobalValueAddress(const std::string &Name) { abort(); }
60 virtual uint64_t getConstantPoolEntryAddress(unsigned Index) { abort(); }
61 virtual uint64_t getCurrentPCValue() { abort(); }
62 virtual uint64_t forceCompilationOf(Function *F) { abort(); }
Alkis Evlogimenos03090662004-03-09 03:35:34 +000063
64 private:
Misha Brukman8606aea2004-07-26 18:48:58 +000065 std::ostream& O;
66 std::ios::fmtflags OldFlags;
67 bool firstByte;
Alkis Evlogimenos03090662004-03-09 03:35:34 +000068 };
69
Chris Lattner055acae2004-08-16 23:16:06 +000070 struct X86AsmPrinter : public AsmPrinter {
71 X86AsmPrinter(std::ostream &O, TargetMachine &TM) : AsmPrinter(O, TM) { }
Brian Gaeke92bdfe62003-07-23 18:37:06 +000072
Chris Lattnerf0eb7be2002-12-15 21:13:40 +000073 virtual const char *getPassName() const {
74 return "X86 Assembly Printer";
75 }
76
Chris Lattner3fa861a2004-08-01 06:02:08 +000077 /// printInstruction - This method is automatically generated by tablegen
78 /// from the instruction set description. This method returns true if the
79 /// machine instruction was sufficiently described to print it, otherwise it
80 /// returns false.
81 bool printInstruction(const MachineInstr *MI);
82
Chris Lattnerb12ee502004-08-01 07:43:46 +000083 // This method is used by the tablegen'erated instruction printer.
Chris Lattner055acae2004-08-16 23:16:06 +000084 void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){
Chris Lattner66fa1dc2004-08-11 02:25:00 +000085 const MachineOperand &MO = MI->getOperand(OpNo);
Chris Lattner25369cf2004-08-01 08:12:41 +000086 if (MO.getType() == MachineOperand::MO_MachineRegister) {
87 assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physref??");
88 // Bug Workaround: See note in Printer::doInitialization about %.
89 O << "%" << TM.getRegisterInfo()->get(MO.getReg()).Name;
90 } else {
91 printOp(MO);
92 }
Chris Lattnerb12ee502004-08-01 07:43:46 +000093 }
94
Chris Lattner055acae2004-08-16 23:16:06 +000095 void printCallOperand(const MachineInstr *MI, unsigned OpNo,
96 MVT::ValueType VT) {
Chris Lattnere4ead0c2004-08-11 06:59:12 +000097 printOp(MI->getOperand(OpNo), true); // Don't print "OFFSET".
98 }
99
Chris Lattner66fa1dc2004-08-11 02:25:00 +0000100 void printMemoryOperand(const MachineInstr *MI, unsigned OpNo,
101 MVT::ValueType VT) {
102 switch (VT) {
103 default: assert(0 && "Unknown arg size!");
104 case MVT::i8: O << "BYTE PTR "; break;
105 case MVT::i16: O << "WORD PTR "; break;
106 case MVT::i32:
107 case MVT::f32: O << "DWORD PTR "; break;
108 case MVT::i64:
109 case MVT::f64: O << "QWORD PTR "; break;
110 case MVT::f80: O << "XWORD PTR "; break;
111 }
112 printMemReference(MI, OpNo);
113 }
114
Brian Gaeked9fb37a2003-07-24 20:20:44 +0000115 void printMachineInstruction(const MachineInstr *MI);
Misha Brukmane8d8fb22004-06-29 19:28:53 +0000116 void printOp(const MachineOperand &MO, bool elideOffsetKeyword = false);
Brian Gaeked9fb37a2003-07-24 20:20:44 +0000117 void printMemReference(const MachineInstr *MI, unsigned Op);
118 void printConstantPool(MachineConstantPool *MCP);
Brian Gaeke01d79ff2003-06-25 18:01:07 +0000119 bool runOnMachineFunction(MachineFunction &F);
Brian Gaeke9e474c42003-06-19 19:32:32 +0000120 bool doInitialization(Module &M);
121 bool doFinalization(Module &M);
Chris Lattnerb4f68ed2002-10-29 22:37:54 +0000122 };
Brian Gaeked7908f62003-06-27 00:00:48 +0000123} // end of anonymous namespace
Chris Lattnerb4f68ed2002-10-29 22:37:54 +0000124
Brian Gaeke92bdfe62003-07-23 18:37:06 +0000125/// createX86CodePrinterPass - Returns a pass that prints the X86
Brian Gaekede420ae2003-07-23 20:25:08 +0000126/// assembly code for a MachineFunction to the given output stream,
127/// using the given target machine description. This should work
128/// regardless of whether the function is in SSA form.
Chris Lattnerdbb61c62002-11-17 22:53:13 +0000129///
Chris Lattner300d0ed2004-02-14 06:00:36 +0000130FunctionPass *llvm::createX86CodePrinterPass(std::ostream &o,TargetMachine &tm){
Chris Lattner3fa861a2004-08-01 06:02:08 +0000131 return new X86AsmPrinter(o, tm);
Chris Lattnerdbb61c62002-11-17 22:53:13 +0000132}
133
Chris Lattner3fa861a2004-08-01 06:02:08 +0000134
135// Include the auto-generated portion of the assembly writer.
136#include "X86GenAsmWriter.inc"
137
138
Brian Gaeke92bdfe62003-07-23 18:37:06 +0000139/// printConstantPool - Print to the current output stream assembly
140/// representations of the constants in the constant pool MCP. This is
141/// used to print out constants which have been "spilled to memory" by
142/// the code generator.
143///
Chris Lattner3fa861a2004-08-01 06:02:08 +0000144void X86AsmPrinter::printConstantPool(MachineConstantPool *MCP) {
Chris Lattnerb7089442003-01-13 00:35:03 +0000145 const std::vector<Constant*> &CP = MCP->getConstants();
Brian Gaekede420ae2003-07-23 20:25:08 +0000146 const TargetData &TD = TM.getTargetData();
Brian Gaeke92bdfe62003-07-23 18:37:06 +0000147
Chris Lattnerb7089442003-01-13 00:35:03 +0000148 if (CP.empty()) return;
149
150 for (unsigned i = 0, e = CP.size(); i != e; ++i) {
151 O << "\t.section .rodata\n";
Chris Lattnerc6393f82004-08-17 19:25:42 +0000152 emitAlignment(TD.getTypeAlignmentShift(CP[i]->getType()));
153 O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t" << CommentChar
Brian Gaeked7908f62003-06-27 00:00:48 +0000154 << *CP[i] << "\n";
Chris Lattnerac662d12003-11-03 20:19:49 +0000155 emitGlobalConstant(CP[i]);
Chris Lattnerb7089442003-01-13 00:35:03 +0000156 }
Chris Lattnerb7089442003-01-13 00:35:03 +0000157}
158
Brian Gaeke92bdfe62003-07-23 18:37:06 +0000159/// runOnMachineFunction - This uses the printMachineInstruction()
160/// method to print assembly for each instruction.
161///
Chris Lattner3fa861a2004-08-01 06:02:08 +0000162bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
Chris Lattner055acae2004-08-16 23:16:06 +0000163 setupMachineFunction(MF);
Chris Lattnere0121322003-08-03 23:37:09 +0000164 O << "\n\n";
Brian Gaeked7908f62003-06-27 00:00:48 +0000165
Chris Lattnerb7089442003-01-13 00:35:03 +0000166 // Print out constants referenced by the function
Brian Gaeke01d79ff2003-06-25 18:01:07 +0000167 printConstantPool(MF.getConstantPool());
Chris Lattnerb7089442003-01-13 00:35:03 +0000168
Brian Gaeke6559bb92002-11-14 22:32:30 +0000169 // Print out labels for the function.
Chris Lattnerb7089442003-01-13 00:35:03 +0000170 O << "\t.text\n";
Chris Lattnerc6393f82004-08-17 19:25:42 +0000171 emitAlignment(4);
Brian Gaeked7908f62003-06-27 00:00:48 +0000172 O << "\t.globl\t" << CurrentFnName << "\n";
Chris Lattner055acae2004-08-16 23:16:06 +0000173 O << "\t.type\t" << CurrentFnName << ", @function\n";
Brian Gaeked7908f62003-06-27 00:00:48 +0000174 O << CurrentFnName << ":\n";
Brian Gaeke6559bb92002-11-14 22:32:30 +0000175
176 // Print out code for the function.
Chris Lattner0285a332002-12-28 20:25:38 +0000177 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
178 I != E; ++I) {
179 // Print a label for the basic block.
Chris Lattnerc6393f82004-08-17 19:25:42 +0000180 O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t"
181 << CommentChar << " " << I->getBasicBlock()->getName() << "\n";
Chris Lattner0285a332002-12-28 20:25:38 +0000182 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
Misha Brukmane8d8fb22004-06-29 19:28:53 +0000183 II != E; ++II) {
Chris Lattner0285a332002-12-28 20:25:38 +0000184 // Print the assembly for the instruction.
185 O << "\t";
Alkis Evlogimenosc0b9dc52004-02-12 02:27:10 +0000186 printMachineInstruction(II);
Brian Gaeke6559bb92002-11-14 22:32:30 +0000187 }
Chris Lattner0285a332002-12-28 20:25:38 +0000188 }
Brian Gaeke6559bb92002-11-14 22:32:30 +0000189
190 // We didn't modify anything.
Chris Lattnerb4f68ed2002-10-29 22:37:54 +0000191 return false;
192}
193
Chris Lattner3d3067b2002-11-21 20:44:15 +0000194static bool isScale(const MachineOperand &MO) {
Chris Lattnerd9096832002-12-15 08:01:39 +0000195 return MO.isImmediate() &&
Brian Gaeke01d79ff2003-06-25 18:01:07 +0000196 (MO.getImmedValue() == 1 || MO.getImmedValue() == 2 ||
197 MO.getImmedValue() == 4 || MO.getImmedValue() == 8);
Chris Lattner3d3067b2002-11-21 20:44:15 +0000198}
199
200static bool isMem(const MachineInstr *MI, unsigned Op) {
Chris Lattnerb7089442003-01-13 00:35:03 +0000201 if (MI->getOperand(Op).isFrameIndex()) return true;
202 if (MI->getOperand(Op).isConstantPoolIndex()) return true;
Chris Lattner3d3067b2002-11-21 20:44:15 +0000203 return Op+4 <= MI->getNumOperands() &&
Chris Lattner2a998bd2004-08-11 07:02:04 +0000204 MI->getOperand(Op ).isRegister() && isScale(MI->getOperand(Op+1)) &&
205 MI->getOperand(Op+2).isRegister() && MI->getOperand(Op+3).isImmediate();
Chris Lattner3d3067b2002-11-21 20:44:15 +0000206}
207
Brian Gaeke2a098772003-08-11 19:05:46 +0000208
209
Chris Lattner3fa861a2004-08-01 06:02:08 +0000210void X86AsmPrinter::printOp(const MachineOperand &MO,
211 bool elideOffsetKeyword /* = false */) {
Brian Gaekede420ae2003-07-23 20:25:08 +0000212 const MRegisterInfo &RI = *TM.getRegisterInfo();
Chris Lattnerf9f60882002-11-18 06:56:51 +0000213 switch (MO.getType()) {
214 case MachineOperand::MO_VirtualRegister:
Chris Lattnerac573f62002-12-04 17:32:52 +0000215 if (Value *V = MO.getVRegValueOrNull()) {
Chris Lattnerdbf30f72002-12-04 06:45:19 +0000216 O << "<" << V->getName() << ">";
217 return;
218 }
Chris Lattnerb7089442003-01-13 00:35:03 +0000219 // FALLTHROUGH
Misha Brukmane1f0d812002-11-20 18:56:41 +0000220 case MachineOperand::MO_MachineRegister:
Alkis Evlogimenos859a18b2004-02-15 21:37:17 +0000221 if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
Brian Gaeke2a098772003-08-11 19:05:46 +0000222 // Bug Workaround: See note in Printer::doInitialization about %.
Brian Gaeke9d99b432003-08-13 18:15:15 +0000223 O << "%" << RI.get(MO.getReg()).Name;
224 else
Chris Lattnerf9f60882002-11-18 06:56:51 +0000225 O << "%reg" << MO.getReg();
226 return;
Chris Lattner77875d82002-11-21 02:00:20 +0000227
228 case MachineOperand::MO_SignExtendedImmed:
229 case MachineOperand::MO_UnextendedImmed:
230 O << (int)MO.getImmedValue();
231 return;
Brian Gaeke3fb5d1a2004-05-14 06:54:57 +0000232 case MachineOperand::MO_MachineBasicBlock: {
233 MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
234 O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
235 << "_" << MBBOp->getNumber () << "\t# "
236 << MBBOp->getBasicBlock ()->getName ();
Chris Lattnerf8bafe82002-12-01 23:25:59 +0000237 return;
Chris Lattnerad200712003-09-09 16:23:36 +0000238 }
Brian Gaeke3fb5d1a2004-05-14 06:54:57 +0000239 case MachineOperand::MO_PCRelativeDisp:
240 std::cerr << "Shouldn't use addPCDisp() when building X86 MachineInstrs";
241 abort ();
242 return;
Chris Lattnerb7089442003-01-13 00:35:03 +0000243 case MachineOperand::MO_GlobalAddress:
Brian Gaeke002a50a2003-07-31 17:38:52 +0000244 if (!elideOffsetKeyword)
245 O << "OFFSET ";
246 O << Mang->getValueName(MO.getGlobal());
Chris Lattnerb7089442003-01-13 00:35:03 +0000247 return;
248 case MachineOperand::MO_ExternalSymbol:
Brian Gaeke9e474c42003-06-19 19:32:32 +0000249 O << MO.getSymbolName();
Chris Lattnerb7089442003-01-13 00:35:03 +0000250 return;
Chris Lattnerf9f60882002-11-18 06:56:51 +0000251 default:
Brian Gaeke01d79ff2003-06-25 18:01:07 +0000252 O << "<unknown operand type>"; return;
Chris Lattnerf9f60882002-11-18 06:56:51 +0000253 }
254}
255
Chris Lattner3fa861a2004-08-01 06:02:08 +0000256void X86AsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op) {
Chris Lattner3d3067b2002-11-21 20:44:15 +0000257 assert(isMem(MI, Op) && "Invalid memory reference!");
Chris Lattnerb7089442003-01-13 00:35:03 +0000258
259 if (MI->getOperand(Op).isFrameIndex()) {
260 O << "[frame slot #" << MI->getOperand(Op).getFrameIndex();
261 if (MI->getOperand(Op+3).getImmedValue())
262 O << " + " << MI->getOperand(Op+3).getImmedValue();
263 O << "]";
264 return;
265 } else if (MI->getOperand(Op).isConstantPoolIndex()) {
Brian Gaeked7908f62003-06-27 00:00:48 +0000266 O << "[.CPI" << CurrentFnName << "_"
Brian Gaeke5e001572003-06-26 18:02:30 +0000267 << MI->getOperand(Op).getConstantPoolIndex();
Chris Lattnerb7089442003-01-13 00:35:03 +0000268 if (MI->getOperand(Op+3).getImmedValue())
269 O << " + " << MI->getOperand(Op+3).getImmedValue();
270 O << "]";
271 return;
272 }
273
Chris Lattner3d3067b2002-11-21 20:44:15 +0000274 const MachineOperand &BaseReg = MI->getOperand(Op);
Chris Lattner0285a332002-12-28 20:25:38 +0000275 int ScaleVal = MI->getOperand(Op+1).getImmedValue();
Chris Lattner3d3067b2002-11-21 20:44:15 +0000276 const MachineOperand &IndexReg = MI->getOperand(Op+2);
Chris Lattner0285a332002-12-28 20:25:38 +0000277 int DispVal = MI->getOperand(Op+3).getImmedValue();
Chris Lattner3d3067b2002-11-21 20:44:15 +0000278
279 O << "[";
280 bool NeedPlus = false;
281 if (BaseReg.getReg()) {
Brian Gaekede420ae2003-07-23 20:25:08 +0000282 printOp(BaseReg);
Chris Lattner3d3067b2002-11-21 20:44:15 +0000283 NeedPlus = true;
284 }
285
286 if (IndexReg.getReg()) {
287 if (NeedPlus) O << " + ";
Chris Lattner0285a332002-12-28 20:25:38 +0000288 if (ScaleVal != 1)
289 O << ScaleVal << "*";
Brian Gaekede420ae2003-07-23 20:25:08 +0000290 printOp(IndexReg);
Chris Lattner3d3067b2002-11-21 20:44:15 +0000291 NeedPlus = true;
292 }
293
Chris Lattner0285a332002-12-28 20:25:38 +0000294 if (DispVal) {
295 if (NeedPlus)
296 if (DispVal > 0)
Misha Brukmane8d8fb22004-06-29 19:28:53 +0000297 O << " + ";
Chris Lattner0285a332002-12-28 20:25:38 +0000298 else {
Misha Brukmane8d8fb22004-06-29 19:28:53 +0000299 O << " - ";
300 DispVal = -DispVal;
Chris Lattner0285a332002-12-28 20:25:38 +0000301 }
302 O << DispVal;
Chris Lattner3d3067b2002-11-21 20:44:15 +0000303 }
304 O << "]";
305}
306
John Criswell4ffff9e2004-04-08 20:31:47 +0000307
Brian Gaeke92bdfe62003-07-23 18:37:06 +0000308/// printMachineInstruction -- Print out a single X86 LLVM instruction
Brian Gaekede420ae2003-07-23 20:25:08 +0000309/// MI in Intel syntax to the current output stream.
Brian Gaeked7908f62003-06-27 00:00:48 +0000310///
Chris Lattner3fa861a2004-08-01 06:02:08 +0000311void X86AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
312 ++EmittedInsts;
Chris Lattner85494292004-08-11 06:09:55 +0000313
314 // gas bugs:
315 //
316 // The 80-bit FP store-pop instruction "fstp XWORD PTR [...]" is misassembled
317 // by gas in intel_syntax mode as its 32-bit equivalent "fstp DWORD PTR
318 // [...]". Workaround: Output the raw opcode bytes instead of the instruction.
319 //
320 // The 80-bit FP load instruction "fld XWORD PTR [...]" is misassembled by gas
321 // in intel_syntax mode as its 32-bit equivalent "fld DWORD PTR
322 // [...]". Workaround: Output the raw opcode bytes instead of the instruction.
323 //
324 // gas intel_syntax mode treats "fild QWORD PTR [...]" as an invalid opcode,
325 // saying "64 bit operations are only supported in 64 bit modes." libopcodes
326 // disassembles it as "fild DWORD PTR [...]", which is wrong. Workaround:
327 // Output the raw opcode bytes instead of the instruction.
328 //
329 // gas intel_syntax mode treats "fistp QWORD PTR [...]" as an invalid opcode,
330 // saying "64 bit operations are only supported in 64 bit modes." libopcodes
331 // disassembles it as "fistpll DWORD PTR [...]", which is wrong. Workaround:
332 // Output the raw opcode bytes instead of the instruction.
333 switch (MI->getOpcode()) {
334 case X86::FSTP80m:
335 case X86::FLD80m:
336 case X86::FILD64m:
337 case X86::FISTP64m:
338 GasBugWorkaroundEmitter gwe(O);
339 X86::emitInstruction(gwe, (X86InstrInfo&)*TM.getInstrInfo(), *MI);
340 O << "\t# ";
341 }
342
Chris Lattner2a998bd2004-08-11 07:02:04 +0000343 // Call the autogenerated instruction printer routines.
344 bool Handled = printInstruction(MI);
345 if (!Handled) {
346 MI->dump();
347 assert(0 && "Do not know how to print this instruction!");
348 abort();
Chris Lattnerf9f60882002-11-18 06:56:51 +0000349 }
Chris Lattner72614082002-10-25 22:55:53 +0000350}
Brian Gaeke9e474c42003-06-19 19:32:32 +0000351
Chris Lattner3fa861a2004-08-01 06:02:08 +0000352bool X86AsmPrinter::doInitialization(Module &M) {
Chris Lattner055acae2004-08-16 23:16:06 +0000353 AsmPrinter::doInitialization(M);
Chris Lattner93c1afa2003-08-11 19:35:26 +0000354 // Tell gas we are outputting Intel syntax (not AT&T syntax) assembly.
Brian Gaeke2a098772003-08-11 19:05:46 +0000355 //
Chris Lattner93c1afa2003-08-11 19:35:26 +0000356 // Bug: gas in `intel_syntax noprefix' mode interprets the symbol `Sp' in an
357 // instruction as a reference to the register named sp, and if you try to
358 // reference a symbol `Sp' (e.g. `mov ECX, OFFSET Sp') then it gets lowercased
359 // before being looked up in the symbol table. This creates spurious
360 // `undefined symbol' errors when linking. Workaround: Do not use `noprefix'
361 // mode, and decorate all register names with percent signs.
Chris Lattner67488a92003-08-11 20:04:57 +0000362 O << "\t.intel_syntax\n";
Chris Lattner055acae2004-08-16 23:16:06 +0000363 return false;
Brian Gaeke9e474c42003-06-19 19:32:32 +0000364}
365
Chris Lattnerad200712003-09-09 16:23:36 +0000366// SwitchSection - Switch to the specified section of the executable if we are
367// not already in it!
368//
369static void SwitchSection(std::ostream &OS, std::string &CurSection,
370 const char *NewSection) {
371 if (CurSection != NewSection) {
372 CurSection = NewSection;
373 if (!CurSection.empty())
374 OS << "\t" << NewSection << "\n";
375 }
Brian Gaeke0517c5a2003-07-11 21:57:01 +0000376}
377
Chris Lattner3fa861a2004-08-01 06:02:08 +0000378bool X86AsmPrinter::doFinalization(Module &M) {
Brian Gaekede420ae2003-07-23 20:25:08 +0000379 const TargetData &TD = TM.getTargetData();
Chris Lattnerad200712003-09-09 16:23:36 +0000380 std::string CurSection;
381
Brian Gaeke01d79ff2003-06-25 18:01:07 +0000382 // Print out module-level global variables here.
Chris Lattnerad200712003-09-09 16:23:36 +0000383 for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
384 if (I->hasInitializer()) { // External global require no code
385 O << "\n\n";
386 std::string name = Mang->getValueName(I);
Brian Gaeke01d79ff2003-06-25 18:01:07 +0000387 Constant *C = I->getInitializer();
Chris Lattnerad200712003-09-09 16:23:36 +0000388 unsigned Size = TD.getTypeSize(C->getType());
Chris Lattnerc6393f82004-08-17 19:25:42 +0000389 unsigned Align = TD.getTypeAlignmentShift(C->getType());
Chris Lattnerad200712003-09-09 16:23:36 +0000390
391 if (C->isNullValue() &&
Chris Lattner72ac148d2003-10-16 18:29:00 +0000392 (I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
393 I->hasWeakLinkage() /* FIXME: Verify correct */)) {
Chris Lattnerad200712003-09-09 16:23:36 +0000394 SwitchSection(O, CurSection, ".data");
395 if (I->hasInternalLinkage())
396 O << "\t.local " << name << "\n";
397
398 O << "\t.comm " << name << "," << TD.getTypeSize(C->getType())
Chris Lattnerc6393f82004-08-17 19:25:42 +0000399 << "," << (1 << Align);
Chris Lattnere0121322003-08-03 23:37:09 +0000400 O << "\t\t# ";
401 WriteAsOperand(O, I, true, true, &M);
402 O << "\n";
Brian Gaeke0517c5a2003-07-11 21:57:01 +0000403 } else {
Chris Lattnerad200712003-09-09 16:23:36 +0000404 switch (I->getLinkage()) {
405 case GlobalValue::LinkOnceLinkage:
Chris Lattner72ac148d2003-10-16 18:29:00 +0000406 case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
Chris Lattnerad200712003-09-09 16:23:36 +0000407 // Nonnull linkonce -> weak
408 O << "\t.weak " << name << "\n";
409 SwitchSection(O, CurSection, "");
410 O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
411 break;
Chris Lattnerad200712003-09-09 16:23:36 +0000412 case GlobalValue::AppendingLinkage:
413 // FIXME: appending linkage variables should go into a section of
414 // their name or something. For now, just emit them as external.
415 case GlobalValue::ExternalLinkage:
416 // If external or appending, declare as a global symbol
417 O << "\t.globl " << name << "\n";
418 // FALL THROUGH
419 case GlobalValue::InternalLinkage:
420 if (C->isNullValue())
421 SwitchSection(O, CurSection, ".bss");
422 else
423 SwitchSection(O, CurSection, ".data");
424 break;
425 }
426
Chris Lattnerc6393f82004-08-17 19:25:42 +0000427 emitAlignment(Align);
Chris Lattnere0121322003-08-03 23:37:09 +0000428 O << "\t.type " << name << ",@object\n";
Chris Lattnerad200712003-09-09 16:23:36 +0000429 O << "\t.size " << name << "," << Size << "\n";
Chris Lattnere0121322003-08-03 23:37:09 +0000430 O << name << ":\t\t\t\t# ";
431 WriteAsOperand(O, I, true, true, &M);
432 O << " = ";
433 WriteAsOperand(O, C, false, false, &M);
434 O << "\n";
Chris Lattnerac662d12003-11-03 20:19:49 +0000435 emitGlobalConstant(C);
Brian Gaeke0517c5a2003-07-11 21:57:01 +0000436 }
Brian Gaeke01d79ff2003-06-25 18:01:07 +0000437 }
Chris Lattnerad200712003-09-09 16:23:36 +0000438
Chris Lattner055acae2004-08-16 23:16:06 +0000439 AsmPrinter::doFinalization(M);
Brian Gaeke9e474c42003-06-19 19:32:32 +0000440 return false; // success
441}