From: Chris Lattner Date: Sun, 14 Nov 2010 18:43:56 +0000 (+0000) Subject: move all the target's asmprinters into the main target. The piece X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=1139691e3aadff751c035f38f835d436ec6cf10a;p=oota-llvm.git move all the target's asmprinters into the main target. The piece that should be split out is the InstPrinter (if a target is mc'ized). This change makes all the targets be consistent. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119056 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index a028edf7747..d549e83593b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -328,11 +328,6 @@ foreach(t ${LLVM_TARGETS_TO_BUILD}) message(STATUS "Targeting ${t}") add_subdirectory(lib/Target/${t}) add_subdirectory(lib/Target/${t}/TargetInfo) - if( EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Target/${t}/AsmPrinter/CMakeLists.txt ) - add_subdirectory(lib/Target/${t}/AsmPrinter) - set(LLVM_ENUM_ASM_PRINTERS - "${LLVM_ENUM_ASM_PRINTERS}LLVM_ASM_PRINTER(${t})\n") - endif( EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Target/${t}/AsmPrinter/CMakeLists.txt ) if( EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Target/${t}/InstPrinter/CMakeLists.txt ) add_subdirectory(lib/Target/${t}/InstPrinter) set(LLVM_ENUM_ASM_PRINTERS diff --git a/lib/Target/Alpha/AlphaAsmPrinter.cpp b/lib/Target/Alpha/AlphaAsmPrinter.cpp new file mode 100644 index 00000000000..46ae286895a --- /dev/null +++ b/lib/Target/Alpha/AlphaAsmPrinter.cpp @@ -0,0 +1,166 @@ +//===-- AlphaAsmPrinter.cpp - Alpha LLVM assembly writer ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file 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 GAS-format Alpha assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "Alpha.h" +#include "AlphaInstrInfo.h" +#include "AlphaTargetMachine.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + struct AlphaAsmPrinter : public AsmPrinter { + /// Unique incrementer for label values for referencing Global values. + /// + + explicit AlphaAsmPrinter(TargetMachine &tm, MCStreamer &Streamer) + : AsmPrinter(tm, Streamer) {} + + virtual const char *getPassName() const { + return "Alpha Assembly Printer"; + } + void printInstruction(const MachineInstr *MI, raw_ostream &O); + void EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); + } + static const char *getRegisterName(unsigned RegNo); + + void printOp(const MachineOperand &MO, raw_ostream &O); + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + virtual void EmitFunctionBodyStart(); + virtual void EmitFunctionBodyEnd(); + void EmitStartOfAsmFile(Module &M); + + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + bool PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O); + }; +} // end of anonymous namespace + +#include "AlphaGenAsmWriter.inc" + +void AlphaAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(opNum); + if (MO.isReg()) { + assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && + "Not physreg??"); + O << getRegisterName(MO.getReg()); + } else if (MO.isImm()) { + O << MO.getImm(); + assert(MO.getImm() < (1 << 30)); + } else { + printOp(MO, O); + } +} + + +void AlphaAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) { + switch (MO.getType()) { + case MachineOperand::MO_Register: + O << getRegisterName(MO.getReg()); + return; + + case MachineOperand::MO_Immediate: + assert(0 && "printOp() does not handle immediate values"); + return; + + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" + << MO.getIndex(); + return; + + case MachineOperand::MO_ExternalSymbol: + O << MO.getSymbolName(); + return; + + case MachineOperand::MO_GlobalAddress: + O << *Mang->getSymbol(MO.getGlobal()); + return; + + case MachineOperand::MO_JumpTableIndex: + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + return; + + default: + O << ""; + return; + } +} + +/// EmitFunctionBodyStart - Targets can override this to emit stuff before +/// the first basic block in the function. +void AlphaAsmPrinter::EmitFunctionBodyStart() { + OutStreamer.EmitRawText("\t.ent " + Twine(CurrentFnSym->getName())); +} + +/// EmitFunctionBodyEnd - Targets can override this to emit stuff after +/// the last basic block in the function. +void AlphaAsmPrinter::EmitFunctionBodyEnd() { + OutStreamer.EmitRawText("\t.end " + Twine(CurrentFnSym->getName())); +} + +void AlphaAsmPrinter::EmitStartOfAsmFile(Module &M) { + OutStreamer.EmitRawText(StringRef("\t.arch ev6")); + OutStreamer.EmitRawText(StringRef("\t.set noat")); +} + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool AlphaAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O) { + printOperand(MI, OpNo, O); + return false; +} + +bool AlphaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier. + O << "0("; + printOperand(MI, OpNo, O); + O << ")"; + return false; +} + +// Force static initialization. +extern "C" void LLVMInitializeAlphaAsmPrinter() { + RegisterAsmPrinter X(TheAlphaTarget); +} diff --git a/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp b/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp deleted file mode 100644 index 46ae286895a..00000000000 --- a/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp +++ /dev/null @@ -1,166 +0,0 @@ -//===-- AlphaAsmPrinter.cpp - Alpha LLVM assembly writer ------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file 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 GAS-format Alpha assembly language. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "asm-printer" -#include "Alpha.h" -#include "AlphaInstrInfo.h" -#include "AlphaTargetMachine.h" -#include "llvm/Module.h" -#include "llvm/Type.h" -#include "llvm/Assembly/Writer.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -namespace { - struct AlphaAsmPrinter : public AsmPrinter { - /// Unique incrementer for label values for referencing Global values. - /// - - explicit AlphaAsmPrinter(TargetMachine &tm, MCStreamer &Streamer) - : AsmPrinter(tm, Streamer) {} - - virtual const char *getPassName() const { - return "Alpha Assembly Printer"; - } - void printInstruction(const MachineInstr *MI, raw_ostream &O); - void EmitInstruction(const MachineInstr *MI) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - printInstruction(MI, OS); - OutStreamer.EmitRawText(OS.str()); - } - static const char *getRegisterName(unsigned RegNo); - - void printOp(const MachineOperand &MO, raw_ostream &O); - void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); - virtual void EmitFunctionBodyStart(); - virtual void EmitFunctionBodyEnd(); - void EmitStartOfAsmFile(Module &M); - - bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O); - bool PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode, raw_ostream &O); - }; -} // end of anonymous namespace - -#include "AlphaGenAsmWriter.inc" - -void AlphaAsmPrinter::printOperand(const MachineInstr *MI, int opNum, - raw_ostream &O) { - const MachineOperand &MO = MI->getOperand(opNum); - if (MO.isReg()) { - assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && - "Not physreg??"); - O << getRegisterName(MO.getReg()); - } else if (MO.isImm()) { - O << MO.getImm(); - assert(MO.getImm() < (1 << 30)); - } else { - printOp(MO, O); - } -} - - -void AlphaAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) { - switch (MO.getType()) { - case MachineOperand::MO_Register: - O << getRegisterName(MO.getReg()); - return; - - case MachineOperand::MO_Immediate: - assert(0 && "printOp() does not handle immediate values"); - return; - - case MachineOperand::MO_MachineBasicBlock: - O << *MO.getMBB()->getSymbol(); - return; - - case MachineOperand::MO_ConstantPoolIndex: - O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" - << MO.getIndex(); - return; - - case MachineOperand::MO_ExternalSymbol: - O << MO.getSymbolName(); - return; - - case MachineOperand::MO_GlobalAddress: - O << *Mang->getSymbol(MO.getGlobal()); - return; - - case MachineOperand::MO_JumpTableIndex: - O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getIndex(); - return; - - default: - O << ""; - return; - } -} - -/// EmitFunctionBodyStart - Targets can override this to emit stuff before -/// the first basic block in the function. -void AlphaAsmPrinter::EmitFunctionBodyStart() { - OutStreamer.EmitRawText("\t.ent " + Twine(CurrentFnSym->getName())); -} - -/// EmitFunctionBodyEnd - Targets can override this to emit stuff after -/// the last basic block in the function. -void AlphaAsmPrinter::EmitFunctionBodyEnd() { - OutStreamer.EmitRawText("\t.end " + Twine(CurrentFnSym->getName())); -} - -void AlphaAsmPrinter::EmitStartOfAsmFile(Module &M) { - OutStreamer.EmitRawText(StringRef("\t.arch ev6")); - OutStreamer.EmitRawText(StringRef("\t.set noat")); -} - -/// PrintAsmOperand - Print out an operand for an inline asm expression. -/// -bool AlphaAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode, raw_ostream &O) { - printOperand(MI, OpNo, O); - return false; -} - -bool AlphaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode, - raw_ostream &O) { - if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier. - O << "0("; - printOperand(MI, OpNo, O); - O << ")"; - return false; -} - -// Force static initialization. -extern "C" void LLVMInitializeAlphaAsmPrinter() { - RegisterAsmPrinter X(TheAlphaTarget); -} diff --git a/lib/Target/Alpha/AsmPrinter/CMakeLists.txt b/lib/Target/Alpha/AsmPrinter/CMakeLists.txt deleted file mode 100644 index 992c2181314..00000000000 --- a/lib/Target/Alpha/AsmPrinter/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - -add_llvm_library(LLVMAlphaAsmPrinter - AlphaAsmPrinter.cpp - ) -add_dependencies(LLVMAlphaAsmPrinter AlphaCodeGenTable_gen) diff --git a/lib/Target/Alpha/AsmPrinter/Makefile b/lib/Target/Alpha/AsmPrinter/Makefile deleted file mode 100644 index ea13c38df4a..00000000000 --- a/lib/Target/Alpha/AsmPrinter/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/Alpha/AsmPrinter/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMAlphaAsmPrinter - -# Hack: we need to include 'main' alpha target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/lib/Target/Alpha/CMakeLists.txt b/lib/Target/Alpha/CMakeLists.txt index fdc1348b731..ad0d1a46ef2 100644 --- a/lib/Target/Alpha/CMakeLists.txt +++ b/lib/Target/Alpha/CMakeLists.txt @@ -11,6 +11,7 @@ tablegen(AlphaGenCallingConv.inc -gen-callingconv) tablegen(AlphaGenSubtarget.inc -gen-subtarget) add_llvm_target(AlphaCodeGen + AlphaAsmPrinter.cpp AlphaBranchSelector.cpp AlphaInstrInfo.cpp AlphaISelDAGToDAG.cpp diff --git a/lib/Target/Alpha/Makefile b/lib/Target/Alpha/Makefile index 2129ec83437..9564be680e5 100644 --- a/lib/Target/Alpha/Makefile +++ b/lib/Target/Alpha/Makefile @@ -18,6 +18,6 @@ BUILT_SOURCES = AlphaGenRegisterInfo.h.inc AlphaGenRegisterNames.inc \ AlphaGenAsmWriter.inc AlphaGenDAGISel.inc \ AlphaGenCallingConv.inc AlphaGenSubtarget.inc -DIRS = AsmPrinter TargetInfo +DIRS = TargetInfo include $(LEVEL)/Makefile.common diff --git a/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp b/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp deleted file mode 100644 index 6ba258beb2b..00000000000 --- a/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp +++ /dev/null @@ -1,156 +0,0 @@ -//===-- BlackfinAsmPrinter.cpp - Blackfin LLVM assembly writer ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file 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 GAS-format BLACKFIN assembly language. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "asm-printer" -#include "Blackfin.h" -#include "BlackfinInstrInfo.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -namespace { - class BlackfinAsmPrinter : public AsmPrinter { - public: - BlackfinAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) - : AsmPrinter(TM, Streamer) {} - - virtual const char *getPassName() const { - return "Blackfin Assembly Printer"; - } - - void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); - void printMemoryOperand(const MachineInstr *MI, int opNum, raw_ostream &O); - void printInstruction(const MachineInstr *MI, raw_ostream &O);// autogen'd. - static const char *getRegisterName(unsigned RegNo); - - void EmitInstruction(const MachineInstr *MI) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - printInstruction(MI, OS); - OutStreamer.EmitRawText(OS.str()); - } - bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O); - bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O); - }; -} // end of anonymous namespace - -#include "BlackfinGenAsmWriter.inc" - -extern "C" void LLVMInitializeBlackfinAsmPrinter() { - RegisterAsmPrinter X(TheBlackfinTarget); -} - -void BlackfinAsmPrinter::printOperand(const MachineInstr *MI, int opNum, - raw_ostream &O) { - const MachineOperand &MO = MI->getOperand(opNum); - switch (MO.getType()) { - case MachineOperand::MO_Register: - assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && - "Virtual registers should be already mapped!"); - O << getRegisterName(MO.getReg()); - break; - - case MachineOperand::MO_Immediate: - O << MO.getImm(); - break; - case MachineOperand::MO_MachineBasicBlock: - O << *MO.getMBB()->getSymbol(); - return; - case MachineOperand::MO_GlobalAddress: - O << *Mang->getSymbol(MO.getGlobal()); - printOffset(MO.getOffset(), O); - break; - case MachineOperand::MO_ExternalSymbol: - O << *GetExternalSymbolSymbol(MO.getSymbolName()); - break; - case MachineOperand::MO_ConstantPoolIndex: - O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" - << MO.getIndex(); - break; - case MachineOperand::MO_JumpTableIndex: - O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getIndex(); - break; - default: - llvm_unreachable(""); - break; - } -} - -void BlackfinAsmPrinter::printMemoryOperand(const MachineInstr *MI, int opNum, - raw_ostream &O) { - printOperand(MI, opNum, O); - - if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0) - return; - - O << " + "; - printOperand(MI, opNum+1, O); -} - -/// PrintAsmOperand - Print out an operand for an inline asm expression. -/// -bool BlackfinAsmPrinter::PrintAsmOperand(const MachineInstr *MI, - unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode, - raw_ostream &O) { - if (ExtraCode && ExtraCode[0]) { - if (ExtraCode[1] != 0) return true; // Unknown modifier. - - switch (ExtraCode[0]) { - default: return true; // Unknown modifier. - case 'r': - break; - } - } - - printOperand(MI, OpNo, O); - - return false; -} - -bool BlackfinAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode, - raw_ostream &O) { - if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier - - O << '['; - printOperand(MI, OpNo, O); - O << ']'; - - return false; -} diff --git a/lib/Target/Blackfin/AsmPrinter/CMakeLists.txt b/lib/Target/Blackfin/AsmPrinter/CMakeLists.txt deleted file mode 100644 index 795aebfe2b8..00000000000 --- a/lib/Target/Blackfin/AsmPrinter/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - -add_llvm_library(LLVMBlackfinAsmPrinter - BlackfinAsmPrinter.cpp - ) -add_dependencies(LLVMBlackfinAsmPrinter BlackfinCodeGenTable_gen) diff --git a/lib/Target/Blackfin/AsmPrinter/Makefile b/lib/Target/Blackfin/AsmPrinter/Makefile deleted file mode 100644 index a106a2382a1..00000000000 --- a/lib/Target/Blackfin/AsmPrinter/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/Blackfin/AsmPrinter/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMBlackfinAsmPrinter - -# Hack: we need to include 'main' Blackfin target directory to grab private -# headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/lib/Target/Blackfin/BlackfinAsmPrinter.cpp b/lib/Target/Blackfin/BlackfinAsmPrinter.cpp new file mode 100644 index 00000000000..6ba258beb2b --- /dev/null +++ b/lib/Target/Blackfin/BlackfinAsmPrinter.cpp @@ -0,0 +1,156 @@ +//===-- BlackfinAsmPrinter.cpp - Blackfin LLVM assembly writer ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file 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 GAS-format BLACKFIN assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "Blackfin.h" +#include "BlackfinInstrInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + class BlackfinAsmPrinter : public AsmPrinter { + public: + BlackfinAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) {} + + virtual const char *getPassName() const { + return "Blackfin Assembly Printer"; + } + + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printMemoryOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printInstruction(const MachineInstr *MI, raw_ostream &O);// autogen'd. + static const char *getRegisterName(unsigned RegNo); + + void EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); + } + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + }; +} // end of anonymous namespace + +#include "BlackfinGenAsmWriter.inc" + +extern "C" void LLVMInitializeBlackfinAsmPrinter() { + RegisterAsmPrinter X(TheBlackfinTarget); +} + +void BlackfinAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(opNum); + switch (MO.getType()) { + case MachineOperand::MO_Register: + assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && + "Virtual registers should be already mapped!"); + O << getRegisterName(MO.getReg()); + break; + + case MachineOperand::MO_Immediate: + O << MO.getImm(); + break; + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + case MachineOperand::MO_GlobalAddress: + O << *Mang->getSymbol(MO.getGlobal()); + printOffset(MO.getOffset(), O); + break; + case MachineOperand::MO_ExternalSymbol: + O << *GetExternalSymbolSymbol(MO.getSymbolName()); + break; + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" + << MO.getIndex(); + break; + case MachineOperand::MO_JumpTableIndex: + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + default: + llvm_unreachable(""); + break; + } +} + +void BlackfinAsmPrinter::printMemoryOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + printOperand(MI, opNum, O); + + if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0) + return; + + O << " + "; + printOperand(MI, opNum+1, O); +} + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool BlackfinAsmPrinter::PrintAsmOperand(const MachineInstr *MI, + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'r': + break; + } + } + + printOperand(MI, OpNo, O); + + return false; +} + +bool BlackfinAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier + + O << '['; + printOperand(MI, OpNo, O); + O << ']'; + + return false; +} diff --git a/lib/Target/Blackfin/CMakeLists.txt b/lib/Target/Blackfin/CMakeLists.txt index f8847d057da..718f4f270f3 100644 --- a/lib/Target/Blackfin/CMakeLists.txt +++ b/lib/Target/Blackfin/CMakeLists.txt @@ -12,6 +12,7 @@ tablegen(BlackfinGenCallingConv.inc -gen-callingconv) tablegen(BlackfinGenIntrinsics.inc -gen-tgt-intrinsic) add_llvm_target(BlackfinCodeGen + BlackfinAsmPrinter.cpp BlackfinInstrInfo.cpp BlackfinIntrinsicInfo.cpp BlackfinISelDAGToDAG.cpp diff --git a/lib/Target/Blackfin/Makefile b/lib/Target/Blackfin/Makefile index 339bef9981f..5eb8e9a992b 100644 --- a/lib/Target/Blackfin/Makefile +++ b/lib/Target/Blackfin/Makefile @@ -18,7 +18,7 @@ BUILT_SOURCES = BlackfinGenRegisterInfo.h.inc BlackfinGenRegisterNames.inc \ BlackfinGenDAGISel.inc BlackfinGenSubtarget.inc \ BlackfinGenCallingConv.inc BlackfinGenIntrinsics.inc -DIRS = AsmPrinter TargetInfo +DIRS = TargetInfo include $(LEVEL)/Makefile.common diff --git a/lib/Target/CellSPU/AsmPrinter/CMakeLists.txt b/lib/Target/CellSPU/AsmPrinter/CMakeLists.txt deleted file mode 100644 index 8a2b59a88a6..00000000000 --- a/lib/Target/CellSPU/AsmPrinter/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -include_directories( - ${CMAKE_CURRENT_BINARY_DIR}/.. - ${CMAKE_CURRENT_SOURCE_DIR}/.. - ) - -add_llvm_library(LLVMCellSPUAsmPrinter - SPUAsmPrinter.cpp - ) -add_dependencies(LLVMCellSPUAsmPrinter CellSPUCodeGenTable_gen) diff --git a/lib/Target/CellSPU/AsmPrinter/Makefile b/lib/Target/CellSPU/AsmPrinter/Makefile deleted file mode 100644 index 4ec9d04c002..00000000000 --- a/lib/Target/CellSPU/AsmPrinter/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -##===- lib/Target/CellSPU/AsmPrinter/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMCellSPUAsmPrinter - -# Hack: we need to include 'main' CellSPU target directory to grab -# private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp b/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp deleted file mode 100644 index 40404614b70..00000000000 --- a/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp +++ /dev/null @@ -1,327 +0,0 @@ -//===-- SPUAsmPrinter.cpp - Print machine instrs to Cell SPU assembly -------=// -// -// The LLVM Compiler Infrastructure -// -// This file 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 Cell SPU assembly language. This printer -// is the output mechanism used by `llc'. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "asmprinter" -#include "SPU.h" -#include "SPUTargetMachine.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -namespace { - class SPUAsmPrinter : public AsmPrinter { - public: - explicit SPUAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) : - AsmPrinter(TM, Streamer) {} - - virtual const char *getPassName() const { - return "STI CBEA SPU Assembly Printer"; - } - - /// printInstruction - This method is automatically generated by tablegen - /// from the instruction set description. - void printInstruction(const MachineInstr *MI, raw_ostream &OS); - static const char *getRegisterName(unsigned RegNo); - - - void EmitInstruction(const MachineInstr *MI) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - printInstruction(MI, OS); - OutStreamer.EmitRawText(OS.str()); - } - void printOp(const MachineOperand &MO, raw_ostream &OS); - - void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { - const MachineOperand &MO = MI->getOperand(OpNo); - if (MO.isReg()) { - O << getRegisterName(MO.getReg()); - } else if (MO.isImm()) { - O << MO.getImm(); - } else { - printOp(MO, O); - } - } - - bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O); - bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O); - - - void - printU7ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) - { - unsigned int value = MI->getOperand(OpNo).getImm(); - assert(value < (1 << 8) && "Invalid u7 argument"); - O << value; - } - - void - printShufAddr(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) - { - char value = MI->getOperand(OpNo).getImm(); - O << (int) value; - O << "("; - printOperand(MI, OpNo+1, O); - O << ")"; - } - - void - printS16ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) - { - O << (short) MI->getOperand(OpNo).getImm(); - } - - void - printU16ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) - { - O << (unsigned short)MI->getOperand(OpNo).getImm(); - } - - void - printMemRegReg(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { - // When used as the base register, r0 reads constant zero rather than - // the value contained in the register. For this reason, the darwin - // assembler requires that we print r0 as 0 (no r) when used as the base. - const MachineOperand &MO = MI->getOperand(OpNo); - O << getRegisterName(MO.getReg()) << ", "; - printOperand(MI, OpNo+1, O); - } - - void - printU18ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) - { - unsigned int value = MI->getOperand(OpNo).getImm(); - assert(value <= (1 << 19) - 1 && "Invalid u18 argument"); - O << value; - } - - void - printS10ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) - { - short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16) - >> 16); - assert((value >= -(1 << 9) && value <= (1 << 9) - 1) - && "Invalid s10 argument"); - O << value; - } - - void - printU10ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) - { - short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16) - >> 16); - assert((value <= (1 << 10) - 1) && "Invalid u10 argument"); - O << value; - } - - void - printDFormAddr(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) - { - assert(MI->getOperand(OpNo).isImm() && - "printDFormAddr first operand is not immediate"); - int64_t value = int64_t(MI->getOperand(OpNo).getImm()); - int16_t value16 = int16_t(value); - assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1) - && "Invalid dform s10 offset argument"); - O << (value16 & ~0xf) << "("; - printOperand(MI, OpNo+1, O); - O << ")"; - } - - void - printAddr256K(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) - { - /* Note: operand 1 is an offset or symbol name. */ - if (MI->getOperand(OpNo).isImm()) { - printS16ImmOperand(MI, OpNo, O); - } else { - printOp(MI->getOperand(OpNo), O); - if (MI->getOperand(OpNo+1).isImm()) { - int displ = int(MI->getOperand(OpNo+1).getImm()); - if (displ > 0) - O << "+" << displ; - else if (displ < 0) - O << displ; - } - } - } - - void printCallOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { - printOp(MI->getOperand(OpNo), O); - } - - void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { - // Used to generate a ".-", but it turns out that the assembler - // really wants the target. - // - // N.B.: This operand is used for call targets. Branch hints are another - // animal entirely. - printOp(MI->getOperand(OpNo), O); - } - - void printSymbolHi(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { - if (MI->getOperand(OpNo).isImm()) { - printS16ImmOperand(MI, OpNo, O); - } else { - printOp(MI->getOperand(OpNo), O); - O << "@h"; - } - } - - void printSymbolLo(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { - if (MI->getOperand(OpNo).isImm()) { - printS16ImmOperand(MI, OpNo, O); - } else { - printOp(MI->getOperand(OpNo), O); - O << "@l"; - } - } - - /// Print local store address - void printSymbolLSA(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { - printOp(MI->getOperand(OpNo), O); - } - - void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo, - raw_ostream &O) { - if (MI->getOperand(OpNo).isImm()) { - int value = (int) MI->getOperand(OpNo).getImm(); - assert((value >= 0 && value < 16) - && "Invalid negated immediate rotate 7-bit argument"); - O << -value; - } else { - llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm"); - } - } - - void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O){ - assert(MI->getOperand(OpNo).isImm() && - "Invalid/non-immediate rotate amount in printRotateNeg7Imm"); - int value = (int) MI->getOperand(OpNo).getImm(); - assert((value >= 0 && value <= 32) - && "Invalid negated immediate rotate 7-bit argument"); - O << -value; - } - }; -} // end of anonymous namespace - -// Include the auto-generated portion of the assembly writer -#include "SPUGenAsmWriter.inc" - -void SPUAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) { - switch (MO.getType()) { - case MachineOperand::MO_Immediate: - report_fatal_error("printOp() does not handle immediate values"); - return; - - case MachineOperand::MO_MachineBasicBlock: - O << *MO.getMBB()->getSymbol(); - return; - case MachineOperand::MO_JumpTableIndex: - O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getIndex(); - return; - case MachineOperand::MO_ConstantPoolIndex: - O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() - << '_' << MO.getIndex(); - return; - case MachineOperand::MO_ExternalSymbol: - // Computing the address of an external symbol, not calling it. - if (TM.getRelocationModel() != Reloc::Static) { - O << "L" << MAI->getGlobalPrefix() << MO.getSymbolName() - << "$non_lazy_ptr"; - return; - } - O << *GetExternalSymbolSymbol(MO.getSymbolName()); - return; - case MachineOperand::MO_GlobalAddress: - // External or weakly linked global variables need non-lazily-resolved - // stubs - if (TM.getRelocationModel() != Reloc::Static) { - const GlobalValue *GV = MO.getGlobal(); - if (((GV->isDeclaration() || GV->hasWeakLinkage() || - GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) { - O << *GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); - return; - } - } - O << *Mang->getSymbol(MO.getGlobal()); - return; - default: - O << ""; - return; - } -} - -/// PrintAsmOperand - Print out an operand for an inline asm expression. -/// -bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode, raw_ostream &O) { - // Does this asm operand have a single letter operand modifier? - if (ExtraCode && ExtraCode[0]) { - if (ExtraCode[1] != 0) return true; // Unknown modifier. - - switch (ExtraCode[0]) { - default: return true; // Unknown modifier. - case 'L': // Write second word of DImode reference. - // Verify that this operand has two consecutive registers. - if (!MI->getOperand(OpNo).isReg() || - OpNo+1 == MI->getNumOperands() || - !MI->getOperand(OpNo+1).isReg()) - return true; - ++OpNo; // Return the high-part. - break; - } - } - - printOperand(MI, OpNo, O); - return false; -} - -bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode, - raw_ostream &O) { - if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier. - printMemRegReg(MI, OpNo, O); - return false; -} - -// Force static initialization. -extern "C" void LLVMInitializeCellSPUAsmPrinter() { - RegisterAsmPrinter X(TheCellSPUTarget); -} diff --git a/lib/Target/CellSPU/CMakeLists.txt b/lib/Target/CellSPU/CMakeLists.txt index 213dea9230c..901122b1c4c 100644 --- a/lib/Target/CellSPU/CMakeLists.txt +++ b/lib/Target/CellSPU/CMakeLists.txt @@ -12,6 +12,7 @@ tablegen(SPUGenSubtarget.inc -gen-subtarget) tablegen(SPUGenCallingConv.inc -gen-callingconv) add_llvm_target(CellSPUCodeGen + SPUAsmPrinter.cpp SPUFrameInfo.cpp SPUHazardRecognizers.cpp SPUInstrInfo.cpp diff --git a/lib/Target/CellSPU/Makefile b/lib/Target/CellSPU/Makefile index cbdbd3c3a5b..77c66be9e85 100644 --- a/lib/Target/CellSPU/Makefile +++ b/lib/Target/CellSPU/Makefile @@ -16,6 +16,6 @@ BUILT_SOURCES = SPUGenInstrNames.inc SPUGenRegisterNames.inc \ SPUGenInstrInfo.inc SPUGenDAGISel.inc \ SPUGenSubtarget.inc SPUGenCallingConv.inc -DIRS = AsmPrinter TargetInfo +DIRS = TargetInfo include $(LEVEL)/Makefile.common diff --git a/lib/Target/CellSPU/SPUAsmPrinter.cpp b/lib/Target/CellSPU/SPUAsmPrinter.cpp new file mode 100644 index 00000000000..40404614b70 --- /dev/null +++ b/lib/Target/CellSPU/SPUAsmPrinter.cpp @@ -0,0 +1,327 @@ +//===-- SPUAsmPrinter.cpp - Print machine instrs to Cell SPU assembly -------=// +// +// The LLVM Compiler Infrastructure +// +// This file 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 Cell SPU assembly language. This printer +// is the output mechanism used by `llc'. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asmprinter" +#include "SPU.h" +#include "SPUTargetMachine.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + class SPUAsmPrinter : public AsmPrinter { + public: + explicit SPUAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) : + AsmPrinter(TM, Streamer) {} + + virtual const char *getPassName() const { + return "STI CBEA SPU Assembly Printer"; + } + + /// printInstruction - This method is automatically generated by tablegen + /// from the instruction set description. + void printInstruction(const MachineInstr *MI, raw_ostream &OS); + static const char *getRegisterName(unsigned RegNo); + + + void EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); + } + void printOp(const MachineOperand &MO, raw_ostream &OS); + + void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(OpNo); + if (MO.isReg()) { + O << getRegisterName(MO.getReg()); + } else if (MO.isImm()) { + O << MO.getImm(); + } else { + printOp(MO, O); + } + } + + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + + + void + printU7ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) + { + unsigned int value = MI->getOperand(OpNo).getImm(); + assert(value < (1 << 8) && "Invalid u7 argument"); + O << value; + } + + void + printShufAddr(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) + { + char value = MI->getOperand(OpNo).getImm(); + O << (int) value; + O << "("; + printOperand(MI, OpNo+1, O); + O << ")"; + } + + void + printS16ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) + { + O << (short) MI->getOperand(OpNo).getImm(); + } + + void + printU16ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) + { + O << (unsigned short)MI->getOperand(OpNo).getImm(); + } + + void + printMemRegReg(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + // When used as the base register, r0 reads constant zero rather than + // the value contained in the register. For this reason, the darwin + // assembler requires that we print r0 as 0 (no r) when used as the base. + const MachineOperand &MO = MI->getOperand(OpNo); + O << getRegisterName(MO.getReg()) << ", "; + printOperand(MI, OpNo+1, O); + } + + void + printU18ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) + { + unsigned int value = MI->getOperand(OpNo).getImm(); + assert(value <= (1 << 19) - 1 && "Invalid u18 argument"); + O << value; + } + + void + printS10ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) + { + short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16) + >> 16); + assert((value >= -(1 << 9) && value <= (1 << 9) - 1) + && "Invalid s10 argument"); + O << value; + } + + void + printU10ImmOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) + { + short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16) + >> 16); + assert((value <= (1 << 10) - 1) && "Invalid u10 argument"); + O << value; + } + + void + printDFormAddr(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) + { + assert(MI->getOperand(OpNo).isImm() && + "printDFormAddr first operand is not immediate"); + int64_t value = int64_t(MI->getOperand(OpNo).getImm()); + int16_t value16 = int16_t(value); + assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1) + && "Invalid dform s10 offset argument"); + O << (value16 & ~0xf) << "("; + printOperand(MI, OpNo+1, O); + O << ")"; + } + + void + printAddr256K(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) + { + /* Note: operand 1 is an offset or symbol name. */ + if (MI->getOperand(OpNo).isImm()) { + printS16ImmOperand(MI, OpNo, O); + } else { + printOp(MI->getOperand(OpNo), O); + if (MI->getOperand(OpNo+1).isImm()) { + int displ = int(MI->getOperand(OpNo+1).getImm()); + if (displ > 0) + O << "+" << displ; + else if (displ < 0) + O << displ; + } + } + } + + void printCallOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + printOp(MI->getOperand(OpNo), O); + } + + void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + // Used to generate a ".-", but it turns out that the assembler + // really wants the target. + // + // N.B.: This operand is used for call targets. Branch hints are another + // animal entirely. + printOp(MI->getOperand(OpNo), O); + } + + void printSymbolHi(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + if (MI->getOperand(OpNo).isImm()) { + printS16ImmOperand(MI, OpNo, O); + } else { + printOp(MI->getOperand(OpNo), O); + O << "@h"; + } + } + + void printSymbolLo(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + if (MI->getOperand(OpNo).isImm()) { + printS16ImmOperand(MI, OpNo, O); + } else { + printOp(MI->getOperand(OpNo), O); + O << "@l"; + } + } + + /// Print local store address + void printSymbolLSA(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + printOp(MI->getOperand(OpNo), O); + } + + void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + if (MI->getOperand(OpNo).isImm()) { + int value = (int) MI->getOperand(OpNo).getImm(); + assert((value >= 0 && value < 16) + && "Invalid negated immediate rotate 7-bit argument"); + O << -value; + } else { + llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm"); + } + } + + void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O){ + assert(MI->getOperand(OpNo).isImm() && + "Invalid/non-immediate rotate amount in printRotateNeg7Imm"); + int value = (int) MI->getOperand(OpNo).getImm(); + assert((value >= 0 && value <= 32) + && "Invalid negated immediate rotate 7-bit argument"); + O << -value; + } + }; +} // end of anonymous namespace + +// Include the auto-generated portion of the assembly writer +#include "SPUGenAsmWriter.inc" + +void SPUAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) { + switch (MO.getType()) { + case MachineOperand::MO_Immediate: + report_fatal_error("printOp() does not handle immediate values"); + return; + + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + case MachineOperand::MO_JumpTableIndex: + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + return; + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + << '_' << MO.getIndex(); + return; + case MachineOperand::MO_ExternalSymbol: + // Computing the address of an external symbol, not calling it. + if (TM.getRelocationModel() != Reloc::Static) { + O << "L" << MAI->getGlobalPrefix() << MO.getSymbolName() + << "$non_lazy_ptr"; + return; + } + O << *GetExternalSymbolSymbol(MO.getSymbolName()); + return; + case MachineOperand::MO_GlobalAddress: + // External or weakly linked global variables need non-lazily-resolved + // stubs + if (TM.getRelocationModel() != Reloc::Static) { + const GlobalValue *GV = MO.getGlobal(); + if (((GV->isDeclaration() || GV->hasWeakLinkage() || + GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) { + O << *GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + return; + } + } + O << *Mang->getSymbol(MO.getGlobal()); + return; + default: + O << ""; + return; + } +} + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O) { + // Does this asm operand have a single letter operand modifier? + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'L': // Write second word of DImode reference. + // Verify that this operand has two consecutive registers. + if (!MI->getOperand(OpNo).isReg() || + OpNo+1 == MI->getNumOperands() || + !MI->getOperand(OpNo+1).isReg()) + return true; + ++OpNo; // Return the high-part. + break; + } + } + + printOperand(MI, OpNo, O); + return false; +} + +bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier. + printMemRegReg(MI, OpNo, O); + return false; +} + +// Force static initialization. +extern "C" void LLVMInitializeCellSPUAsmPrinter() { + RegisterAsmPrinter X(TheCellSPUTarget); +} diff --git a/lib/Target/Mips/AsmPrinter/CMakeLists.txt b/lib/Target/Mips/AsmPrinter/CMakeLists.txt deleted file mode 100644 index d3099d2a4e3..00000000000 --- a/lib/Target/Mips/AsmPrinter/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -include_directories( - ${CMAKE_CURRENT_BINARY_DIR}/.. - ${CMAKE_CURRENT_SOURCE_DIR}/.. - ) - -add_llvm_library(LLVMMipsAsmPrinter - MipsAsmPrinter.cpp - ) -add_dependencies(LLVMMipsAsmPrinter MipsCodeGenTable_gen) diff --git a/lib/Target/Mips/AsmPrinter/Makefile b/lib/Target/Mips/AsmPrinter/Makefile deleted file mode 100644 index b1efe9b9447..00000000000 --- a/lib/Target/Mips/AsmPrinter/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -##===- lib/Target/Mips/AsmPrinter/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMMipsAsmPrinter - -# Hack: we need to include 'main' Mips target directory to grab -# private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp deleted file mode 100644 index 6660f6b6243..00000000000 --- a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp +++ /dev/null @@ -1,386 +0,0 @@ -//===-- MipsAsmPrinter.cpp - Mips LLVM assembly writer --------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file 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 GAS-format MIPS assembly language. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "mips-asm-printer" -#include "Mips.h" -#include "MipsSubtarget.h" -#include "MipsInstrInfo.h" -#include "MipsTargetMachine.h" -#include "MipsMachineFunction.h" -#include "llvm/BasicBlock.h" -#include "llvm/Instructions.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -namespace { - class MipsAsmPrinter : public AsmPrinter { - const MipsSubtarget *Subtarget; - public: - explicit MipsAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) - : AsmPrinter(TM, Streamer) { - Subtarget = &TM.getSubtarget(); - } - - virtual const char *getPassName() const { - return "Mips Assembly Printer"; - } - - bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O); - void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); - void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O); - void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, - const char *Modifier = 0); - void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, - const char *Modifier = 0); - void printSavedRegsBitmask(raw_ostream &O); - void printHex32(unsigned int Value, raw_ostream &O); - - const char *getCurrentABIString() const; - void emitFrameDirective(); - - void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen'd. - void EmitInstruction(const MachineInstr *MI) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - printInstruction(MI, OS); - OutStreamer.EmitRawText(OS.str()); - } - virtual void EmitFunctionBodyStart(); - virtual void EmitFunctionBodyEnd(); - virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; - static const char *getRegisterName(unsigned RegNo); - - virtual void EmitFunctionEntryLabel(); - void EmitStartOfAsmFile(Module &M); - }; -} // end of anonymous namespace - -#include "MipsGenAsmWriter.inc" - -//===----------------------------------------------------------------------===// -// -// Mips Asm Directives -// -// -- Frame directive "frame Stackpointer, Stacksize, RARegister" -// Describe the stack frame. -// -// -- Mask directives "(f)mask bitmask, offset" -// Tells the assembler which registers are saved and where. -// bitmask - contain a little endian bitset indicating which registers are -// saved on function prologue (e.g. with a 0x80000000 mask, the -// assembler knows the register 31 (RA) is saved at prologue. -// offset - the position before stack pointer subtraction indicating where -// the first saved register on prologue is located. (e.g. with a -// -// Consider the following function prologue: -// -// .frame $fp,48,$ra -// .mask 0xc0000000,-8 -// addiu $sp, $sp, -48 -// sw $ra, 40($sp) -// sw $fp, 36($sp) -// -// With a 0xc0000000 mask, the assembler knows the register 31 (RA) and -// 30 (FP) are saved at prologue. As the save order on prologue is from -// left to right, RA is saved first. A -8 offset means that after the -// stack pointer subtration, the first register in the mask (RA) will be -// saved at address 48-8=40. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Mask directives -//===----------------------------------------------------------------------===// - -// Create a bitmask with all callee saved registers for CPU or Floating Point -// registers. For CPU registers consider RA, GP and FP for saving if necessary. -void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { - const TargetRegisterInfo &RI = *TM.getRegisterInfo(); - const MipsFunctionInfo *MipsFI = MF->getInfo(); - - // CPU and FPU Saved Registers Bitmasks - unsigned int CPUBitmask = 0; - unsigned int FPUBitmask = 0; - - // Set the CPU and FPU Bitmasks - const MachineFrameInfo *MFI = MF->getFrameInfo(); - const std::vector &CSI = MFI->getCalleeSavedInfo(); - for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - unsigned Reg = CSI[i].getReg(); - unsigned RegNum = MipsRegisterInfo::getRegisterNumbering(Reg); - if (Mips::CPURegsRegisterClass->contains(Reg)) - CPUBitmask |= (1 << RegNum); - else - FPUBitmask |= (1 << RegNum); - } - - // Return Address and Frame registers must also be set in CPUBitmask. - if (RI.hasFP(*MF)) - CPUBitmask |= (1 << MipsRegisterInfo:: - getRegisterNumbering(RI.getFrameRegister(*MF))); - - if (MFI->adjustsStack()) - CPUBitmask |= (1 << MipsRegisterInfo:: - getRegisterNumbering(RI.getRARegister())); - - // Print CPUBitmask - O << "\t.mask \t"; printHex32(CPUBitmask, O); - O << ',' << MipsFI->getCPUTopSavedRegOff() << '\n'; - - // Print FPUBitmask - O << "\t.fmask\t"; printHex32(FPUBitmask, O); O << "," - << MipsFI->getFPUTopSavedRegOff() << '\n'; -} - -// Print a 32 bit hex number with all numbers. -void MipsAsmPrinter::printHex32(unsigned Value, raw_ostream &O) { - O << "0x"; - for (int i = 7; i >= 0; i--) - O << utohexstr((Value & (0xF << (i*4))) >> (i*4)); -} - -//===----------------------------------------------------------------------===// -// Frame and Set directives -//===----------------------------------------------------------------------===// - -/// Frame Directive -void MipsAsmPrinter::emitFrameDirective() { - const TargetRegisterInfo &RI = *TM.getRegisterInfo(); - - unsigned stackReg = RI.getFrameRegister(*MF); - unsigned returnReg = RI.getRARegister(); - unsigned stackSize = MF->getFrameInfo()->getStackSize(); - - OutStreamer.EmitRawText("\t.frame\t$" + - Twine(LowercaseString(getRegisterName(stackReg))) + - "," + Twine(stackSize) + ",$" + - Twine(LowercaseString(getRegisterName(returnReg)))); -} - -/// Emit Set directives. -const char *MipsAsmPrinter::getCurrentABIString() const { - switch (Subtarget->getTargetABI()) { - case MipsSubtarget::O32: return "abi32"; - case MipsSubtarget::O64: return "abiO64"; - case MipsSubtarget::N32: return "abiN32"; - case MipsSubtarget::N64: return "abi64"; - case MipsSubtarget::EABI: return "eabi32"; // TODO: handle eabi64 - default: break; - } - - llvm_unreachable("Unknown Mips ABI"); - return NULL; -} - -void MipsAsmPrinter::EmitFunctionEntryLabel() { - OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); - OutStreamer.EmitLabel(CurrentFnSym); -} - -/// EmitFunctionBodyStart - Targets can override this to emit stuff before -/// the first basic block in the function. -void MipsAsmPrinter::EmitFunctionBodyStart() { - emitFrameDirective(); - - SmallString<128> Str; - raw_svector_ostream OS(Str); - printSavedRegsBitmask(OS); - OutStreamer.EmitRawText(OS.str()); -} - -/// EmitFunctionBodyEnd - Targets can override this to emit stuff after -/// the last basic block in the function. -void MipsAsmPrinter::EmitFunctionBodyEnd() { - // There are instruction for this macros, but they must - // always be at the function end, and we can't emit and - // break with BB logic. - OutStreamer.EmitRawText(StringRef("\t.set\tmacro")); - OutStreamer.EmitRawText(StringRef("\t.set\treorder")); - OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); -} - - -/// isBlockOnlyReachableByFallthough - Return true if the basic block has -/// exactly one predecessor and the control transfer mechanism between -/// the predecessor and this block is a fall-through. -bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) - const { - // The predecessor has to be immediately before this block. - const MachineBasicBlock *Pred = *MBB->pred_begin(); - - // If the predecessor is a switch statement, assume a jump table - // implementation, so it is not a fall through. - if (const BasicBlock *bb = Pred->getBasicBlock()) - if (isa(bb->getTerminator())) - return false; - - return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB); -} - -// Print out an operand for an inline asm expression. -bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant,const char *ExtraCode, - raw_ostream &O) { - // Does this asm operand have a single letter operand modifier? - if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier. - - printOperand(MI, OpNo, O); - return false; -} - -void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, - raw_ostream &O) { - const MachineOperand &MO = MI->getOperand(opNum); - bool closeP = false; - - if (MO.getTargetFlags()) - closeP = true; - - switch(MO.getTargetFlags()) { - case MipsII::MO_GPREL: O << "%gp_rel("; break; - case MipsII::MO_GOT_CALL: O << "%call16("; break; - case MipsII::MO_GOT: - if (MI->getOpcode() == Mips::LW) - O << "%got("; - else - O << "%lo("; - break; - case MipsII::MO_ABS_HILO: - if (MI->getOpcode() == Mips::LUi) - O << "%hi("; - else - O << "%lo("; - break; - } - - switch (MO.getType()) { - case MachineOperand::MO_Register: - O << '$' << LowercaseString(getRegisterName(MO.getReg())); - break; - - case MachineOperand::MO_Immediate: - O << (short int)MO.getImm(); - break; - - case MachineOperand::MO_MachineBasicBlock: - O << *MO.getMBB()->getSymbol(); - return; - - case MachineOperand::MO_GlobalAddress: - O << *Mang->getSymbol(MO.getGlobal()); - break; - - case MachineOperand::MO_ExternalSymbol: - O << *GetExternalSymbolSymbol(MO.getSymbolName()); - break; - - case MachineOperand::MO_JumpTableIndex: - O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getIndex(); - break; - - case MachineOperand::MO_ConstantPoolIndex: - O << MAI->getPrivateGlobalPrefix() << "CPI" - << getFunctionNumber() << "_" << MO.getIndex(); - if (MO.getOffset()) - O << "+" << MO.getOffset(); - break; - - default: - llvm_unreachable(""); - } - - if (closeP) O << ")"; -} - -void MipsAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, - raw_ostream &O) { - const MachineOperand &MO = MI->getOperand(opNum); - if (MO.isImm()) - O << (unsigned short int)MO.getImm(); - else - printOperand(MI, opNum, O); -} - -void MipsAsmPrinter:: -printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, - const char *Modifier) { - // when using stack locations for not load/store instructions - // print the same way as all normal 3 operand instructions. - if (Modifier && !strcmp(Modifier, "stackloc")) { - printOperand(MI, opNum+1, O); - O << ", "; - printOperand(MI, opNum, O); - return; - } - - // Load/Store memory operands -- imm($reg) - // If PIC target the target is loaded as the - // pattern lw $25,%call16($28) - printOperand(MI, opNum, O); - O << "("; - printOperand(MI, opNum+1, O); - O << ")"; -} - -void MipsAsmPrinter:: -printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, - const char *Modifier) { - const MachineOperand& MO = MI->getOperand(opNum); - O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); -} - -void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { - // FIXME: Use SwitchSection. - - // Tell the assembler which ABI we are using - OutStreamer.EmitRawText("\t.section .mdebug." + Twine(getCurrentABIString())); - - // TODO: handle O64 ABI - if (Subtarget->isABI_EABI()) { - if (Subtarget->isGP32bit()) - OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long32")); - else - OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long64")); - } - - // return to previous section - OutStreamer.EmitRawText(StringRef("\t.previous")); -} - -// Force static initialization. -extern "C" void LLVMInitializeMipsAsmPrinter() { - RegisterAsmPrinter X(TheMipsTarget); - RegisterAsmPrinter Y(TheMipselTarget); -} diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index 78767e52e1d..dda6da9fc3f 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -11,6 +11,7 @@ tablegen(MipsGenCallingConv.inc -gen-callingconv) tablegen(MipsGenSubtarget.inc -gen-subtarget) add_llvm_target(MipsCodeGen + MipsAsmPrinter.cpp MipsDelaySlotFiller.cpp MipsInstrInfo.cpp MipsISelDAGToDAG.cpp diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile index 2ed8d77b85b..d16b066a624 100644 --- a/lib/Target/Mips/Makefile +++ b/lib/Target/Mips/Makefile @@ -18,7 +18,7 @@ BUILT_SOURCES = MipsGenRegisterInfo.h.inc MipsGenRegisterNames.inc \ MipsGenDAGISel.inc MipsGenCallingConv.inc \ MipsGenSubtarget.inc -DIRS = AsmPrinter TargetInfo +DIRS = TargetInfo include $(LEVEL)/Makefile.common diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp new file mode 100644 index 00000000000..6660f6b6243 --- /dev/null +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -0,0 +1,386 @@ +//===-- MipsAsmPrinter.cpp - Mips LLVM assembly writer --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file 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 GAS-format MIPS assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mips-asm-printer" +#include "Mips.h" +#include "MipsSubtarget.h" +#include "MipsInstrInfo.h" +#include "MipsTargetMachine.h" +#include "MipsMachineFunction.h" +#include "llvm/BasicBlock.h" +#include "llvm/Instructions.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + class MipsAsmPrinter : public AsmPrinter { + const MipsSubtarget *Subtarget; + public: + explicit MipsAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) { + Subtarget = &TM.getSubtarget(); + } + + virtual const char *getPassName() const { + return "Mips Assembly Printer"; + } + + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O); + void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, + const char *Modifier = 0); + void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, + const char *Modifier = 0); + void printSavedRegsBitmask(raw_ostream &O); + void printHex32(unsigned int Value, raw_ostream &O); + + const char *getCurrentABIString() const; + void emitFrameDirective(); + + void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen'd. + void EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); + } + virtual void EmitFunctionBodyStart(); + virtual void EmitFunctionBodyEnd(); + virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; + static const char *getRegisterName(unsigned RegNo); + + virtual void EmitFunctionEntryLabel(); + void EmitStartOfAsmFile(Module &M); + }; +} // end of anonymous namespace + +#include "MipsGenAsmWriter.inc" + +//===----------------------------------------------------------------------===// +// +// Mips Asm Directives +// +// -- Frame directive "frame Stackpointer, Stacksize, RARegister" +// Describe the stack frame. +// +// -- Mask directives "(f)mask bitmask, offset" +// Tells the assembler which registers are saved and where. +// bitmask - contain a little endian bitset indicating which registers are +// saved on function prologue (e.g. with a 0x80000000 mask, the +// assembler knows the register 31 (RA) is saved at prologue. +// offset - the position before stack pointer subtraction indicating where +// the first saved register on prologue is located. (e.g. with a +// +// Consider the following function prologue: +// +// .frame $fp,48,$ra +// .mask 0xc0000000,-8 +// addiu $sp, $sp, -48 +// sw $ra, 40($sp) +// sw $fp, 36($sp) +// +// With a 0xc0000000 mask, the assembler knows the register 31 (RA) and +// 30 (FP) are saved at prologue. As the save order on prologue is from +// left to right, RA is saved first. A -8 offset means that after the +// stack pointer subtration, the first register in the mask (RA) will be +// saved at address 48-8=40. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Mask directives +//===----------------------------------------------------------------------===// + +// Create a bitmask with all callee saved registers for CPU or Floating Point +// registers. For CPU registers consider RA, GP and FP for saving if necessary. +void MipsAsmPrinter::printSavedRegsBitmask(raw_ostream &O) { + const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + const MipsFunctionInfo *MipsFI = MF->getInfo(); + + // CPU and FPU Saved Registers Bitmasks + unsigned int CPUBitmask = 0; + unsigned int FPUBitmask = 0; + + // Set the CPU and FPU Bitmasks + const MachineFrameInfo *MFI = MF->getFrameInfo(); + const std::vector &CSI = MFI->getCalleeSavedInfo(); + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + unsigned RegNum = MipsRegisterInfo::getRegisterNumbering(Reg); + if (Mips::CPURegsRegisterClass->contains(Reg)) + CPUBitmask |= (1 << RegNum); + else + FPUBitmask |= (1 << RegNum); + } + + // Return Address and Frame registers must also be set in CPUBitmask. + if (RI.hasFP(*MF)) + CPUBitmask |= (1 << MipsRegisterInfo:: + getRegisterNumbering(RI.getFrameRegister(*MF))); + + if (MFI->adjustsStack()) + CPUBitmask |= (1 << MipsRegisterInfo:: + getRegisterNumbering(RI.getRARegister())); + + // Print CPUBitmask + O << "\t.mask \t"; printHex32(CPUBitmask, O); + O << ',' << MipsFI->getCPUTopSavedRegOff() << '\n'; + + // Print FPUBitmask + O << "\t.fmask\t"; printHex32(FPUBitmask, O); O << "," + << MipsFI->getFPUTopSavedRegOff() << '\n'; +} + +// Print a 32 bit hex number with all numbers. +void MipsAsmPrinter::printHex32(unsigned Value, raw_ostream &O) { + O << "0x"; + for (int i = 7; i >= 0; i--) + O << utohexstr((Value & (0xF << (i*4))) >> (i*4)); +} + +//===----------------------------------------------------------------------===// +// Frame and Set directives +//===----------------------------------------------------------------------===// + +/// Frame Directive +void MipsAsmPrinter::emitFrameDirective() { + const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + + unsigned stackReg = RI.getFrameRegister(*MF); + unsigned returnReg = RI.getRARegister(); + unsigned stackSize = MF->getFrameInfo()->getStackSize(); + + OutStreamer.EmitRawText("\t.frame\t$" + + Twine(LowercaseString(getRegisterName(stackReg))) + + "," + Twine(stackSize) + ",$" + + Twine(LowercaseString(getRegisterName(returnReg)))); +} + +/// Emit Set directives. +const char *MipsAsmPrinter::getCurrentABIString() const { + switch (Subtarget->getTargetABI()) { + case MipsSubtarget::O32: return "abi32"; + case MipsSubtarget::O64: return "abiO64"; + case MipsSubtarget::N32: return "abiN32"; + case MipsSubtarget::N64: return "abi64"; + case MipsSubtarget::EABI: return "eabi32"; // TODO: handle eabi64 + default: break; + } + + llvm_unreachable("Unknown Mips ABI"); + return NULL; +} + +void MipsAsmPrinter::EmitFunctionEntryLabel() { + OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); + OutStreamer.EmitLabel(CurrentFnSym); +} + +/// EmitFunctionBodyStart - Targets can override this to emit stuff before +/// the first basic block in the function. +void MipsAsmPrinter::EmitFunctionBodyStart() { + emitFrameDirective(); + + SmallString<128> Str; + raw_svector_ostream OS(Str); + printSavedRegsBitmask(OS); + OutStreamer.EmitRawText(OS.str()); +} + +/// EmitFunctionBodyEnd - Targets can override this to emit stuff after +/// the last basic block in the function. +void MipsAsmPrinter::EmitFunctionBodyEnd() { + // There are instruction for this macros, but they must + // always be at the function end, and we can't emit and + // break with BB logic. + OutStreamer.EmitRawText(StringRef("\t.set\tmacro")); + OutStreamer.EmitRawText(StringRef("\t.set\treorder")); + OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); +} + + +/// isBlockOnlyReachableByFallthough - Return true if the basic block has +/// exactly one predecessor and the control transfer mechanism between +/// the predecessor and this block is a fall-through. +bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) + const { + // The predecessor has to be immediately before this block. + const MachineBasicBlock *Pred = *MBB->pred_begin(); + + // If the predecessor is a switch statement, assume a jump table + // implementation, so it is not a fall through. + if (const BasicBlock *bb = Pred->getBasicBlock()) + if (isa(bb->getTerminator())) + return false; + + return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB); +} + +// Print out an operand for an inline asm expression. +bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant,const char *ExtraCode, + raw_ostream &O) { + // Does this asm operand have a single letter operand modifier? + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier. + + printOperand(MI, OpNo, O); + return false; +} + +void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(opNum); + bool closeP = false; + + if (MO.getTargetFlags()) + closeP = true; + + switch(MO.getTargetFlags()) { + case MipsII::MO_GPREL: O << "%gp_rel("; break; + case MipsII::MO_GOT_CALL: O << "%call16("; break; + case MipsII::MO_GOT: + if (MI->getOpcode() == Mips::LW) + O << "%got("; + else + O << "%lo("; + break; + case MipsII::MO_ABS_HILO: + if (MI->getOpcode() == Mips::LUi) + O << "%hi("; + else + O << "%lo("; + break; + } + + switch (MO.getType()) { + case MachineOperand::MO_Register: + O << '$' << LowercaseString(getRegisterName(MO.getReg())); + break; + + case MachineOperand::MO_Immediate: + O << (short int)MO.getImm(); + break; + + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + + case MachineOperand::MO_GlobalAddress: + O << *Mang->getSymbol(MO.getGlobal()); + break; + + case MachineOperand::MO_ExternalSymbol: + O << *GetExternalSymbolSymbol(MO.getSymbolName()); + break; + + case MachineOperand::MO_JumpTableIndex: + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" + << getFunctionNumber() << "_" << MO.getIndex(); + if (MO.getOffset()) + O << "+" << MO.getOffset(); + break; + + default: + llvm_unreachable(""); + } + + if (closeP) O << ")"; +} + +void MipsAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(opNum); + if (MO.isImm()) + O << (unsigned short int)MO.getImm(); + else + printOperand(MI, opNum, O); +} + +void MipsAsmPrinter:: +printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, + const char *Modifier) { + // when using stack locations for not load/store instructions + // print the same way as all normal 3 operand instructions. + if (Modifier && !strcmp(Modifier, "stackloc")) { + printOperand(MI, opNum+1, O); + O << ", "; + printOperand(MI, opNum, O); + return; + } + + // Load/Store memory operands -- imm($reg) + // If PIC target the target is loaded as the + // pattern lw $25,%call16($28) + printOperand(MI, opNum, O); + O << "("; + printOperand(MI, opNum+1, O); + O << ")"; +} + +void MipsAsmPrinter:: +printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, + const char *Modifier) { + const MachineOperand& MO = MI->getOperand(opNum); + O << Mips::MipsFCCToString((Mips::CondCode)MO.getImm()); +} + +void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { + // FIXME: Use SwitchSection. + + // Tell the assembler which ABI we are using + OutStreamer.EmitRawText("\t.section .mdebug." + Twine(getCurrentABIString())); + + // TODO: handle O64 ABI + if (Subtarget->isABI_EABI()) { + if (Subtarget->isGP32bit()) + OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long32")); + else + OutStreamer.EmitRawText(StringRef("\t.section .gcc_compiled_long64")); + } + + // return to previous section + OutStreamer.EmitRawText(StringRef("\t.previous")); +} + +// Force static initialization. +extern "C" void LLVMInitializeMipsAsmPrinter() { + RegisterAsmPrinter X(TheMipsTarget); + RegisterAsmPrinter Y(TheMipselTarget); +} diff --git a/lib/Target/PTX/AsmPrinter/CMakeLists.txt b/lib/Target/PTX/AsmPrinter/CMakeLists.txt deleted file mode 100644 index 3f4257b444b..00000000000 --- a/lib/Target/PTX/AsmPrinter/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - -add_llvm_library(LLVMPTXAsmPrinter - PTXAsmPrinter.cpp - ) -add_dependencies(LLVMPTXAsmPrinter PTXCodeGenTable_gen) diff --git a/lib/Target/PTX/AsmPrinter/Makefile b/lib/Target/PTX/AsmPrinter/Makefile deleted file mode 100644 index 67ee3bc34b3..00000000000 --- a/lib/Target/PTX/AsmPrinter/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/PTX/AsmPrinter/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMPTXAsmPrinter - -# Hack: we need to include 'main' PTX target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/lib/Target/PTX/AsmPrinter/PTXAsmPrinter.cpp b/lib/Target/PTX/AsmPrinter/PTXAsmPrinter.cpp deleted file mode 100644 index b861807b633..00000000000 --- a/lib/Target/PTX/AsmPrinter/PTXAsmPrinter.cpp +++ /dev/null @@ -1,190 +0,0 @@ -//===-- PTXAsmPrinter.cpp - PTX LLVM assembly writer ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file 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 PTX assembly language. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "ptx-asm-printer" - -#include "PTX.h" -#include "PTXMachineFunctionInfo.h" -#include "PTXTargetMachine.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Twine.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -namespace { -class PTXAsmPrinter : public AsmPrinter { -public: - explicit PTXAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) - : AsmPrinter(TM, Streamer) {} - - const char *getPassName() const { return "PTX Assembly Printer"; } - - virtual bool runOnMachineFunction(MachineFunction &MF); - - virtual void EmitFunctionBodyStart(); - virtual void EmitFunctionBodyEnd() { OutStreamer.EmitRawText(Twine("}")); } - - virtual void EmitInstruction(const MachineInstr *MI); - - void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); - - // autogen'd. - void printInstruction(const MachineInstr *MI, raw_ostream &OS); - static const char *getRegisterName(unsigned RegNo); - -private: - void EmitFunctionDeclaration(); -}; // class PTXAsmPrinter -} // namespace - -static const char PARAM_PREFIX[] = "__param_"; - -static const char *getRegisterTypeName(unsigned RegNo){ -#define TEST_REGCLS(cls, clsstr) \ - if (PTX::cls ## RegisterClass->contains(RegNo)) return # clsstr; - TEST_REGCLS(RRegs32, .s32); - TEST_REGCLS(Preds, .pred); -#undef TEST_REGCLS - - llvm_unreachable("Not in any register class!"); - return NULL; -} - -bool PTXAsmPrinter::runOnMachineFunction(MachineFunction &MF) { - SetupMachineFunction(MF); - EmitFunctionDeclaration(); - EmitFunctionBody(); - return false; -} - -void PTXAsmPrinter::EmitFunctionBodyStart() { - OutStreamer.EmitRawText(Twine("{")); - - const PTXMachineFunctionInfo *MFI = MF->getInfo(); - - // Print local variable definition - for (PTXMachineFunctionInfo::reg_iterator - i = MFI->localVarRegBegin(), e = MFI->localVarRegEnd(); i != e; ++ i) { - unsigned reg = *i; - - std::string def = "\t.reg "; - def += getRegisterTypeName(reg); - def += ' '; - def += getRegisterName(reg); - def += ';'; - OutStreamer.EmitRawText(Twine(def)); - } -} - -void PTXAsmPrinter::EmitInstruction(const MachineInstr *MI) { - SmallString<128> str; - raw_svector_ostream OS(str); - printInstruction(MI, OS); - OS << ';'; - OutStreamer.EmitRawText(OS.str()); -} - -void PTXAsmPrinter::printOperand(const MachineInstr *MI, int opNum, - raw_ostream &OS) { - const MachineOperand &MO = MI->getOperand(opNum); - - switch (MO.getType()) { - default: - llvm_unreachable(""); - break; - case MachineOperand::MO_Register: - OS << getRegisterName(MO.getReg()); - break; - case MachineOperand::MO_Immediate: - OS << (int) MO.getImm(); - break; - } -} - -void PTXAsmPrinter::EmitFunctionDeclaration() { - // The function label could have already been emitted if two symbols end up - // conflicting due to asm renaming. Detect this and emit an error. - if (!CurrentFnSym->isUndefined()) { - report_fatal_error("'" + Twine(CurrentFnSym->getName()) + - "' label emitted multiple times to assembly file"); - return; - } - - const PTXMachineFunctionInfo *MFI = MF->getInfo(); - const bool isKernel = MFI->isKernel(); - unsigned reg; - - std::string decl = isKernel ? ".entry" : ".func"; - - // Print return register - reg = MFI->retReg(); - if (!isKernel && reg != PTX::NoRegister) { - decl += " (.reg "; // FIXME: could it return in .param space? - decl += getRegisterTypeName(reg); - decl += " "; - decl += getRegisterName(reg); - decl += ")"; - } - - // Print function name - decl += " "; - decl += CurrentFnSym->getName().str(); - - // Print parameter list - if (!MFI->argRegEmpty()) { - decl += " ("; - if (isKernel) { - for (int i = 0, e = MFI->getNumArg(); i != e; ++i) { - if (i != 0) - decl += ", "; - decl += ".param .s32 "; // TODO: param's type - decl += PARAM_PREFIX; - decl += utostr(i + 1); - } - } else { - for (PTXMachineFunctionInfo::reg_iterator - i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i; i != e; ++i) { - reg = *i; - assert(reg != PTX::NoRegister && "Not a valid register!"); - if (i != b) - decl += ", "; - decl += ".reg "; - decl += getRegisterTypeName(reg); - decl += " "; - decl += getRegisterName(reg); - } - } - decl += ")"; - } - - OutStreamer.EmitRawText(Twine(decl)); -} - -#include "PTXGenAsmWriter.inc" - -// Force static initialization. -extern "C" void LLVMInitializePTXAsmPrinter() { - RegisterAsmPrinter X(ThePTXTarget); -} diff --git a/lib/Target/PTX/CMakeLists.txt b/lib/Target/PTX/CMakeLists.txt index 07b13ae53ca..d35d6d59a3a 100644 --- a/lib/Target/PTX/CMakeLists.txt +++ b/lib/Target/PTX/CMakeLists.txt @@ -10,6 +10,7 @@ tablegen(PTXGenRegisterNames.inc -gen-register-enums) tablegen(PTXGenSubtarget.inc -gen-subtarget) add_llvm_target(PTXCodeGen + PTXAsmPrinter.cpp PTXISelDAGToDAG.cpp PTXISelLowering.cpp PTXInstrInfo.cpp diff --git a/lib/Target/PTX/Makefile b/lib/Target/PTX/Makefile index cfb3b9c0f7f..2c40d699409 100644 --- a/lib/Target/PTX/Makefile +++ b/lib/Target/PTX/Makefile @@ -21,6 +21,6 @@ BUILT_SOURCES = PTXGenAsmWriter.inc \ PTXGenRegisterNames.inc \ PTXGenSubtarget.inc -DIRS = AsmPrinter TargetInfo +DIRS = TargetInfo include $(LEVEL)/Makefile.common diff --git a/lib/Target/PTX/PTXAsmPrinter.cpp b/lib/Target/PTX/PTXAsmPrinter.cpp new file mode 100644 index 00000000000..b861807b633 --- /dev/null +++ b/lib/Target/PTX/PTXAsmPrinter.cpp @@ -0,0 +1,190 @@ +//===-- PTXAsmPrinter.cpp - PTX LLVM assembly writer ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file 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 PTX assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "ptx-asm-printer" + +#include "PTX.h" +#include "PTXMachineFunctionInfo.h" +#include "PTXTargetMachine.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { +class PTXAsmPrinter : public AsmPrinter { +public: + explicit PTXAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) {} + + const char *getPassName() const { return "PTX Assembly Printer"; } + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void EmitFunctionBodyStart(); + virtual void EmitFunctionBodyEnd() { OutStreamer.EmitRawText(Twine("}")); } + + virtual void EmitInstruction(const MachineInstr *MI); + + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); + + // autogen'd. + void printInstruction(const MachineInstr *MI, raw_ostream &OS); + static const char *getRegisterName(unsigned RegNo); + +private: + void EmitFunctionDeclaration(); +}; // class PTXAsmPrinter +} // namespace + +static const char PARAM_PREFIX[] = "__param_"; + +static const char *getRegisterTypeName(unsigned RegNo){ +#define TEST_REGCLS(cls, clsstr) \ + if (PTX::cls ## RegisterClass->contains(RegNo)) return # clsstr; + TEST_REGCLS(RRegs32, .s32); + TEST_REGCLS(Preds, .pred); +#undef TEST_REGCLS + + llvm_unreachable("Not in any register class!"); + return NULL; +} + +bool PTXAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + SetupMachineFunction(MF); + EmitFunctionDeclaration(); + EmitFunctionBody(); + return false; +} + +void PTXAsmPrinter::EmitFunctionBodyStart() { + OutStreamer.EmitRawText(Twine("{")); + + const PTXMachineFunctionInfo *MFI = MF->getInfo(); + + // Print local variable definition + for (PTXMachineFunctionInfo::reg_iterator + i = MFI->localVarRegBegin(), e = MFI->localVarRegEnd(); i != e; ++ i) { + unsigned reg = *i; + + std::string def = "\t.reg "; + def += getRegisterTypeName(reg); + def += ' '; + def += getRegisterName(reg); + def += ';'; + OutStreamer.EmitRawText(Twine(def)); + } +} + +void PTXAsmPrinter::EmitInstruction(const MachineInstr *MI) { + SmallString<128> str; + raw_svector_ostream OS(str); + printInstruction(MI, OS); + OS << ';'; + OutStreamer.EmitRawText(OS.str()); +} + +void PTXAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &OS) { + const MachineOperand &MO = MI->getOperand(opNum); + + switch (MO.getType()) { + default: + llvm_unreachable(""); + break; + case MachineOperand::MO_Register: + OS << getRegisterName(MO.getReg()); + break; + case MachineOperand::MO_Immediate: + OS << (int) MO.getImm(); + break; + } +} + +void PTXAsmPrinter::EmitFunctionDeclaration() { + // The function label could have already been emitted if two symbols end up + // conflicting due to asm renaming. Detect this and emit an error. + if (!CurrentFnSym->isUndefined()) { + report_fatal_error("'" + Twine(CurrentFnSym->getName()) + + "' label emitted multiple times to assembly file"); + return; + } + + const PTXMachineFunctionInfo *MFI = MF->getInfo(); + const bool isKernel = MFI->isKernel(); + unsigned reg; + + std::string decl = isKernel ? ".entry" : ".func"; + + // Print return register + reg = MFI->retReg(); + if (!isKernel && reg != PTX::NoRegister) { + decl += " (.reg "; // FIXME: could it return in .param space? + decl += getRegisterTypeName(reg); + decl += " "; + decl += getRegisterName(reg); + decl += ")"; + } + + // Print function name + decl += " "; + decl += CurrentFnSym->getName().str(); + + // Print parameter list + if (!MFI->argRegEmpty()) { + decl += " ("; + if (isKernel) { + for (int i = 0, e = MFI->getNumArg(); i != e; ++i) { + if (i != 0) + decl += ", "; + decl += ".param .s32 "; // TODO: param's type + decl += PARAM_PREFIX; + decl += utostr(i + 1); + } + } else { + for (PTXMachineFunctionInfo::reg_iterator + i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i; i != e; ++i) { + reg = *i; + assert(reg != PTX::NoRegister && "Not a valid register!"); + if (i != b) + decl += ", "; + decl += ".reg "; + decl += getRegisterTypeName(reg); + decl += " "; + decl += getRegisterName(reg); + } + } + decl += ")"; + } + + OutStreamer.EmitRawText(Twine(decl)); +} + +#include "PTXGenAsmWriter.inc" + +// Force static initialization. +extern "C" void LLVMInitializePTXAsmPrinter() { + RegisterAsmPrinter X(ThePTXTarget); +} diff --git a/lib/Target/Sparc/AsmPrinter/CMakeLists.txt b/lib/Target/Sparc/AsmPrinter/CMakeLists.txt deleted file mode 100644 index da629f6e63f..00000000000 --- a/lib/Target/Sparc/AsmPrinter/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - -add_llvm_library(LLVMSparcAsmPrinter - SparcAsmPrinter.cpp - ) -add_dependencies(LLVMSparcAsmPrinter SparcCodeGenTable_gen) diff --git a/lib/Target/Sparc/AsmPrinter/Makefile b/lib/Target/Sparc/AsmPrinter/Makefile deleted file mode 100644 index fe475389c68..00000000000 --- a/lib/Target/Sparc/AsmPrinter/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/Sparc/AsmPrinter/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMSparcAsmPrinter - -# Hack: we need to include 'main' Sparc target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp deleted file mode 100644 index ab948bb37ff..00000000000 --- a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp +++ /dev/null @@ -1,249 +0,0 @@ -//===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file 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 GAS-format SPARC assembly language. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "asm-printer" -#include "Sparc.h" -#include "SparcInstrInfo.h" -#include "SparcTargetMachine.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -namespace { - class SparcAsmPrinter : public AsmPrinter { - public: - explicit SparcAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) - : AsmPrinter(TM, Streamer) {} - - virtual const char *getPassName() const { - return "Sparc Assembly Printer"; - } - - void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); - void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS, - const char *Modifier = 0); - void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); - - virtual void EmitInstruction(const MachineInstr *MI) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - printInstruction(MI, OS); - OutStreamer.EmitRawText(OS.str()); - } - void printInstruction(const MachineInstr *MI, raw_ostream &OS);// autogen'd. - static const char *getRegisterName(unsigned RegNo); - - bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O); - bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O); - - bool printGetPCX(const MachineInstr *MI, unsigned OpNo, raw_ostream &OS); - - virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) - const; - }; -} // end of anonymous namespace - -#include "SparcGenAsmWriter.inc" - -void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum, - raw_ostream &O) { - const MachineOperand &MO = MI->getOperand (opNum); - bool CloseParen = false; - if (MI->getOpcode() == SP::SETHIi && !MO.isReg() && !MO.isImm()) { - O << "%hi("; - CloseParen = true; - } else if ((MI->getOpcode() == SP::ORri || MI->getOpcode() == SP::ADDri) && - !MO.isReg() && !MO.isImm()) { - O << "%lo("; - CloseParen = true; - } - switch (MO.getType()) { - case MachineOperand::MO_Register: - O << "%" << LowercaseString(getRegisterName(MO.getReg())); - break; - - case MachineOperand::MO_Immediate: - O << (int)MO.getImm(); - break; - case MachineOperand::MO_MachineBasicBlock: - O << *MO.getMBB()->getSymbol(); - return; - case MachineOperand::MO_GlobalAddress: - O << *Mang->getSymbol(MO.getGlobal()); - break; - case MachineOperand::MO_ExternalSymbol: - O << MO.getSymbolName(); - break; - case MachineOperand::MO_ConstantPoolIndex: - O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" - << MO.getIndex(); - break; - default: - llvm_unreachable(""); - } - if (CloseParen) O << ")"; -} - -void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, - raw_ostream &O, const char *Modifier) { - printOperand(MI, opNum, O); - - // If this is an ADD operand, emit it like normal operands. - if (Modifier && !strcmp(Modifier, "arith")) { - O << ", "; - printOperand(MI, opNum+1, O); - return; - } - - if (MI->getOperand(opNum+1).isReg() && - MI->getOperand(opNum+1).getReg() == SP::G0) - return; // don't print "+%g0" - if (MI->getOperand(opNum+1).isImm() && - MI->getOperand(opNum+1).getImm() == 0) - return; // don't print "+0" - - O << "+"; - if (MI->getOperand(opNum+1).isGlobal() || - MI->getOperand(opNum+1).isCPI()) { - O << "%lo("; - printOperand(MI, opNum+1, O); - O << ")"; - } else { - printOperand(MI, opNum+1, O); - } -} - -bool SparcAsmPrinter::printGetPCX(const MachineInstr *MI, unsigned opNum, - raw_ostream &O) { - std::string operand = ""; - const MachineOperand &MO = MI->getOperand(opNum); - switch (MO.getType()) { - default: assert(0 && "Operand is not a register "); - case MachineOperand::MO_Register: - assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && - "Operand is not a physical register "); - operand = "%" + LowercaseString(getRegisterName(MO.getReg())); - break; - } - - unsigned mfNum = MI->getParent()->getParent()->getFunctionNumber(); - unsigned bbNum = MI->getParent()->getNumber(); - - O << '\n' << ".LLGETPCH" << mfNum << '_' << bbNum << ":\n"; - O << "\tcall\t.LLGETPC" << mfNum << '_' << bbNum << '\n' ; - - O << "\t sethi\t" - << "%hi(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum << ")), " - << operand << '\n' ; - - O << ".LLGETPC" << mfNum << '_' << bbNum << ":\n" ; - O << "\tor\t" << operand - << ", %lo(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum - << ")), " << operand << '\n'; - O << "\tadd\t" << operand << ", %o7, " << operand << '\n'; - - return true; -} - -void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum, - raw_ostream &O) { - int CC = (int)MI->getOperand(opNum).getImm(); - O << SPARCCondCodeToString((SPCC::CondCodes)CC); -} - -/// PrintAsmOperand - Print out an operand for an inline asm expression. -/// -bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode, - raw_ostream &O) { - if (ExtraCode && ExtraCode[0]) { - if (ExtraCode[1] != 0) return true; // Unknown modifier. - - switch (ExtraCode[0]) { - default: return true; // Unknown modifier. - case 'r': - break; - } - } - - printOperand(MI, OpNo, O); - - return false; -} - -bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, - unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode, - raw_ostream &O) { - if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier - - O << '['; - printMemOperand(MI, OpNo, O); - O << ']'; - - return false; -} - -/// isBlockOnlyReachableByFallthough - Return true if the basic block has -/// exactly one predecessor and the control transfer mechanism between -/// the predecessor and this block is a fall-through. -/// -/// This overrides AsmPrinter's implementation to handle delay slots. -bool SparcAsmPrinter:: -isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { - // If this is a landing pad, it isn't a fall through. If it has no preds, - // then nothing falls through to it. - if (MBB->isLandingPad() || MBB->pred_empty()) - return false; - - // If there isn't exactly one predecessor, it can't be a fall through. - MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; - ++PI2; - if (PI2 != MBB->pred_end()) - return false; - - // The predecessor has to be immediately before this block. - const MachineBasicBlock *Pred = *PI; - - if (!Pred->isLayoutSuccessor(MBB)) - return false; - - // Check if the last terminator is an unconditional branch. - MachineBasicBlock::const_iterator I = Pred->end(); - while (I != Pred->begin() && !(--I)->getDesc().isTerminator()) - ; // Noop - return I == Pred->end() || !I->getDesc().isBarrier(); -} - - - -// Force static initialization. -extern "C" void LLVMInitializeSparcAsmPrinter() { - RegisterAsmPrinter X(TheSparcTarget); - RegisterAsmPrinter Y(TheSparcV9Target); -} diff --git a/lib/Target/Sparc/CMakeLists.txt b/lib/Target/Sparc/CMakeLists.txt index b789fa7ad5f..9ed85e03cfa 100644 --- a/lib/Target/Sparc/CMakeLists.txt +++ b/lib/Target/Sparc/CMakeLists.txt @@ -13,6 +13,7 @@ tablegen(SparcGenCallingConv.inc -gen-callingconv) add_llvm_target(SparcCodeGen DelaySlotFiller.cpp FPMover.cpp + SparcAsmPrinter.cpp SparcInstrInfo.cpp SparcISelDAGToDAG.cpp SparcISelLowering.cpp diff --git a/lib/Target/Sparc/Makefile b/lib/Target/Sparc/Makefile index e4078487e16..27942c56fb3 100644 --- a/lib/Target/Sparc/Makefile +++ b/lib/Target/Sparc/Makefile @@ -17,7 +17,7 @@ BUILT_SOURCES = SparcGenRegisterInfo.h.inc SparcGenRegisterNames.inc \ SparcGenInstrInfo.inc SparcGenAsmWriter.inc \ SparcGenDAGISel.inc SparcGenSubtarget.inc SparcGenCallingConv.inc -DIRS = AsmPrinter TargetInfo +DIRS = TargetInfo include $(LEVEL)/Makefile.common diff --git a/lib/Target/Sparc/SparcAsmPrinter.cpp b/lib/Target/Sparc/SparcAsmPrinter.cpp new file mode 100644 index 00000000000..ab948bb37ff --- /dev/null +++ b/lib/Target/Sparc/SparcAsmPrinter.cpp @@ -0,0 +1,249 @@ +//===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file 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 GAS-format SPARC assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "Sparc.h" +#include "SparcInstrInfo.h" +#include "SparcTargetMachine.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + class SparcAsmPrinter : public AsmPrinter { + public: + explicit SparcAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) {} + + virtual const char *getPassName() const { + return "Sparc Assembly Printer"; + } + + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); + void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS, + const char *Modifier = 0); + void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); + + virtual void EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); + } + void printInstruction(const MachineInstr *MI, raw_ostream &OS);// autogen'd. + static const char *getRegisterName(unsigned RegNo); + + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + + bool printGetPCX(const MachineInstr *MI, unsigned OpNo, raw_ostream &OS); + + virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) + const; + }; +} // end of anonymous namespace + +#include "SparcGenAsmWriter.inc" + +void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand (opNum); + bool CloseParen = false; + if (MI->getOpcode() == SP::SETHIi && !MO.isReg() && !MO.isImm()) { + O << "%hi("; + CloseParen = true; + } else if ((MI->getOpcode() == SP::ORri || MI->getOpcode() == SP::ADDri) && + !MO.isReg() && !MO.isImm()) { + O << "%lo("; + CloseParen = true; + } + switch (MO.getType()) { + case MachineOperand::MO_Register: + O << "%" << LowercaseString(getRegisterName(MO.getReg())); + break; + + case MachineOperand::MO_Immediate: + O << (int)MO.getImm(); + break; + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + case MachineOperand::MO_GlobalAddress: + O << *Mang->getSymbol(MO.getGlobal()); + break; + case MachineOperand::MO_ExternalSymbol: + O << MO.getSymbolName(); + break; + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" + << MO.getIndex(); + break; + default: + llvm_unreachable(""); + } + if (CloseParen) O << ")"; +} + +void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, + raw_ostream &O, const char *Modifier) { + printOperand(MI, opNum, O); + + // If this is an ADD operand, emit it like normal operands. + if (Modifier && !strcmp(Modifier, "arith")) { + O << ", "; + printOperand(MI, opNum+1, O); + return; + } + + if (MI->getOperand(opNum+1).isReg() && + MI->getOperand(opNum+1).getReg() == SP::G0) + return; // don't print "+%g0" + if (MI->getOperand(opNum+1).isImm() && + MI->getOperand(opNum+1).getImm() == 0) + return; // don't print "+0" + + O << "+"; + if (MI->getOperand(opNum+1).isGlobal() || + MI->getOperand(opNum+1).isCPI()) { + O << "%lo("; + printOperand(MI, opNum+1, O); + O << ")"; + } else { + printOperand(MI, opNum+1, O); + } +} + +bool SparcAsmPrinter::printGetPCX(const MachineInstr *MI, unsigned opNum, + raw_ostream &O) { + std::string operand = ""; + const MachineOperand &MO = MI->getOperand(opNum); + switch (MO.getType()) { + default: assert(0 && "Operand is not a register "); + case MachineOperand::MO_Register: + assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && + "Operand is not a physical register "); + operand = "%" + LowercaseString(getRegisterName(MO.getReg())); + break; + } + + unsigned mfNum = MI->getParent()->getParent()->getFunctionNumber(); + unsigned bbNum = MI->getParent()->getNumber(); + + O << '\n' << ".LLGETPCH" << mfNum << '_' << bbNum << ":\n"; + O << "\tcall\t.LLGETPC" << mfNum << '_' << bbNum << '\n' ; + + O << "\t sethi\t" + << "%hi(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum << ")), " + << operand << '\n' ; + + O << ".LLGETPC" << mfNum << '_' << bbNum << ":\n" ; + O << "\tor\t" << operand + << ", %lo(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum + << ")), " << operand << '\n'; + O << "\tadd\t" << operand << ", %o7, " << operand << '\n'; + + return true; +} + +void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + int CC = (int)MI->getOperand(opNum).getImm(); + O << SPARCCondCodeToString((SPCC::CondCodes)CC); +} + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'r': + break; + } + } + + printOperand(MI, OpNo, O); + + return false; +} + +bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier + + O << '['; + printMemOperand(MI, OpNo, O); + O << ']'; + + return false; +} + +/// isBlockOnlyReachableByFallthough - Return true if the basic block has +/// exactly one predecessor and the control transfer mechanism between +/// the predecessor and this block is a fall-through. +/// +/// This overrides AsmPrinter's implementation to handle delay slots. +bool SparcAsmPrinter:: +isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { + // If this is a landing pad, it isn't a fall through. If it has no preds, + // then nothing falls through to it. + if (MBB->isLandingPad() || MBB->pred_empty()) + return false; + + // If there isn't exactly one predecessor, it can't be a fall through. + MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; + ++PI2; + if (PI2 != MBB->pred_end()) + return false; + + // The predecessor has to be immediately before this block. + const MachineBasicBlock *Pred = *PI; + + if (!Pred->isLayoutSuccessor(MBB)) + return false; + + // Check if the last terminator is an unconditional branch. + MachineBasicBlock::const_iterator I = Pred->end(); + while (I != Pred->begin() && !(--I)->getDesc().isTerminator()) + ; // Noop + return I == Pred->end() || !I->getDesc().isBarrier(); +} + + + +// Force static initialization. +extern "C" void LLVMInitializeSparcAsmPrinter() { + RegisterAsmPrinter X(TheSparcTarget); + RegisterAsmPrinter Y(TheSparcV9Target); +} diff --git a/lib/Target/SystemZ/AsmPrinter/CMakeLists.txt b/lib/Target/SystemZ/AsmPrinter/CMakeLists.txt deleted file mode 100644 index c6be83a6108..00000000000 --- a/lib/Target/SystemZ/AsmPrinter/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - -add_llvm_library(LLVMSystemZAsmPrinter - SystemZAsmPrinter.cpp - ) -add_dependencies(LLVMSystemZAsmPrinter SystemZCodeGenTable_gen) diff --git a/lib/Target/SystemZ/AsmPrinter/Makefile b/lib/Target/SystemZ/AsmPrinter/Makefile deleted file mode 100644 index 0f90ed369f7..00000000000 --- a/lib/Target/SystemZ/AsmPrinter/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/SystemZ/AsmPrinter/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMSystemZAsmPrinter - -# Hack: we need to include 'main' SystemZ target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp b/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp deleted file mode 100644 index d7ac8f50b69..00000000000 --- a/lib/Target/SystemZ/AsmPrinter/SystemZAsmPrinter.cpp +++ /dev/null @@ -1,217 +0,0 @@ -//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly writer ---------------===// -// -// The LLVM Compiler Infrastructure -// -// This file 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 the SystemZ assembly language. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "asm-printer" -#include "SystemZ.h" -#include "SystemZInstrInfo.h" -#include "SystemZTargetMachine.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" -#include "llvm/Assembly/Writer.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -namespace { - class SystemZAsmPrinter : public AsmPrinter { - public: - SystemZAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) - : AsmPrinter(TM, Streamer) {} - - virtual const char *getPassName() const { - return "SystemZ Assembly Printer"; - } - - void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, - const char* Modifier = 0); - void printPCRelImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); - void printRIAddrOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, - const char* Modifier = 0); - void printRRIAddrOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, - const char* Modifier = 0); - void printS16ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) { - O << (int16_t)MI->getOperand(OpNum).getImm(); - } - void printS32ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) { - O << (int32_t)MI->getOperand(OpNum).getImm(); - } - - void printInstruction(const MachineInstr *MI, raw_ostream &O); - static const char *getRegisterName(unsigned RegNo); - - void EmitInstruction(const MachineInstr *MI); - }; -} // end of anonymous namespace - -#include "SystemZGenAsmWriter.inc" - -void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - printInstruction(MI, OS); - OutStreamer.EmitRawText(OS.str()); -} - -void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum, - raw_ostream &O) { - const MachineOperand &MO = MI->getOperand(OpNum); - switch (MO.getType()) { - case MachineOperand::MO_Immediate: - O << MO.getImm(); - return; - case MachineOperand::MO_MachineBasicBlock: - O << *MO.getMBB()->getSymbol(); - return; - case MachineOperand::MO_GlobalAddress: { - const GlobalValue *GV = MO.getGlobal(); - O << *Mang->getSymbol(GV); - - // Assemble calls via PLT for externally visible symbols if PIC. - if (TM.getRelocationModel() == Reloc::PIC_ && - !GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() && - !GV->hasLocalLinkage()) - O << "@PLT"; - - printOffset(MO.getOffset(), O); - return; - } - case MachineOperand::MO_ExternalSymbol: { - std::string Name(MAI->getGlobalPrefix()); - Name += MO.getSymbolName(); - O << Name; - - if (TM.getRelocationModel() == Reloc::PIC_) - O << "@PLT"; - - return; - } - default: - assert(0 && "Not implemented yet!"); - } -} - - -void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, - raw_ostream &O, const char *Modifier) { - const MachineOperand &MO = MI->getOperand(OpNum); - switch (MO.getType()) { - case MachineOperand::MO_Register: { - assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && - "Virtual registers should be already mapped!"); - unsigned Reg = MO.getReg(); - if (Modifier && strncmp(Modifier, "subreg", 6) == 0) { - if (strncmp(Modifier + 7, "even", 4) == 0) - Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::subreg_32bit); - else if (strncmp(Modifier + 7, "odd", 3) == 0) - Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::subreg_odd32); - else - assert(0 && "Invalid subreg modifier"); - } - - O << '%' << getRegisterName(Reg); - return; - } - case MachineOperand::MO_Immediate: - O << MO.getImm(); - return; - case MachineOperand::MO_MachineBasicBlock: - O << *MO.getMBB()->getSymbol(); - return; - case MachineOperand::MO_JumpTableIndex: - O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' - << MO.getIndex(); - - return; - case MachineOperand::MO_ConstantPoolIndex: - O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' - << MO.getIndex(); - - printOffset(MO.getOffset(), O); - break; - case MachineOperand::MO_GlobalAddress: - O << *Mang->getSymbol(MO.getGlobal()); - break; - case MachineOperand::MO_ExternalSymbol: { - O << *GetExternalSymbolSymbol(MO.getSymbolName()); - break; - } - default: - assert(0 && "Not implemented yet!"); - } - - switch (MO.getTargetFlags()) { - default: assert(0 && "Unknown target flag on GV operand"); - case SystemZII::MO_NO_FLAG: - break; - case SystemZII::MO_GOTENT: O << "@GOTENT"; break; - case SystemZII::MO_PLT: O << "@PLT"; break; - } - - printOffset(MO.getOffset(), O); -} - -void SystemZAsmPrinter::printRIAddrOperand(const MachineInstr *MI, int OpNum, - raw_ostream &O, - const char *Modifier) { - const MachineOperand &Base = MI->getOperand(OpNum); - - // Print displacement operand. - printOperand(MI, OpNum+1, O); - - // Print base operand (if any) - if (Base.getReg()) { - O << '('; - printOperand(MI, OpNum, O); - O << ')'; - } -} - -void SystemZAsmPrinter::printRRIAddrOperand(const MachineInstr *MI, int OpNum, - raw_ostream &O, - const char *Modifier) { - const MachineOperand &Base = MI->getOperand(OpNum); - const MachineOperand &Index = MI->getOperand(OpNum+2); - - // Print displacement operand. - printOperand(MI, OpNum+1, O); - - // Print base operand (if any) - if (Base.getReg()) { - O << '('; - printOperand(MI, OpNum, O); - if (Index.getReg()) { - O << ','; - printOperand(MI, OpNum+2, O); - } - O << ')'; - } else - assert(!Index.getReg() && "Should allocate base register first!"); -} - -// Force static initialization. -extern "C" void LLVMInitializeSystemZAsmPrinter() { - RegisterAsmPrinter X(TheSystemZTarget); -} diff --git a/lib/Target/SystemZ/CMakeLists.txt b/lib/Target/SystemZ/CMakeLists.txt index e780934d514..8bbdfbd8a48 100644 --- a/lib/Target/SystemZ/CMakeLists.txt +++ b/lib/Target/SystemZ/CMakeLists.txt @@ -11,6 +11,7 @@ tablegen(SystemZGenCallingConv.inc -gen-callingconv) tablegen(SystemZGenSubtarget.inc -gen-subtarget) add_llvm_target(SystemZCodeGen + SystemZAsmPrinter.cpp SystemZISelDAGToDAG.cpp SystemZISelLowering.cpp SystemZInstrInfo.cpp diff --git a/lib/Target/SystemZ/Makefile b/lib/Target/SystemZ/Makefile index 5b44090f3f1..6930e14c061 100644 --- a/lib/Target/SystemZ/Makefile +++ b/lib/Target/SystemZ/Makefile @@ -17,7 +17,7 @@ BUILT_SOURCES = SystemZGenRegisterInfo.h.inc SystemZGenRegisterNames.inc \ SystemZGenInstrInfo.inc SystemZGenAsmWriter.inc \ SystemZGenDAGISel.inc SystemZGenSubtarget.inc SystemZGenCallingConv.inc -DIRS = AsmPrinter TargetInfo +DIRS = TargetInfo include $(LEVEL)/Makefile.common diff --git a/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/lib/Target/SystemZ/SystemZAsmPrinter.cpp new file mode 100644 index 00000000000..d7ac8f50b69 --- /dev/null +++ b/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -0,0 +1,217 @@ +//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly writer ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file 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 the SystemZ assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "SystemZ.h" +#include "SystemZInstrInfo.h" +#include "SystemZTargetMachine.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + class SystemZAsmPrinter : public AsmPrinter { + public: + SystemZAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) {} + + virtual const char *getPassName() const { + return "SystemZ Assembly Printer"; + } + + void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, + const char* Modifier = 0); + void printPCRelImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); + void printRIAddrOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, + const char* Modifier = 0); + void printRRIAddrOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, + const char* Modifier = 0); + void printS16ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) { + O << (int16_t)MI->getOperand(OpNum).getImm(); + } + void printS32ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) { + O << (int32_t)MI->getOperand(OpNum).getImm(); + } + + void printInstruction(const MachineInstr *MI, raw_ostream &O); + static const char *getRegisterName(unsigned RegNo); + + void EmitInstruction(const MachineInstr *MI); + }; +} // end of anonymous namespace + +#include "SystemZGenAsmWriter.inc" + +void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream OS(Str); + printInstruction(MI, OS); + OutStreamer.EmitRawText(OS.str()); +} + +void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(OpNum); + switch (MO.getType()) { + case MachineOperand::MO_Immediate: + O << MO.getImm(); + return; + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + case MachineOperand::MO_GlobalAddress: { + const GlobalValue *GV = MO.getGlobal(); + O << *Mang->getSymbol(GV); + + // Assemble calls via PLT for externally visible symbols if PIC. + if (TM.getRelocationModel() == Reloc::PIC_ && + !GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() && + !GV->hasLocalLinkage()) + O << "@PLT"; + + printOffset(MO.getOffset(), O); + return; + } + case MachineOperand::MO_ExternalSymbol: { + std::string Name(MAI->getGlobalPrefix()); + Name += MO.getSymbolName(); + O << Name; + + if (TM.getRelocationModel() == Reloc::PIC_) + O << "@PLT"; + + return; + } + default: + assert(0 && "Not implemented yet!"); + } +} + + +void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O, const char *Modifier) { + const MachineOperand &MO = MI->getOperand(OpNum); + switch (MO.getType()) { + case MachineOperand::MO_Register: { + assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && + "Virtual registers should be already mapped!"); + unsigned Reg = MO.getReg(); + if (Modifier && strncmp(Modifier, "subreg", 6) == 0) { + if (strncmp(Modifier + 7, "even", 4) == 0) + Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::subreg_32bit); + else if (strncmp(Modifier + 7, "odd", 3) == 0) + Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::subreg_odd32); + else + assert(0 && "Invalid subreg modifier"); + } + + O << '%' << getRegisterName(Reg); + return; + } + case MachineOperand::MO_Immediate: + O << MO.getImm(); + return; + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + case MachineOperand::MO_JumpTableIndex: + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_' + << MO.getIndex(); + + return; + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' + << MO.getIndex(); + + printOffset(MO.getOffset(), O); + break; + case MachineOperand::MO_GlobalAddress: + O << *Mang->getSymbol(MO.getGlobal()); + break; + case MachineOperand::MO_ExternalSymbol: { + O << *GetExternalSymbolSymbol(MO.getSymbolName()); + break; + } + default: + assert(0 && "Not implemented yet!"); + } + + switch (MO.getTargetFlags()) { + default: assert(0 && "Unknown target flag on GV operand"); + case SystemZII::MO_NO_FLAG: + break; + case SystemZII::MO_GOTENT: O << "@GOTENT"; break; + case SystemZII::MO_PLT: O << "@PLT"; break; + } + + printOffset(MO.getOffset(), O); +} + +void SystemZAsmPrinter::printRIAddrOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O, + const char *Modifier) { + const MachineOperand &Base = MI->getOperand(OpNum); + + // Print displacement operand. + printOperand(MI, OpNum+1, O); + + // Print base operand (if any) + if (Base.getReg()) { + O << '('; + printOperand(MI, OpNum, O); + O << ')'; + } +} + +void SystemZAsmPrinter::printRRIAddrOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O, + const char *Modifier) { + const MachineOperand &Base = MI->getOperand(OpNum); + const MachineOperand &Index = MI->getOperand(OpNum+2); + + // Print displacement operand. + printOperand(MI, OpNum+1, O); + + // Print base operand (if any) + if (Base.getReg()) { + O << '('; + printOperand(MI, OpNum, O); + if (Index.getReg()) { + O << ','; + printOperand(MI, OpNum+2, O); + } + O << ')'; + } else + assert(!Index.getReg() && "Should allocate base register first!"); +} + +// Force static initialization. +extern "C" void LLVMInitializeSystemZAsmPrinter() { + RegisterAsmPrinter X(TheSystemZTarget); +} diff --git a/lib/Target/XCore/AsmPrinter/CMakeLists.txt b/lib/Target/XCore/AsmPrinter/CMakeLists.txt deleted file mode 100644 index 7c7c2f4ded0..00000000000 --- a/lib/Target/XCore/AsmPrinter/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - -add_llvm_library(LLVMXCoreAsmPrinter - XCoreAsmPrinter.cpp - ) -add_dependencies(LLVMXCoreAsmPrinter XCoreCodeGenTable_gen) diff --git a/lib/Target/XCore/AsmPrinter/Makefile b/lib/Target/XCore/AsmPrinter/Makefile deleted file mode 100644 index 581f736b743..00000000000 --- a/lib/Target/XCore/AsmPrinter/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/XCore/AsmPrinter/Makefile ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMXCoreAsmPrinter - -# Hack: we need to include 'main' XCore target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp b/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp deleted file mode 100644 index 8f06dd32662..00000000000 --- a/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp +++ /dev/null @@ -1,280 +0,0 @@ -//===-- XCoreAsmPrinter.cpp - XCore LLVM assembly writer ------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file 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 the XAS-format XCore assembly language. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "asm-printer" -#include "XCore.h" -#include "XCoreInstrInfo.h" -#include "XCoreSubtarget.h" -#include "XCoreMCAsmInfo.h" -#include "XCoreTargetMachine.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" -#include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/MachineJumpTableInfo.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -using namespace llvm; - -static cl::opt MaxThreads("xcore-max-threads", cl::Optional, - cl::desc("Maximum number of threads (for emulation thread-local storage)"), - cl::Hidden, - cl::value_desc("number"), - cl::init(8)); - -namespace { - class XCoreAsmPrinter : public AsmPrinter { - const XCoreSubtarget &Subtarget; - public: - explicit XCoreAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) - : AsmPrinter(TM, Streamer), Subtarget(TM.getSubtarget()){} - - virtual const char *getPassName() const { - return "XCore Assembly Printer"; - } - - void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O); - void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O, - const std::string &directive = ".jmptable"); - void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) { - printInlineJT(MI, opNum, O, ".jmptable32"); - } - void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); - bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &O); - - void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV); - virtual void EmitGlobalVariable(const GlobalVariable *GV); - - void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen'd. - static const char *getRegisterName(unsigned RegNo); - - void EmitFunctionEntryLabel(); - void EmitInstruction(const MachineInstr *MI); - void EmitFunctionBodyEnd(); - }; -} // end of anonymous namespace - -#include "XCoreGenAsmWriter.inc" - -void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) { - assert(((GV->hasExternalLinkage() || - GV->hasWeakLinkage()) || - GV->hasLinkOnceLinkage()) && "Unexpected linkage"); - if (const ArrayType *ATy = dyn_cast( - cast(GV->getType())->getElementType())) { - OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global); - // FIXME: MCStreamerize. - OutStreamer.EmitRawText(StringRef(".globound")); - OutStreamer.EmitRawText("\t.set\t" + Twine(Sym->getName())); - OutStreamer.EmitRawText(".globound," + Twine(ATy->getNumElements())); - if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { - // TODO Use COMDAT groups for LinkOnceLinkage - OutStreamer.EmitRawText(MAI->getWeakDefDirective() +Twine(Sym->getName())+ - ".globound"); - } - } -} - -void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { - // Check to see if this is a special global used by LLVM, if so, emit it. - if (!GV->hasInitializer() || - EmitSpecialLLVMGlobal(GV)) - return; - - const TargetData *TD = TM.getTargetData(); - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM)); - - - MCSymbol *GVSym = Mang->getSymbol(GV); - Constant *C = GV->getInitializer(); - unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); - - // Mark the start of the global - OutStreamer.EmitRawText("\t.cc_top " + Twine(GVSym->getName()) + ".data," + - GVSym->getName()); - - switch (GV->getLinkage()) { - case GlobalValue::AppendingLinkage: - report_fatal_error("AppendingLinkage is not supported by this target!"); - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - case GlobalValue::ExternalLinkage: - emitArrayBound(GVSym, GV); - OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); - - // TODO Use COMDAT groups for LinkOnceLinkage - if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) - OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); - // FALL THROUGH - case GlobalValue::InternalLinkage: - case GlobalValue::PrivateLinkage: - break; - case GlobalValue::DLLImportLinkage: - llvm_unreachable("DLLImport linkage is not supported by this target!"); - case GlobalValue::DLLExportLinkage: - llvm_unreachable("DLLExport linkage is not supported by this target!"); - default: - llvm_unreachable("Unknown linkage type!"); - } - - EmitAlignment(Align > 2 ? Align : 2, GV); - - unsigned Size = TD->getTypeAllocSize(C->getType()); - if (GV->isThreadLocal()) { - Size *= MaxThreads; - } - if (MAI->hasDotTypeDotSizeDirective()) { - OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); - OutStreamer.EmitRawText("\t.size " + Twine(GVSym->getName()) + "," + - Twine(Size)); - } - OutStreamer.EmitLabel(GVSym); - - EmitGlobalConstant(C); - if (GV->isThreadLocal()) { - for (unsigned i = 1; i < MaxThreads; ++i) - EmitGlobalConstant(C); - } - // The ABI requires that unsigned scalar types smaller than 32 bits - // are padded to 32 bits. - if (Size < 4) - OutStreamer.EmitZeros(4 - Size, 0); - - // Mark the end of the global - OutStreamer.EmitRawText("\t.cc_bottom " + Twine(GVSym->getName()) + ".data"); -} - -/// EmitFunctionBodyEnd - Targets can override this to emit stuff after -/// the last basic block in the function. -void XCoreAsmPrinter::EmitFunctionBodyEnd() { - // Emit function end directives - OutStreamer.EmitRawText("\t.cc_bottom " + Twine(CurrentFnSym->getName()) + - ".function"); -} - -void XCoreAsmPrinter::EmitFunctionEntryLabel() { - // Mark the start of the function - OutStreamer.EmitRawText("\t.cc_top " + Twine(CurrentFnSym->getName()) + - ".function," + CurrentFnSym->getName()); - OutStreamer.EmitLabel(CurrentFnSym); -} - -void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, - raw_ostream &O) { - printOperand(MI, opNum, O); - - if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0) - return; - - O << "+"; - printOperand(MI, opNum+1, O); -} - -void XCoreAsmPrinter:: -printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O, - const std::string &directive) { - unsigned JTI = MI->getOperand(opNum).getIndex(); - const MachineFunction *MF = MI->getParent()->getParent(); - const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); - const std::vector &JT = MJTI->getJumpTables(); - const std::vector &JTBBs = JT[JTI].MBBs; - O << "\t" << directive << " "; - for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { - MachineBasicBlock *MBB = JTBBs[i]; - if (i > 0) - O << ","; - O << *MBB->getSymbol(); - } -} - -void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum, - raw_ostream &O) { - const MachineOperand &MO = MI->getOperand(opNum); - switch (MO.getType()) { - case MachineOperand::MO_Register: - O << getRegisterName(MO.getReg()); - break; - case MachineOperand::MO_Immediate: - O << MO.getImm(); - break; - case MachineOperand::MO_MachineBasicBlock: - O << *MO.getMBB()->getSymbol(); - break; - case MachineOperand::MO_GlobalAddress: - O << *Mang->getSymbol(MO.getGlobal()); - break; - case MachineOperand::MO_ExternalSymbol: - O << MO.getSymbolName(); - break; - case MachineOperand::MO_ConstantPoolIndex: - O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() - << '_' << MO.getIndex(); - break; - case MachineOperand::MO_JumpTableIndex: - O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() - << '_' << MO.getIndex(); - break; - case MachineOperand::MO_BlockAddress: - O << *GetBlockAddressSymbol(MO.getBlockAddress()); - break; - default: - llvm_unreachable("not implemented"); - } -} - -/// PrintAsmOperand - Print out an operand for an inline asm expression. -/// -bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant,const char *ExtraCode, - raw_ostream &O) { - printOperand(MI, OpNo, O); - return false; -} - -void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) { - SmallString<128> Str; - raw_svector_ostream O(Str); - - // Check for mov mnemonic - if (MI->getOpcode() == XCore::ADD_2rus && !MI->getOperand(2).getImm()) - O << "\tmov " << getRegisterName(MI->getOperand(0).getReg()) << ", " - << getRegisterName(MI->getOperand(1).getReg()); - else - printInstruction(MI, O); - OutStreamer.EmitRawText(O.str()); -} - -// Force static initialization. -extern "C" void LLVMInitializeXCoreAsmPrinter() { - RegisterAsmPrinter X(TheXCoreTarget); -} diff --git a/lib/Target/XCore/CMakeLists.txt b/lib/Target/XCore/CMakeLists.txt index 38b35d7666c..d1c66a4d161 100644 --- a/lib/Target/XCore/CMakeLists.txt +++ b/lib/Target/XCore/CMakeLists.txt @@ -11,6 +11,7 @@ tablegen(XCoreGenCallingConv.inc -gen-callingconv) tablegen(XCoreGenSubtarget.inc -gen-subtarget) add_llvm_target(XCoreCodeGen + XCoreAsmPrinter.cpp XCoreFrameInfo.cpp XCoreInstrInfo.cpp XCoreISelDAGToDAG.cpp diff --git a/lib/Target/XCore/Makefile b/lib/Target/XCore/Makefile index 1b709745041..6c1ef886031 100644 --- a/lib/Target/XCore/Makefile +++ b/lib/Target/XCore/Makefile @@ -18,7 +18,7 @@ BUILT_SOURCES = XCoreGenRegisterInfo.h.inc XCoreGenRegisterNames.inc \ XCoreGenDAGISel.inc XCoreGenCallingConv.inc \ XCoreGenSubtarget.inc -DIRS = AsmPrinter TargetInfo +DIRS = TargetInfo include $(LEVEL)/Makefile.common diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp new file mode 100644 index 00000000000..8f06dd32662 --- /dev/null +++ b/lib/Target/XCore/XCoreAsmPrinter.cpp @@ -0,0 +1,280 @@ +//===-- XCoreAsmPrinter.cpp - XCore LLVM assembly writer ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file 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 the XAS-format XCore assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "XCore.h" +#include "XCoreInstrInfo.h" +#include "XCoreSubtarget.h" +#include "XCoreMCAsmInfo.h" +#include "XCoreTargetMachine.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +using namespace llvm; + +static cl::opt MaxThreads("xcore-max-threads", cl::Optional, + cl::desc("Maximum number of threads (for emulation thread-local storage)"), + cl::Hidden, + cl::value_desc("number"), + cl::init(8)); + +namespace { + class XCoreAsmPrinter : public AsmPrinter { + const XCoreSubtarget &Subtarget; + public: + explicit XCoreAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer), Subtarget(TM.getSubtarget()){} + + virtual const char *getPassName() const { + return "XCore Assembly Printer"; + } + + void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O, + const std::string &directive = ".jmptable"); + void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) { + printInlineJT(MI, opNum, O, ".jmptable32"); + } + void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + + void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV); + virtual void EmitGlobalVariable(const GlobalVariable *GV); + + void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen'd. + static const char *getRegisterName(unsigned RegNo); + + void EmitFunctionEntryLabel(); + void EmitInstruction(const MachineInstr *MI); + void EmitFunctionBodyEnd(); + }; +} // end of anonymous namespace + +#include "XCoreGenAsmWriter.inc" + +void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) { + assert(((GV->hasExternalLinkage() || + GV->hasWeakLinkage()) || + GV->hasLinkOnceLinkage()) && "Unexpected linkage"); + if (const ArrayType *ATy = dyn_cast( + cast(GV->getType())->getElementType())) { + OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global); + // FIXME: MCStreamerize. + OutStreamer.EmitRawText(StringRef(".globound")); + OutStreamer.EmitRawText("\t.set\t" + Twine(Sym->getName())); + OutStreamer.EmitRawText(".globound," + Twine(ATy->getNumElements())); + if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { + // TODO Use COMDAT groups for LinkOnceLinkage + OutStreamer.EmitRawText(MAI->getWeakDefDirective() +Twine(Sym->getName())+ + ".globound"); + } + } +} + +void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { + // Check to see if this is a special global used by LLVM, if so, emit it. + if (!GV->hasInitializer() || + EmitSpecialLLVMGlobal(GV)) + return; + + const TargetData *TD = TM.getTargetData(); + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM)); + + + MCSymbol *GVSym = Mang->getSymbol(GV); + Constant *C = GV->getInitializer(); + unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); + + // Mark the start of the global + OutStreamer.EmitRawText("\t.cc_top " + Twine(GVSym->getName()) + ".data," + + GVSym->getName()); + + switch (GV->getLinkage()) { + case GlobalValue::AppendingLinkage: + report_fatal_error("AppendingLinkage is not supported by this target!"); + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + case GlobalValue::ExternalLinkage: + emitArrayBound(GVSym, GV); + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + + // TODO Use COMDAT groups for LinkOnceLinkage + if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); + // FALL THROUGH + case GlobalValue::InternalLinkage: + case GlobalValue::PrivateLinkage: + break; + case GlobalValue::DLLImportLinkage: + llvm_unreachable("DLLImport linkage is not supported by this target!"); + case GlobalValue::DLLExportLinkage: + llvm_unreachable("DLLExport linkage is not supported by this target!"); + default: + llvm_unreachable("Unknown linkage type!"); + } + + EmitAlignment(Align > 2 ? Align : 2, GV); + + unsigned Size = TD->getTypeAllocSize(C->getType()); + if (GV->isThreadLocal()) { + Size *= MaxThreads; + } + if (MAI->hasDotTypeDotSizeDirective()) { + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); + OutStreamer.EmitRawText("\t.size " + Twine(GVSym->getName()) + "," + + Twine(Size)); + } + OutStreamer.EmitLabel(GVSym); + + EmitGlobalConstant(C); + if (GV->isThreadLocal()) { + for (unsigned i = 1; i < MaxThreads; ++i) + EmitGlobalConstant(C); + } + // The ABI requires that unsigned scalar types smaller than 32 bits + // are padded to 32 bits. + if (Size < 4) + OutStreamer.EmitZeros(4 - Size, 0); + + // Mark the end of the global + OutStreamer.EmitRawText("\t.cc_bottom " + Twine(GVSym->getName()) + ".data"); +} + +/// EmitFunctionBodyEnd - Targets can override this to emit stuff after +/// the last basic block in the function. +void XCoreAsmPrinter::EmitFunctionBodyEnd() { + // Emit function end directives + OutStreamer.EmitRawText("\t.cc_bottom " + Twine(CurrentFnSym->getName()) + + ".function"); +} + +void XCoreAsmPrinter::EmitFunctionEntryLabel() { + // Mark the start of the function + OutStreamer.EmitRawText("\t.cc_top " + Twine(CurrentFnSym->getName()) + + ".function," + CurrentFnSym->getName()); + OutStreamer.EmitLabel(CurrentFnSym); +} + +void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + printOperand(MI, opNum, O); + + if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0) + return; + + O << "+"; + printOperand(MI, opNum+1, O); +} + +void XCoreAsmPrinter:: +printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O, + const std::string &directive) { + unsigned JTI = MI->getOperand(opNum).getIndex(); + const MachineFunction *MF = MI->getParent()->getParent(); + const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); + const std::vector &JT = MJTI->getJumpTables(); + const std::vector &JTBBs = JT[JTI].MBBs; + O << "\t" << directive << " "; + for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { + MachineBasicBlock *MBB = JTBBs[i]; + if (i > 0) + O << ","; + O << *MBB->getSymbol(); + } +} + +void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(opNum); + switch (MO.getType()) { + case MachineOperand::MO_Register: + O << getRegisterName(MO.getReg()); + break; + case MachineOperand::MO_Immediate: + O << MO.getImm(); + break; + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + break; + case MachineOperand::MO_GlobalAddress: + O << *Mang->getSymbol(MO.getGlobal()); + break; + case MachineOperand::MO_ExternalSymbol: + O << MO.getSymbolName(); + break; + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + case MachineOperand::MO_JumpTableIndex: + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + case MachineOperand::MO_BlockAddress: + O << *GetBlockAddressSymbol(MO.getBlockAddress()); + break; + default: + llvm_unreachable("not implemented"); + } +} + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant,const char *ExtraCode, + raw_ostream &O) { + printOperand(MI, OpNo, O); + return false; +} + +void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream O(Str); + + // Check for mov mnemonic + if (MI->getOpcode() == XCore::ADD_2rus && !MI->getOperand(2).getImm()) + O << "\tmov " << getRegisterName(MI->getOperand(0).getReg()) << ", " + << getRegisterName(MI->getOperand(1).getReg()); + else + printInstruction(MI, O); + OutStreamer.EmitRawText(O.str()); +} + +// Force static initialization. +extern "C" void LLVMInitializeXCoreAsmPrinter() { + RegisterAsmPrinter X(TheXCoreTarget); +}