From b36cbd0286cf008987737dbcc3b788af902d414b Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 1 Jul 2005 22:44:09 +0000 Subject: [PATCH] Refactor X86AsmPrinter.cpp into multiple files. Patch contributed by Aaron Gray, cleaned up by me. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22324 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ATTAsmPrinter.cpp | 171 +++++++++ lib/Target/X86/X86ATTAsmPrinter.h | 61 ++++ lib/Target/X86/X86AsmPrinter.cpp | 646 +++++----------------------------- lib/Target/X86/X86AsmPrinter.h | 69 ++++ lib/Target/X86/X86IntelAsmPrinter.cpp | 205 +++++++++++ lib/Target/X86/X86IntelAsmPrinter.h | 81 +++++ 6 files changed, 676 insertions(+), 557 deletions(-) create mode 100755 lib/Target/X86/X86ATTAsmPrinter.cpp create mode 100755 lib/Target/X86/X86ATTAsmPrinter.h create mode 100755 lib/Target/X86/X86AsmPrinter.h create mode 100755 lib/Target/X86/X86IntelAsmPrinter.cpp create mode 100755 lib/Target/X86/X86IntelAsmPrinter.h diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp new file mode 100755 index 00000000000..a7e6729141d --- /dev/null +++ b/lib/Target/X86/X86ATTAsmPrinter.cpp @@ -0,0 +1,171 @@ +//===-- X86ATTAsmPrinter.cpp - Convert X86 LLVM code to Intel assembly ----===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to AT&T format assembly +// language. This printer is the output mechanism used by `llc'. +// +//===----------------------------------------------------------------------===// + +#include "X86ATTAsmPrinter.h" +#include "X86.h" +#include "X86TargetMachine.h" +#include "llvm/Module.h" +#include "llvm/Support/Mangler.h" +using namespace llvm; +using namespace x86; + +/// runOnMachineFunction - This uses the printMachineInstruction() +/// method to print assembly for each instruction. +/// +bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + setupMachineFunction(MF); + O << "\n\n"; + + // Print out constants referenced by the function + printConstantPool(MF.getConstantPool()); + + // Print out labels for the function. + O << "\t.text\n"; + emitAlignment(4); + O << "\t.globl\t" << CurrentFnName << "\n"; + if (!forCygwin && !forDarwin) + O << "\t.type\t" << CurrentFnName << ", @function\n"; + O << CurrentFnName << ":\n"; + + // Print out code for the function. + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + // Print a label for the basic block. + if (I->pred_begin() != I->pred_end()) + O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t" + << CommentString << " " << I->getBasicBlock()->getName() << "\n"; + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) { + // Print the assembly for the instruction. + O << "\t"; + printMachineInstruction(II); + } + } + + // We didn't modify anything. + return false; +} + +void X86ATTAsmPrinter::printOp(const MachineOperand &MO, bool isCallOp) { + const MRegisterInfo &RI = *TM.getRegisterInfo(); + switch (MO.getType()) { + case MachineOperand::MO_VirtualRegister: + case MachineOperand::MO_MachineRegister: + assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) && + "Virtual registers should not make it this far!"); + O << '%'; + for (const char *Name = RI.get(MO.getReg()).Name; *Name; ++Name) + O << (char)tolower(*Name); + return; + + case MachineOperand::MO_SignExtendedImmed: + case MachineOperand::MO_UnextendedImmed: + O << '$' << (int)MO.getImmedValue(); + return; + case MachineOperand::MO_MachineBasicBlock: { + MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); + O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction()) + << "_" << MBBOp->getNumber () << "\t# " + << MBBOp->getBasicBlock ()->getName (); + return; + } + case MachineOperand::MO_PCRelativeDisp: + std::cerr << "Shouldn't use addPCDisp() when building X86 MachineInstrs"; + abort (); + return; + case MachineOperand::MO_GlobalAddress: { + if (!isCallOp) O << '$'; + O << Mang->getValueName(MO.getGlobal()); + int Offset = MO.getOffset(); + if (Offset > 0) + O << "+" << Offset; + else if (Offset < 0) + O << Offset; + return; + } + case MachineOperand::MO_ExternalSymbol: + if (!isCallOp) O << '$'; + O << GlobalPrefix << MO.getSymbolName(); + return; + default: + O << ""; return; + } +} + +void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){ + assert(isMem(MI, Op) && "Invalid memory reference!"); + + const MachineOperand &BaseReg = MI->getOperand(Op); + int ScaleVal = MI->getOperand(Op+1).getImmedValue(); + const MachineOperand &IndexReg = MI->getOperand(Op+2); + const MachineOperand &DispSpec = MI->getOperand(Op+3); + + if (BaseReg.isFrameIndex()) { + O << "[frame slot #" << BaseReg.getFrameIndex(); + if (DispSpec.getImmedValue()) + O << " + " << DispSpec.getImmedValue(); + O << "]"; + return; + } else if (BaseReg.isConstantPoolIndex()) { + O << ".CPI" << CurrentFnName << "_" + << BaseReg.getConstantPoolIndex(); + if (DispSpec.getImmedValue()) + O << "+" << DispSpec.getImmedValue(); + if (IndexReg.getReg()) { + O << "(,"; + printOp(IndexReg); + if (ScaleVal != 1) + O << "," << ScaleVal; + O << ")"; + } + return; + } + + if (DispSpec.isGlobalAddress()) { + printOp(DispSpec, true); + } else { + int DispVal = DispSpec.getImmedValue(); + if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) + O << DispVal; + } + + if (IndexReg.getReg() || BaseReg.getReg()) { + O << "("; + if (BaseReg.getReg()) + printOp(BaseReg); + + if (IndexReg.getReg()) { + O << ","; + printOp(IndexReg); + if (ScaleVal != 1) + O << "," << ScaleVal; + } + + O << ")"; + } +} + +/// printMachineInstruction -- Print out a single X86 LLVM instruction +/// MI in Intel syntax to the current output stream. +/// +void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) { + ++EmittedInsts; + // Call the autogenerated instruction printer routines. + printInstruction(MI); +} + +// Include the auto-generated portion of the assembly writer. +#include "X86GenAsmWriter.inc" + diff --git a/lib/Target/X86/X86ATTAsmPrinter.h b/lib/Target/X86/X86ATTAsmPrinter.h new file mode 100755 index 00000000000..ee91e8e0659 --- /dev/null +++ b/lib/Target/X86/X86ATTAsmPrinter.h @@ -0,0 +1,61 @@ +//===-- X86ATTAsmPrinter.h - Convert X86 LLVM code to Intel assembly ------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// AT&T assembly code printer class. +// +//===----------------------------------------------------------------------===// + +#ifndef X86ATTASMPRINTER_H +#define X86ATTASMPRINTER_H + +#include "X86AsmPrinter.h" +#include "llvm/CodeGen/ValueTypes.h" + +namespace llvm { +namespace x86 { + +struct X86ATTAsmPrinter : public X86SharedAsmPrinter { + X86ATTAsmPrinter(std::ostream &O, TargetMachine &TM) + : X86SharedAsmPrinter(O, TM) { } + + virtual const char *getPassName() const { + return "X86 AT&T-Style Assembly Printer"; + } + + /// printInstruction - This method is automatically generated by tablegen + /// from the instruction set description. This method returns true if the + /// machine instruction was sufficiently described to print it, otherwise it + /// returns false. + bool printInstruction(const MachineInstr *MI); + + // This method is used by the tablegen'erated instruction printer. + void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){ + printOp(MI->getOperand(OpNo)); + } + + void printCallOperand(const MachineInstr *MI, unsigned OpNo, + MVT::ValueType VT) { + printOp(MI->getOperand(OpNo), true); // Don't print '$' prefix. + } + + void printMemoryOperand(const MachineInstr *MI, unsigned OpNo, + MVT::ValueType VT) { + printMemReference(MI, OpNo); + } + + void printMachineInstruction(const MachineInstr *MI); + void printOp(const MachineOperand &MO, bool isCallOperand = false); + void printMemReference(const MachineInstr *MI, unsigned Op); + bool runOnMachineFunction(MachineFunction &F); +}; + +} // end namespace x86 +} // end namespace llvm + +#endif diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp index bcc0a0cb5d4..a5b82b5a77e 100644 --- a/lib/Target/X86/X86AsmPrinter.cpp +++ b/lib/Target/X86/X86AsmPrinter.cpp @@ -1,4 +1,4 @@ -//===-- X86AsmPrinter.cpp - Convert X86 LLVM code to Intel assembly -------===// +//===-- X86AsmPrinter.cpp - Convert X86 LLVM IR to X86 assembly -----------===// // // The LLVM Compiler Infrastructure // @@ -7,98 +7,62 @@ // //===----------------------------------------------------------------------===// // -// This file contains a printer that converts from our internal representation -// of machine-dependent LLVM code to Intel and AT&T format assembly -// language. This printer is the output mechanism used by `llc' and `lli -// -print-machineinstrs' on X86. +// This file the shared super class printer that converts from our internal +// representation of machine-dependent LLVM code to Intel and AT&T format +// assembly language. +// This printer is the output mechanism used by `llc'. // //===----------------------------------------------------------------------===// +#include "X86ATTAsmPrinter.h" +#include "X86IntelAsmPrinter.h" #include "X86.h" -#include "X86TargetMachine.h" #include "llvm/Module.h" -#include "llvm/Type.h" #include "llvm/Assembly/Writer.h" -#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/Target/TargetMachine.h" #include "llvm/Support/Mangler.h" -#include "llvm/ADT/Statistic.h" #include "llvm/Support/CommandLine.h" using namespace llvm; +using namespace x86; -namespace { - Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed"); - enum AsmWriterFlavor { att, intel }; +Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed"); - cl::opt - AsmWriterFlavor("x86-asm-syntax", - cl::desc("Choose style of code to emit from X86 backend:"), - cl::values( - clEnumVal(att, " Emit AT&T-style assembly"), - clEnumVal(intel, " Emit Intel-style assembly"), - clEnumValEnd), - cl::init(att)); +enum AsmWriterFlavorTy { att, intel }; +cl::opt +AsmWriterFlavor("x86-asm-syntax", + cl::desc("Choose style of code to emit from X86 backend:"), + cl::values( + clEnumVal(att, " Emit AT&T-style assembly"), + clEnumVal(intel, " Emit Intel-style assembly"), + clEnumValEnd), + cl::init(att)); - struct X86SharedAsmPrinter : public AsmPrinter { - X86SharedAsmPrinter(std::ostream &O, TargetMachine &TM) - : AsmPrinter(O, TM), forCygwin(false), forDarwin(false) { } - - bool doInitialization(Module &M); - void printConstantPool(MachineConstantPool *MCP); - bool doFinalization(Module &M); - bool forCygwin; - bool forDarwin; - }; -} - -static bool isScale(const MachineOperand &MO) { - return MO.isImmediate() && - (MO.getImmedValue() == 1 || MO.getImmedValue() == 2 || - MO.getImmedValue() == 4 || MO.getImmedValue() == 8); -} - -static bool isMem(const MachineInstr *MI, unsigned Op) { - if (MI->getOperand(Op).isFrameIndex()) return true; - if (MI->getOperand(Op).isConstantPoolIndex()) return true; - return Op+4 <= MI->getNumOperands() && - MI->getOperand(Op ).isRegister() && isScale(MI->getOperand(Op+1)) && - MI->getOperand(Op+2).isRegister() && (MI->getOperand(Op+3).isImmediate() || - MI->getOperand(Op+3).isGlobalAddress()); -} - -// SwitchSection - Switch to the specified section of the executable if we are -// not already in it! -// -static void SwitchSection(std::ostream &OS, std::string &CurSection, - const char *NewSection) { - if (CurSection != NewSection) { - CurSection = NewSection; - if (!CurSection.empty()) - OS << "\t" << NewSection << "\n"; - } -} - -/// doInitialization - determine +/// doInitialization bool X86SharedAsmPrinter::doInitialization(Module& M) { + bool leadingUnderscore = false; + forCygwin = false; const std::string& TT = M.getTargetTriple(); if (TT.length() > 5) { forCygwin = TT.find("cygwin") != std::string::npos || TT.find("mingw") != std::string::npos; forDarwin = TT.find("darwin") != std::string::npos; } else if (TT.empty()) { -#if defined(__CYGWIN__) || defined(__MINGW32__) + #if defined(__CYGWIN__) || defined(__MINGW32__) forCygwin = true; -#elif defined(__MACOSX__) + #elif defined(__MACOSX__) forDarwin = true; -#endif + #elif defined(_WIN32) + leadingUnderscore = true; + #else + leadingUnderscore = false; + #endif } - if (forCygwin || forDarwin) + if (leadingUnderscore || forCygwin || forDarwin) GlobalPrefix = "_"; + if (forDarwin) AlignmentIsInBytes = false; + return AsmPrinter::doInitialization(M); } @@ -128,502 +92,70 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) { // Print out module-level global variables here. for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) - if (I->hasInitializer()) { // External global require no code - O << "\n\n"; - std::string name = Mang->getValueName(I); - Constant *C = I->getInitializer(); - unsigned Size = TD.getTypeSize(C->getType()); - unsigned Align = TD.getTypeAlignmentShift(C->getType()); - - if (C->isNullValue() && - (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || - I->hasWeakLinkage() /* FIXME: Verify correct */)) { - SwitchSection(O, CurSection, ".data"); - if (!forCygwin && I->hasInternalLinkage()) - O << "\t.local " << name << "\n"; - - O << "\t.comm " << name << "," << TD.getTypeSize(C->getType()); - if (!forCygwin) - O << "," << (1 << Align); - O << "\t\t# "; - WriteAsOperand(O, I, true, true, &M); - O << "\n"; - } else { - switch (I->getLinkage()) { - case GlobalValue::LinkOnceLinkage: - case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. - // Nonnull linkonce -> weak - O << "\t.weak " << name << "\n"; - SwitchSection(O, CurSection, ""); - O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"; - break; - case GlobalValue::AppendingLinkage: - // FIXME: appending linkage variables should go into a section of - // their name or something. For now, just emit them as external. - case GlobalValue::ExternalLinkage: - // If external or appending, declare as a global symbol - O << "\t.globl " << name << "\n"; - // FALL THROUGH - case GlobalValue::InternalLinkage: - if (C->isNullValue()) - SwitchSection(O, CurSection, ".bss"); - else - SwitchSection(O, CurSection, ".data"); - break; - case GlobalValue::GhostLinkage: - std::cerr << "GhostLinkage cannot appear in X86AsmPrinter!\n"; - abort(); - } - - emitAlignment(Align); - if (!forCygwin && !forDarwin) { - O << "\t.type " << name << ",@object\n"; - O << "\t.size " << name << "," << Size << "\n"; - } - O << name << ":\t\t\t\t# "; - WriteAsOperand(O, I, true, true, &M); - O << " = "; - WriteAsOperand(O, C, false, false, &M); - O << "\n"; - emitGlobalConstant(C); - } + if (I->hasInitializer()) { // External global require no code + O << "\n\n"; + std::string name = Mang->getValueName(I); + Constant *C = I->getInitializer(); + unsigned Size = TD.getTypeSize(C->getType()); + unsigned Align = TD.getTypeAlignmentShift(C->getType()); + + if (C->isNullValue() && + (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || + I->hasWeakLinkage() /* FIXME: Verify correct */)) { + SwitchSection(O, CurSection, ".data"); + if (!forCygwin && I->hasInternalLinkage()) + O << "\t.local " << name << "\n"; + O << "\t.comm " << name << "," << TD.getTypeSize(C->getType()); + if (!forCygwin) + O << "," << (1 << Align); + O << "\t\t# "; + WriteAsOperand(O, I, true, true, &M); + O << "\n"; + } else { + switch (I->getLinkage()) { + case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. + // Nonnull linkonce -> weak + O << "\t.weak " << name << "\n"; + SwitchSection(O, CurSection, ""); + O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"; + break; + case GlobalValue::AppendingLinkage: + // FIXME: appending linkage variables should go into a section of + // their name or something. For now, just emit them as external. + case GlobalValue::ExternalLinkage: + // If external or appending, declare as a global symbol + O << "\t.globl " << name << "\n"; + // FALL THROUGH + case GlobalValue::InternalLinkage: + if (C->isNullValue()) + SwitchSection(O, CurSection, ".bss"); + else + SwitchSection(O, CurSection, ".data"); + break; + case GlobalValue::GhostLinkage: + std::cerr << "GhostLinkage cannot appear in X86AsmPrinter!\n"; + abort(); + } + + emitAlignment(Align); + if (!forCygwin && !forDarwin) { + O << "\t.type " << name << ",@object\n"; + O << "\t.size " << name << "," << Size << "\n"; + } + O << name << ":\t\t\t\t# "; + WriteAsOperand(O, I, true, true, &M); + O << " = "; + WriteAsOperand(O, C, false, false, &M); + O << "\n"; + emitGlobalConstant(C); + } } AsmPrinter::doFinalization(M); return false; // success } -namespace { - struct X86IntelAsmPrinter : public X86SharedAsmPrinter { - X86IntelAsmPrinter(std::ostream &O, TargetMachine &TM) - : X86SharedAsmPrinter(O, TM) { } - - virtual const char *getPassName() const { - return "X86 Intel-Style Assembly Printer"; - } - - /// printInstruction - This method is automatically generated by tablegen - /// from the instruction set description. This method returns true if the - /// machine instruction was sufficiently described to print it, otherwise it - /// returns false. - bool printInstruction(const MachineInstr *MI); - - // This method is used by the tablegen'erated instruction printer. - void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){ - const MachineOperand &MO = MI->getOperand(OpNo); - if (MO.getType() == MachineOperand::MO_MachineRegister) { - assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physref??"); - // Bug Workaround: See note in Printer::doInitialization about %. - O << "%" << TM.getRegisterInfo()->get(MO.getReg()).Name; - } else { - printOp(MO); - } - } - - void printCallOperand(const MachineInstr *MI, unsigned OpNo, - MVT::ValueType VT) { - printOp(MI->getOperand(OpNo), true); // Don't print "OFFSET". - } - - void printMemoryOperand(const MachineInstr *MI, unsigned OpNo, - MVT::ValueType VT) { - switch (VT) { - default: assert(0 && "Unknown arg size!"); - case MVT::i8: O << "BYTE PTR "; break; - case MVT::i16: O << "WORD PTR "; break; - case MVT::i32: - case MVT::f32: O << "DWORD PTR "; break; - case MVT::i64: - case MVT::f64: O << "QWORD PTR "; break; - case MVT::f80: O << "XWORD PTR "; break; - } - printMemReference(MI, OpNo); - } - - void printMachineInstruction(const MachineInstr *MI); - void printOp(const MachineOperand &MO, bool elideOffsetKeyword = false); - void printMemReference(const MachineInstr *MI, unsigned Op); - bool runOnMachineFunction(MachineFunction &F); - bool doInitialization(Module &M); - }; -} // end of anonymous namespace - - -// Include the auto-generated portion of the assembly writer. -#include "X86GenAsmWriter1.inc" - - -/// runOnMachineFunction - This uses the printMachineInstruction() -/// method to print assembly for each instruction. -/// -bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) { - setupMachineFunction(MF); - O << "\n\n"; - - // Print out constants referenced by the function - printConstantPool(MF.getConstantPool()); - - // Print out labels for the function. - O << "\t.text\n"; - emitAlignment(4); - O << "\t.globl\t" << CurrentFnName << "\n"; - if (!forCygwin && !forDarwin) - O << "\t.type\t" << CurrentFnName << ", @function\n"; - O << CurrentFnName << ":\n"; - - // Print out code for the function. - for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); - I != E; ++I) { - // Print a label for the basic block if there are any predecessors. - if (I->pred_begin() != I->pred_end()) - O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t" - << CommentString << " " << I->getBasicBlock()->getName() << "\n"; - for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); - II != E; ++II) { - // Print the assembly for the instruction. - O << "\t"; - printMachineInstruction(II); - } - } - - // We didn't modify anything. - return false; -} - -void X86IntelAsmPrinter::printOp(const MachineOperand &MO, - bool elideOffsetKeyword /* = false */) { - const MRegisterInfo &RI = *TM.getRegisterInfo(); - switch (MO.getType()) { - case MachineOperand::MO_VirtualRegister: - if (Value *V = MO.getVRegValueOrNull()) { - O << "<" << V->getName() << ">"; - return; - } - // FALLTHROUGH - case MachineOperand::MO_MachineRegister: - if (MRegisterInfo::isPhysicalRegister(MO.getReg())) - // Bug Workaround: See note in Printer::doInitialization about %. - O << "%" << RI.get(MO.getReg()).Name; - else - O << "%reg" << MO.getReg(); - return; - - case MachineOperand::MO_SignExtendedImmed: - case MachineOperand::MO_UnextendedImmed: - O << (int)MO.getImmedValue(); - return; - case MachineOperand::MO_MachineBasicBlock: { - MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); - O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction()) - << "_" << MBBOp->getNumber () << '\t' << CommentString - << MBBOp->getBasicBlock ()->getName (); - return; - } - case MachineOperand::MO_PCRelativeDisp: - std::cerr << "Shouldn't use addPCDisp() when building X86 MachineInstrs"; - abort (); - return; - case MachineOperand::MO_GlobalAddress: { - if (!elideOffsetKeyword) - O << "OFFSET "; - O << Mang->getValueName(MO.getGlobal()); - int Offset = MO.getOffset(); - if (Offset > 0) - O << " + " << Offset; - else if (Offset < 0) - O << " - " << -Offset; - return; - } - case MachineOperand::MO_ExternalSymbol: - O << GlobalPrefix << MO.getSymbolName(); - return; - default: - O << ""; return; - } -} - -void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){ - assert(isMem(MI, Op) && "Invalid memory reference!"); - - const MachineOperand &BaseReg = MI->getOperand(Op); - int ScaleVal = MI->getOperand(Op+1).getImmedValue(); - const MachineOperand &IndexReg = MI->getOperand(Op+2); - const MachineOperand &DispSpec = MI->getOperand(Op+3); - - if (BaseReg.isFrameIndex()) { - O << "[frame slot #" << BaseReg.getFrameIndex(); - if (DispSpec.getImmedValue()) - O << " + " << DispSpec.getImmedValue(); - O << "]"; - return; - } else if (BaseReg.isConstantPoolIndex()) { - O << "[.CPI" << CurrentFnName << "_" - << BaseReg.getConstantPoolIndex(); - - if (IndexReg.getReg()) { - O << " + "; - if (ScaleVal != 1) - O << ScaleVal << "*"; - printOp(IndexReg); - } - - if (DispSpec.getImmedValue()) - O << " + " << DispSpec.getImmedValue(); - O << "]"; - return; - } - - O << "["; - bool NeedPlus = false; - if (BaseReg.getReg()) { - printOp(BaseReg, true); - NeedPlus = true; - } - - if (IndexReg.getReg()) { - if (NeedPlus) O << " + "; - if (ScaleVal != 1) - O << ScaleVal << "*"; - printOp(IndexReg); - NeedPlus = true; - } - - if (DispSpec.isGlobalAddress()) { - if (NeedPlus) - O << " + "; - printOp(DispSpec, true); - } else { - int DispVal = DispSpec.getImmedValue(); - if (DispVal || (!BaseReg.getReg() && !IndexReg.getReg())) { - if (NeedPlus) - if (DispVal > 0) - O << " + "; - else { - O << " - "; - DispVal = -DispVal; - } - O << DispVal; - } - } - O << "]"; -} - - -/// printMachineInstruction -- Print out a single X86 LLVM instruction -/// MI in Intel syntax to the current output stream. -/// -void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) { - ++EmittedInsts; - - // Call the autogenerated instruction printer routines. - printInstruction(MI); -} - -bool X86IntelAsmPrinter::doInitialization(Module &M) { - AsmPrinter::doInitialization(M); - // Tell gas we are outputting Intel syntax (not AT&T syntax) assembly. - // - // Bug: gas in `intel_syntax noprefix' mode interprets the symbol `Sp' in an - // instruction as a reference to the register named sp, and if you try to - // reference a symbol `Sp' (e.g. `mov ECX, OFFSET Sp') then it gets lowercased - // before being looked up in the symbol table. This creates spurious - // `undefined symbol' errors when linking. Workaround: Do not use `noprefix' - // mode, and decorate all register names with percent signs. - O << "\t.intel_syntax\n"; - return false; -} - - - -namespace { - struct X86ATTAsmPrinter : public X86SharedAsmPrinter { - X86ATTAsmPrinter(std::ostream &O, TargetMachine &TM) - : X86SharedAsmPrinter(O, TM) { } - - virtual const char *getPassName() const { - return "X86 AT&T-Style Assembly Printer"; - } - - /// printInstruction - This method is automatically generated by tablegen - /// from the instruction set description. This method returns true if the - /// machine instruction was sufficiently described to print it, otherwise it - /// returns false. - bool printInstruction(const MachineInstr *MI); - - // This method is used by the tablegen'erated instruction printer. - void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){ - printOp(MI->getOperand(OpNo)); - } - - void printCallOperand(const MachineInstr *MI, unsigned OpNo, - MVT::ValueType VT) { - printOp(MI->getOperand(OpNo), true); // Don't print '$' prefix. - } - - void printMemoryOperand(const MachineInstr *MI, unsigned OpNo, - MVT::ValueType VT) { - printMemReference(MI, OpNo); - } - - void printMachineInstruction(const MachineInstr *MI); - void printOp(const MachineOperand &MO, bool isCallOperand = false); - void printMemReference(const MachineInstr *MI, unsigned Op); - bool runOnMachineFunction(MachineFunction &F); - }; -} // end of anonymous namespace - - -// Include the auto-generated portion of the assembly writer. -#include "X86GenAsmWriter.inc" - - -/// runOnMachineFunction - This uses the printMachineInstruction() -/// method to print assembly for each instruction. -/// -bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) { - setupMachineFunction(MF); - O << "\n\n"; - - // Print out constants referenced by the function - printConstantPool(MF.getConstantPool()); - - // Print out labels for the function. - O << "\t.text\n"; - emitAlignment(4); - O << "\t.globl\t" << CurrentFnName << "\n"; - if (!forCygwin && !forDarwin) - O << "\t.type\t" << CurrentFnName << ", @function\n"; - O << CurrentFnName << ":\n"; - - // Print out code for the function. - for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); - I != E; ++I) { - // Print a label for the basic block. - if (I->pred_begin() != I->pred_end()) - O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t" - << CommentString << " " << I->getBasicBlock()->getName() << "\n"; - for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); - II != E; ++II) { - // Print the assembly for the instruction. - O << "\t"; - printMachineInstruction(II); - } - } - - // We didn't modify anything. - return false; -} - -void X86ATTAsmPrinter::printOp(const MachineOperand &MO, bool isCallOp) { - const MRegisterInfo &RI = *TM.getRegisterInfo(); - switch (MO.getType()) { - case MachineOperand::MO_VirtualRegister: - case MachineOperand::MO_MachineRegister: - assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) && - "Virtual registers should not make it this far!"); - O << '%'; - for (const char *Name = RI.get(MO.getReg()).Name; *Name; ++Name) - O << (char)tolower(*Name); - return; - - case MachineOperand::MO_SignExtendedImmed: - case MachineOperand::MO_UnextendedImmed: - O << '$' << (int)MO.getImmedValue(); - return; - case MachineOperand::MO_MachineBasicBlock: { - MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); - O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction()) - << "_" << MBBOp->getNumber () << '\t' << CommentString - << MBBOp->getBasicBlock ()->getName (); - return; - } - case MachineOperand::MO_PCRelativeDisp: - std::cerr << "Shouldn't use addPCDisp() when building X86 MachineInstrs"; - abort (); - return; - case MachineOperand::MO_GlobalAddress: { - if (!isCallOp) O << '$'; - O << Mang->getValueName(MO.getGlobal()); - int Offset = MO.getOffset(); - if (Offset > 0) - O << "+" << Offset; - else if (Offset < 0) - O << Offset; - return; - } - case MachineOperand::MO_ExternalSymbol: - if (!isCallOp) O << '$'; - O << GlobalPrefix << MO.getSymbolName(); - return; - default: - O << ""; return; - } -} - -void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){ - assert(isMem(MI, Op) && "Invalid memory reference!"); - - const MachineOperand &BaseReg = MI->getOperand(Op); - int ScaleVal = MI->getOperand(Op+1).getImmedValue(); - const MachineOperand &IndexReg = MI->getOperand(Op+2); - const MachineOperand &DispSpec = MI->getOperand(Op+3); - - if (BaseReg.isFrameIndex()) { - O << "[frame slot #" << BaseReg.getFrameIndex(); - if (DispSpec.getImmedValue()) - O << " + " << DispSpec.getImmedValue(); - O << "]"; - return; - } else if (BaseReg.isConstantPoolIndex()) { - O << ".CPI" << CurrentFnName << "_" - << BaseReg.getConstantPoolIndex(); - if (DispSpec.getImmedValue()) - O << "+" << DispSpec.getImmedValue(); - if (IndexReg.getReg()) { - O << "(,"; - printOp(IndexReg); - if (ScaleVal != 1) - O << "," << ScaleVal; - O << ")"; - } - return; - } - - if (DispSpec.isGlobalAddress()) { - printOp(DispSpec, true); - } else { - int DispVal = DispSpec.getImmedValue(); - if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) - O << DispVal; - } - - if (IndexReg.getReg() || BaseReg.getReg()) { - O << "("; - if (BaseReg.getReg()) - printOp(BaseReg); - - if (IndexReg.getReg()) { - O << ","; - printOp(IndexReg); - if (ScaleVal != 1) - O << "," << ScaleVal; - } - - O << ")"; - } -} - - -/// printMachineInstruction -- Print out a single X86 LLVM instruction -/// MI in Intel syntax to the current output stream. -/// -void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) { - ++EmittedInsts; - // Call the autogenerated instruction printer routines. - printInstruction(MI); -} - - /// createX86CodePrinterPass - Returns a pass that prints the X86 assembly code /// for a MachineFunction to the given output stream, using the given target /// machine description. diff --git a/lib/Target/X86/X86AsmPrinter.h b/lib/Target/X86/X86AsmPrinter.h new file mode 100755 index 00000000000..3b05ed96f92 --- /dev/null +++ b/lib/Target/X86/X86AsmPrinter.h @@ -0,0 +1,69 @@ +//===-- X86AsmPrinter.h - Convert X86 LLVM code to Intel assembly ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file the shared super class printer that converts from our internal +// representation of machine-dependent LLVM code to Intel and AT&T format +// assembly language. This printer is the output mechanism used by `llc'. +// +//===----------------------------------------------------------------------===// + +#ifndef X86ASMPRINTER_H +#define X86ASMPRINTER_H + +#include "X86.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/ADT/Statistic.h" + +namespace llvm { +namespace x86 { + +extern Statistic<> EmittedInsts; + +struct X86SharedAsmPrinter : public AsmPrinter { + X86SharedAsmPrinter(std::ostream &O, TargetMachine &TM) + : AsmPrinter(O, TM), forCygwin(false), forDarwin(false) { } + + bool doInitialization(Module &M); + void printConstantPool(MachineConstantPool *MCP); + bool doFinalization(Module &M); + + bool forCygwin; + bool forDarwin; + + inline static bool isScale(const MachineOperand &MO) { + return MO.isImmediate() && + (MO.getImmedValue() == 1 || MO.getImmedValue() == 2 || + MO.getImmedValue() == 4 || MO.getImmedValue() == 8); + } + + inline static bool isMem(const MachineInstr *MI, unsigned Op) { + if (MI->getOperand(Op).isFrameIndex()) return true; + if (MI->getOperand(Op).isConstantPoolIndex()) return true; + return Op+4 <= MI->getNumOperands() && + MI->getOperand(Op ).isRegister() && isScale(MI->getOperand(Op+1)) && + MI->getOperand(Op+2).isRegister() && (MI->getOperand(Op+3).isImmediate()|| + MI->getOperand(Op+3).isGlobalAddress()); + } + + // SwitchSection - Switch to the specified section of the executable if we are + // not already in it! + inline static void SwitchSection(std::ostream &OS, std::string &CurSection, + const char *NewSection) { + if (CurSection != NewSection) { + CurSection = NewSection; + if (!CurSection.empty()) + OS << "\t" << NewSection << "\n"; + } + } +}; + +} // end namespace x86 +} // end namespace llvm + +#endif diff --git a/lib/Target/X86/X86IntelAsmPrinter.cpp b/lib/Target/X86/X86IntelAsmPrinter.cpp new file mode 100755 index 00000000000..64c843b661f --- /dev/null +++ b/lib/Target/X86/X86IntelAsmPrinter.cpp @@ -0,0 +1,205 @@ +//===-- X86IntelAsmPrinter.cpp - Convert X86 LLVM code to Intel assembly --===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to Intel format assembly language. +// This printer is the output mechanism used by `llc'. +// +//===----------------------------------------------------------------------===// + +#include "X86IntelAsmPrinter.h" +#include "X86.h" +#include "llvm/Module.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/Mangler.h" +using namespace llvm; +using namespace x86; + +/// runOnMachineFunction - This uses the printMachineInstruction() +/// method to print assembly for each instruction. +/// +bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + setupMachineFunction(MF); + O << "\n\n"; + + // Print out constants referenced by the function + printConstantPool(MF.getConstantPool()); + + // Print out labels for the function. + O << "\t.text\n"; + emitAlignment(4); + O << "\t.globl\t" << CurrentFnName << "\n"; + if (!forCygwin && !forDarwin) + O << "\t.type\t" << CurrentFnName << ", @function\n"; + O << CurrentFnName << ":\n"; + + // Print out code for the function. + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + // Print a label for the basic block if there are any predecessors. + if (I->pred_begin() != I->pred_end()) + O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t" + << CommentString << " " << I->getBasicBlock()->getName() << "\n"; + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) { + // Print the assembly for the instruction. + O << "\t"; + printMachineInstruction(II); + } + } + + // We didn't modify anything. + return false; +} + +void X86IntelAsmPrinter::printOp(const MachineOperand &MO, + bool elideOffsetKeyword /* = false */) { + const MRegisterInfo &RI = *TM.getRegisterInfo(); + switch (MO.getType()) { + case MachineOperand::MO_VirtualRegister: + if (Value *V = MO.getVRegValueOrNull()) { + O << "<" << V->getName() << ">"; + return; + } + // FALLTHROUGH + case MachineOperand::MO_MachineRegister: + if (MRegisterInfo::isPhysicalRegister(MO.getReg())) + // Bug Workaround: See note in Printer::doInitialization about %. + O << "%" << RI.get(MO.getReg()).Name; + else + O << "%reg" << MO.getReg(); + return; + + case MachineOperand::MO_SignExtendedImmed: + case MachineOperand::MO_UnextendedImmed: + O << (int)MO.getImmedValue(); + return; + case MachineOperand::MO_MachineBasicBlock: { + MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); + O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction()) + << "_" << MBBOp->getNumber () << "\t# " + << MBBOp->getBasicBlock ()->getName (); + return; + } + case MachineOperand::MO_PCRelativeDisp: + std::cerr << "Shouldn't use addPCDisp() when building X86 MachineInstrs"; + abort (); + return; + case MachineOperand::MO_GlobalAddress: { + if (!elideOffsetKeyword) + O << "OFFSET "; + O << Mang->getValueName(MO.getGlobal()); + int Offset = MO.getOffset(); + if (Offset > 0) + O << " + " << Offset; + else if (Offset < 0) + O << " - " << -Offset; + return; + } + case MachineOperand::MO_ExternalSymbol: + O << GlobalPrefix << MO.getSymbolName(); + return; + default: + O << ""; return; + } +} + +void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){ + assert(isMem(MI, Op) && "Invalid memory reference!"); + + const MachineOperand &BaseReg = MI->getOperand(Op); + int ScaleVal = MI->getOperand(Op+1).getImmedValue(); + const MachineOperand &IndexReg = MI->getOperand(Op+2); + const MachineOperand &DispSpec = MI->getOperand(Op+3); + + if (BaseReg.isFrameIndex()) { + O << "[frame slot #" << BaseReg.getFrameIndex(); + if (DispSpec.getImmedValue()) + O << " + " << DispSpec.getImmedValue(); + O << "]"; + return; + } else if (BaseReg.isConstantPoolIndex()) { + O << "[.CPI" << CurrentFnName << "_" + << BaseReg.getConstantPoolIndex(); + + if (IndexReg.getReg()) { + O << " + "; + if (ScaleVal != 1) + O << ScaleVal << "*"; + printOp(IndexReg); + } + + if (DispSpec.getImmedValue()) + O << " + " << DispSpec.getImmedValue(); + O << "]"; + return; + } + + O << "["; + bool NeedPlus = false; + if (BaseReg.getReg()) { + printOp(BaseReg, true); + NeedPlus = true; + } + + if (IndexReg.getReg()) { + if (NeedPlus) O << " + "; + if (ScaleVal != 1) + O << ScaleVal << "*"; + printOp(IndexReg); + NeedPlus = true; + } + + if (DispSpec.isGlobalAddress()) { + if (NeedPlus) + O << " + "; + printOp(DispSpec, true); + } else { + int DispVal = DispSpec.getImmedValue(); + if (DispVal || (!BaseReg.getReg() && !IndexReg.getReg())) { + if (NeedPlus) + if (DispVal > 0) + O << " + "; + else { + O << " - "; + DispVal = -DispVal; + } + O << DispVal; + } + } + O << "]"; +} + + +/// printMachineInstruction -- Print out a single X86 LLVM instruction +/// MI in Intel syntax to the current output stream. +/// +void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) { + ++EmittedInsts; + + // Call the autogenerated instruction printer routines. + printInstruction(MI); +} + +bool X86IntelAsmPrinter::doInitialization(Module &M) { + AsmPrinter::doInitialization(M); + // Tell gas we are outputting Intel syntax (not AT&T syntax) assembly. + // + // Bug: gas in `intel_syntax noprefix' mode interprets the symbol `Sp' in an + // instruction as a reference to the register named sp, and if you try to + // reference a symbol `Sp' (e.g. `mov ECX, OFFSET Sp') then it gets lowercased + // before being looked up in the symbol table. This creates spurious + // `undefined symbol' errors when linking. Workaround: Do not use `noprefix' + // mode, and decorate all register names with percent signs. + O << "\t.intel_syntax\n"; + return false; +} + +// Include the auto-generated portion of the assembly writer. +#include "X86GenAsmWriter1.inc" diff --git a/lib/Target/X86/X86IntelAsmPrinter.h b/lib/Target/X86/X86IntelAsmPrinter.h new file mode 100755 index 00000000000..4dec56aeaf2 --- /dev/null +++ b/lib/Target/X86/X86IntelAsmPrinter.h @@ -0,0 +1,81 @@ +//===-- X86IntelAsmPrinter.h - Convert X86 LLVM code to Intel assembly ----===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Intel assembly code printer class. +// +//===----------------------------------------------------------------------===// + +#ifndef X86INTELASMPRINTER_H +#define X86INTELASMPRINTER_H + +#include "X86AsmPrinter.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/MRegisterInfo.h" + +namespace llvm { +namespace x86 { + +struct X86IntelAsmPrinter : public X86SharedAsmPrinter { + X86IntelAsmPrinter(std::ostream &O, TargetMachine &TM) + : X86SharedAsmPrinter(O, TM) { } + + virtual const char *getPassName() const { + return "X86 Intel-Style Assembly Printer"; + } + + /// printInstruction - This method is automatically generated by tablegen + /// from the instruction set description. This method returns true if the + /// machine instruction was sufficiently described to print it, otherwise it + /// returns false. + bool printInstruction(const MachineInstr *MI); + + // This method is used by the tablegen'erated instruction printer. + void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){ + const MachineOperand &MO = MI->getOperand(OpNo); + if (MO.getType() == MachineOperand::MO_MachineRegister) { + assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physref??"); + // Bug Workaround: See note in Printer::doInitialization about %. + O << "%" << TM.getRegisterInfo()->get(MO.getReg()).Name; + } else { + printOp(MO); + } + } + + void printCallOperand(const MachineInstr *MI, unsigned OpNo, + MVT::ValueType VT) { + printOp(MI->getOperand(OpNo), true); // Don't print "OFFSET". + } + + void printMemoryOperand(const MachineInstr *MI, unsigned OpNo, + MVT::ValueType VT) { + switch (VT) { + default: assert(0 && "Unknown arg size!"); + case MVT::i8: O << "BYTE PTR "; break; + case MVT::i16: O << "WORD PTR "; break; + case MVT::i32: + case MVT::f32: O << "DWORD PTR "; break; + case MVT::i64: + case MVT::f64: O << "QWORD PTR "; break; + case MVT::f80: O << "XWORD PTR "; break; + } + printMemReference(MI, OpNo); + } + + void printMachineInstruction(const MachineInstr *MI); + void printOp(const MachineOperand &MO, bool elideOffsetKeyword = false); + void printMemReference(const MachineInstr *MI, unsigned Op); + bool runOnMachineFunction(MachineFunction &F); + bool doInitialization(Module &M); +}; + +} // end namespace x86 +} // end namespace llvm + +#endif -- 2.11.0