From 76a1dca38dbea9009cc16b6055e53497d3f756e4 Mon Sep 17 00:00:00 2001 From: Venkatraman Govindaraju Date: Thu, 26 Dec 2013 01:49:59 +0000 Subject: [PATCH] [Sparc] Lower and MachineInstr to MC and print assembly using MCInstPrinter. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198030 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Sparc/CMakeLists.txt | 1 + .../Sparc/InstPrinter/SparcInstPrinter.cpp | 3 +- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt | 1 + lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt | 2 +- .../Sparc/MCTargetDesc/SparcMCTargetDesc.cpp | 35 +++ .../MCTargetDesc/SparcTargetStreamer.cpp | 40 ++++ lib/Target/Sparc/Sparc.h | 6 + lib/Target/Sparc/Sparc.td | 7 - lib/Target/Sparc/SparcAsmPrinter.cpp | 203 ++++++++++++------ lib/Target/Sparc/SparcMCInstLower.cpp | 141 ++++++++++++ lib/Target/Sparc/SparcTargetStreamer.h | 47 ++++ test/CodeGen/SPARC/exception.ll | 2 +- 12 files changed, 417 insertions(+), 71 deletions(-) create mode 100644 lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp create mode 100644 lib/Target/Sparc/SparcMCInstLower.cpp create mode 100644 lib/Target/Sparc/SparcTargetStreamer.h diff --git a/lib/Target/Sparc/CMakeLists.txt b/lib/Target/Sparc/CMakeLists.txt index fb50656b97c..3aad2723aba 100644 --- a/lib/Target/Sparc/CMakeLists.txt +++ b/lib/Target/Sparc/CMakeLists.txt @@ -23,6 +23,7 @@ add_llvm_target(SparcCodeGen SparcSelectionDAGInfo.cpp SparcJITInfo.cpp SparcCodeEmitter.cpp + SparcMCInstLower.cpp ) add_subdirectory(TargetInfo) diff --git a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp index 1c5a334f249..d7bee72b747 100644 --- a/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +++ b/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp @@ -23,8 +23,7 @@ using namespace llvm; #define GET_INSTRUCTION_NAME -// Uncomment the following line once we are ready to use MCAsmWriter. -//#include "SparcGenAsmWriter.inc" +#include "SparcGenAsmWriter.inc" void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { diff --git a/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt b/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt index 8bf924e86d7..3a40fcaba47 100644 --- a/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt @@ -2,4 +2,5 @@ add_llvm_library(LLVMSparcDesc SparcMCTargetDesc.cpp SparcMCAsmInfo.cpp SparcMCExpr.cpp + SparcTargetStreamer.cpp ) diff --git a/lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt b/lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt index 97f8f162c27..22515e6d6dc 100644 --- a/lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt +++ b/lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt @@ -19,5 +19,5 @@ type = Library name = SparcDesc parent = Sparc -required_libraries = MC SparcInfo Support +required_libraries = MC SparcAsmPrinter SparcInfo Support add_to_library_groups = Sparc diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp index 1c64e1b0c4c..45e1d353695 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp @@ -13,6 +13,8 @@ #include "SparcMCTargetDesc.h" #include "SparcMCAsmInfo.h" +#include "SparcTargetStreamer.h" +#include "InstPrinter/SparcInstPrinter.h" #include "llvm/MC/MCCodeGenInfo.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" @@ -86,6 +88,28 @@ static MCCodeGenInfo *createSparcV9MCCodeGenInfo(StringRef TT, Reloc::Model RM, X->InitMCCodeGenInfo(RM, CM, OL); return X; } + +static MCStreamer * +createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + bool isVerboseAsm, bool useLoc, bool useCFI, + bool useDwarfDirectory, MCInstPrinter *InstPrint, + MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst) { + SparcTargetAsmStreamer *S = new SparcTargetAsmStreamer(OS); + + return llvm::createAsmStreamer(Ctx, S, OS, isVerboseAsm, useLoc, useCFI, + useDwarfDirectory, InstPrint, CE, TAB, + ShowInst); +} + +static MCInstPrinter *createSparcMCInstPrinter(const Target &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI, + const MCSubtargetInfo &STI) { + return new SparcInstPrinter(MAI, MII, MRI); +} + extern "C" void LLVMInitializeSparcTargetMC() { // Register the MC asm info. RegisterMCAsmInfo X(TheSparcTarget); @@ -106,4 +130,15 @@ extern "C" void LLVMInitializeSparcTargetMC() { // Register the MC subtarget info. TargetRegistry::RegisterMCSubtargetInfo(TheSparcTarget, createSparcMCSubtargetInfo); + + TargetRegistry::RegisterAsmStreamer(TheSparcTarget, + createMCAsmStreamer); + TargetRegistry::RegisterAsmStreamer(TheSparcV9Target, + createMCAsmStreamer); + + // Register the MCInstPrinter + TargetRegistry::RegisterMCInstPrinter(TheSparcTarget, + createSparcMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheSparcV9Target, + createSparcMCInstPrinter); } diff --git a/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp b/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp new file mode 100644 index 00000000000..01043aed5ee --- /dev/null +++ b/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp @@ -0,0 +1,40 @@ +//===-- SparcTargetStreamer.cpp - Sparc Target Streamer Methods -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Sparc specific target streamer methods. +// +//===----------------------------------------------------------------------===// + +#include "SparcTargetStreamer.h" +#include "InstPrinter/SparcInstPrinter.h" +#include "llvm/Support/FormattedStream.h" + +using namespace llvm; + +// pin vtable to this file +void SparcTargetStreamer::anchor() {} + +SparcTargetAsmStreamer::SparcTargetAsmStreamer(formatted_raw_ostream &OS) + : OS(OS) {} + +void SparcTargetAsmStreamer::emitSparcRegisterIgnore(unsigned reg) { + OS << "\t.register " + << "%" << StringRef(SparcInstPrinter::getRegisterName(reg)).lower() + << ", #ignore\n"; +} + +void SparcTargetAsmStreamer::emitSparcRegisterScratch(unsigned reg) { + OS << "\t.register " + << "%" << StringRef(SparcInstPrinter::getRegisterName(reg)).lower() + << ", #scratch\n"; +} + +MCELFStreamer &SparcTargetELFStreamer::getStreamer() { + return static_cast(*Streamer); +} diff --git a/lib/Target/Sparc/Sparc.h b/lib/Target/Sparc/Sparc.h index f44b60420d0..8d46c60255e 100644 --- a/lib/Target/Sparc/Sparc.h +++ b/lib/Target/Sparc/Sparc.h @@ -23,12 +23,18 @@ namespace llvm { class FunctionPass; class SparcTargetMachine; class formatted_raw_ostream; + class AsmPrinter; + class MCInst; + class MachineInstr; FunctionPass *createSparcISelDag(SparcTargetMachine &TM); FunctionPass *createSparcDelaySlotFillerPass(TargetMachine &TM); FunctionPass *createSparcJITCodeEmitterPass(SparcTargetMachine &TM, JITCodeEmitter &JCE); + void LowerSparcMachineInstrToMCInst(const MachineInstr *MI, + MCInst &OutMI, + AsmPrinter &AP); } // end namespace llvm; namespace llvm { diff --git a/lib/Target/Sparc/Sparc.td b/lib/Target/Sparc/Sparc.td index 097b565b88f..0df48f60e8f 100644 --- a/lib/Target/Sparc/Sparc.td +++ b/lib/Target/Sparc/Sparc.td @@ -66,11 +66,6 @@ def : Proc<"ultrasparc3", [FeatureV9, FeatureV8Deprecated]>; def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>; -def SparcAsmWriter : AsmWriter { - string AsmWriterClassName = "AsmPrinter"; - bit isMCAsmWriter = 0; -} - //===----------------------------------------------------------------------===// // Declare the target which we are implementing //===----------------------------------------------------------------------===// @@ -78,6 +73,4 @@ def SparcAsmWriter : AsmWriter { def Sparc : Target { // Pull in Instruction Info: let InstructionSet = SparcInstrInfo; - - let AssemblyWriters = [SparcAsmWriter]; } diff --git a/lib/Target/Sparc/SparcAsmPrinter.cpp b/lib/Target/Sparc/SparcAsmPrinter.cpp index d06c894c7e0..e787ed20a14 100644 --- a/lib/Target/Sparc/SparcAsmPrinter.cpp +++ b/lib/Target/Sparc/SparcAsmPrinter.cpp @@ -16,12 +16,17 @@ #include "Sparc.h" #include "SparcInstrInfo.h" #include "SparcTargetMachine.h" +#include "SparcTargetStreamer.h" +#include "InstPrinter/SparcInstPrinter.h" #include "MCTargetDesc/SparcBaseInfo.h" +#include "MCTargetDesc/SparcMCExpr.h" #include "llvm/ADT/SmallString.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInst.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/TargetRegistry.h" @@ -31,6 +36,9 @@ using namespace llvm; namespace { class SparcAsmPrinter : public AsmPrinter { + SparcTargetStreamer &getTargetStreamer() { + return static_cast(OutStreamer.getTargetStreamer()); + } public: explicit SparcAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) : AsmPrinter(TM, Streamer) {} @@ -45,14 +53,11 @@ namespace { void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS); virtual void EmitFunctionBodyStart(); - virtual void EmitInstruction(const MachineInstr *MI) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - printInstruction(MI, OS); - OutStreamer.EmitRawText(OS.str()); + virtual void EmitInstruction(const MachineInstr *MI); + + static const char *getRegisterName(unsigned RegNo) { + return SparcInstPrinter::getRegisterName(RegNo); } - 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, @@ -61,24 +66,138 @@ namespace { 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; - void EmitGlobalRegisterDecl(unsigned reg) { - SmallString<128> Str; - raw_svector_ostream OS(Str); - OS << "\t.register " - << "%" << StringRef(getRegisterName(reg)).lower() - << ", " - << ((reg == SP::G6 || reg == SP::G7)? "#ignore" : "#scratch"); - OutStreamer.EmitRawText(OS.str()); - } }; } // end of anonymous namespace -#include "SparcGenAsmWriter.inc" +static MCOperand createPCXCallOP(MCSymbol *Label, + MCContext &OutContext) +{ + const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Label, + OutContext); + const SparcMCExpr *expr = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_None, + MCSym, OutContext); + return MCOperand::CreateExpr(expr); +} + +static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind, + MCSymbol *GOTLabel, MCSymbol *StartLabel, + MCSymbol *CurLabel, + MCContext &OutContext) +{ + const MCSymbolRefExpr *GOT = MCSymbolRefExpr::Create(GOTLabel, OutContext); + const MCSymbolRefExpr *Start = MCSymbolRefExpr::Create(StartLabel, + OutContext); + const MCSymbolRefExpr *Cur = MCSymbolRefExpr::Create(CurLabel, + OutContext); + + const MCBinaryExpr *Sub = MCBinaryExpr::CreateSub(Cur, Start, OutContext); + const MCBinaryExpr *Add = MCBinaryExpr::CreateAdd(GOT, Sub, OutContext); + const SparcMCExpr *expr = SparcMCExpr::Create(Kind, + Add, OutContext); + return MCOperand::CreateExpr(expr); +} + +static void EmitCall(MCStreamer &OutStreamer, + MCOperand &Callee) +{ + MCInst CallInst; + CallInst.setOpcode(SP::CALL); + CallInst.addOperand(Callee); + OutStreamer.EmitInstruction(CallInst); +} + +static void EmitSETHI(MCStreamer &OutStreamer, + MCOperand &Imm, MCOperand &RD) +{ + MCInst SETHIInst; + SETHIInst.setOpcode(SP::SETHIi); + SETHIInst.addOperand(RD); + SETHIInst.addOperand(Imm); + OutStreamer.EmitInstruction(SETHIInst); +} + +static void EmitOR(MCStreamer &OutStreamer, MCOperand &RS1, + MCOperand &Imm, MCOperand &RD) +{ + MCInst ORInst; + ORInst.setOpcode(SP::ORri); + ORInst.addOperand(RD); + ORInst.addOperand(RS1); + ORInst.addOperand(Imm); + OutStreamer.EmitInstruction(ORInst); +} + +void EmitADD(MCStreamer &OutStreamer, + MCOperand &RS1, MCOperand &RS2, MCOperand &RD) +{ + MCInst ADDInst; + ADDInst.setOpcode(SP::ADDrr); + ADDInst.addOperand(RD); + ADDInst.addOperand(RS1); + ADDInst.addOperand(RS2); + OutStreamer.EmitInstruction(ADDInst); +} + +static void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI, + MCStreamer &OutStreamer, + MCContext &OutContext) +{ + const MachineOperand &MO = MI->getOperand(0); + MCSymbol *StartLabel = OutContext.CreateTempSymbol(); + MCSymbol *EndLabel = OutContext.CreateTempSymbol(); + MCSymbol *SethiLabel = OutContext.CreateTempSymbol(); + MCSymbol *GOTLabel = + OutContext.GetOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_")); + + assert(MO.getReg() != SP::O7 && + "%o7 is assigned as destination for getpcx!"); + + MCOperand MCRegOP = MCOperand::CreateReg(MO.getReg()); + MCOperand RegO7 = MCOperand::CreateReg(SP::O7); + + // : + // call + // : + // sethi %hi(_GLOBAL_OFFSET_TABLE_+(-)), + // : + // or , %lo(_GLOBAL_OFFSET_TABLE_+(-))), + // add , %o7, + + OutStreamer.EmitLabel(StartLabel); + MCOperand Callee = createPCXCallOP(EndLabel, OutContext); + EmitCall(OutStreamer, Callee); + OutStreamer.EmitLabel(SethiLabel); + MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_HI, + GOTLabel, StartLabel, SethiLabel, + OutContext); + EmitSETHI(OutStreamer, hiImm, MCRegOP); + OutStreamer.EmitLabel(EndLabel); + MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_LO, + GOTLabel, StartLabel, EndLabel, + OutContext); + EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP); + EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP); +} + +void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI) +{ + MCInst TmpInst; + + switch (MI->getOpcode()) { + default: break; + case TargetOpcode::DBG_VALUE: + // FIXME: Debug Value. + return; + case SP::GETPCX: + LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext); + return; + } + LowerSparcMachineInstrToMCInst(MI, TmpInst, *this); + OutStreamer.EmitInstruction(TmpInst); +} void SparcAsmPrinter::EmitFunctionBodyStart() { if (!TM.getSubtarget().is64Bit()) @@ -90,7 +209,11 @@ void SparcAsmPrinter::EmitFunctionBodyStart() { unsigned reg = globalRegs[i]; if (MRI.use_empty(reg)) continue; - EmitGlobalRegisterDecl(reg); + + if (reg == SP::G6 || reg == SP::G7) + getTargetStreamer().emitSparcRegisterIgnore(reg); + else + getTargetStreamer().emitSparcRegisterScratch(reg); } } @@ -226,46 +349,6 @@ void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum, 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: llvm_unreachable("Operand is not a register"); - case MachineOperand::MO_Register: - assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && - "Operand is not a physical register "); - assert(MO.getReg() != SP::O7 && - "%o7 is assigned as destination for getpcx!"); - operand = "%" + StringRef(getRegisterName(MO.getReg())).lower(); - 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, diff --git a/lib/Target/Sparc/SparcMCInstLower.cpp b/lib/Target/Sparc/SparcMCInstLower.cpp new file mode 100644 index 00000000000..f58a83c125e --- /dev/null +++ b/lib/Target/Sparc/SparcMCInstLower.cpp @@ -0,0 +1,141 @@ +//===-- SparcMCInstLower.cpp - Convert Sparc MachineInstr to MCInst -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains code to lower Sparc MachineInstrs to their corresponding +// MCInst records. +// +//===----------------------------------------------------------------------===// + +#include "Sparc.h" +#include "MCTargetDesc/SparcBaseInfo.h" +#include "MCTargetDesc/SparcMCExpr.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Target/Mangler.h" +#include "llvm/ADT/SmallString.h" + +using namespace llvm; + + +static MCOperand LowerSymbolOperand(const MachineInstr *MI, + const MachineOperand &MO, + AsmPrinter &AP) { + + SparcMCExpr::VariantKind Kind; + const MCSymbol *Symbol = 0; + + unsigned TF = MO.getTargetFlags(); + + switch(TF) { + default: llvm_unreachable("Unknown target flags on operand"); + case SPII::MO_NO_FLAG: Kind = SparcMCExpr::VK_Sparc_None; break; + case SPII::MO_LO: Kind = SparcMCExpr::VK_Sparc_LO; break; + case SPII::MO_HI: Kind = SparcMCExpr::VK_Sparc_HI; break; + case SPII::MO_H44: Kind = SparcMCExpr::VK_Sparc_H44; break; + case SPII::MO_M44: Kind = SparcMCExpr::VK_Sparc_M44; break; + case SPII::MO_L44: Kind = SparcMCExpr::VK_Sparc_L44; break; + case SPII::MO_HH: Kind = SparcMCExpr::VK_Sparc_HH; break; + case SPII::MO_HM: Kind = SparcMCExpr::VK_Sparc_HM; break; + case SPII::MO_TLS_GD_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_GD_HI22; break; + case SPII::MO_TLS_GD_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_GD_LO10; break; + case SPII::MO_TLS_GD_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_GD_ADD; break; + case SPII::MO_TLS_GD_CALL: Kind = SparcMCExpr::VK_Sparc_TLS_GD_CALL; break; + case SPII::MO_TLS_LDM_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_HI22; break; + case SPII::MO_TLS_LDM_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_LO10; break; + case SPII::MO_TLS_LDM_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_ADD; break; + case SPII::MO_TLS_LDM_CALL: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_CALL; break; + case SPII::MO_TLS_LDO_HIX22:Kind = SparcMCExpr::VK_Sparc_TLS_LDO_HIX22; break; + case SPII::MO_TLS_LDO_LOX10:Kind = SparcMCExpr::VK_Sparc_TLS_LDO_LOX10; break; + case SPII::MO_TLS_LDO_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_LDO_ADD; break; + case SPII::MO_TLS_IE_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_IE_HI22; break; + case SPII::MO_TLS_IE_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LO10; break; + case SPII::MO_TLS_IE_LD: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LD; break; + case SPII::MO_TLS_IE_LDX: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LDX; break; + case SPII::MO_TLS_IE_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_IE_ADD; break; + case SPII::MO_TLS_LE_HIX22: Kind = SparcMCExpr::VK_Sparc_TLS_LE_HIX22; break; + case SPII::MO_TLS_LE_LOX10: Kind = SparcMCExpr::VK_Sparc_TLS_LE_LOX10; break; + } + + switch(MO.getType()) { + default: llvm_unreachable("Unknown type in LowerSymbolOperand"); + case MachineOperand::MO_MachineBasicBlock: + Symbol = MO.getMBB()->getSymbol(); + break; + + case MachineOperand::MO_GlobalAddress: + Symbol = AP.getSymbol(MO.getGlobal()); + break; + + case MachineOperand::MO_BlockAddress: + Symbol = AP.GetBlockAddressSymbol(MO.getBlockAddress()); + break; + + case MachineOperand::MO_ExternalSymbol: + Symbol = AP.GetExternalSymbolSymbol(MO.getSymbolName()); + break; + + case MachineOperand::MO_ConstantPoolIndex: + Symbol = AP.GetCPISymbol(MO.getIndex()); + break; + } + + const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol, + AP.OutContext); + const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym, + AP.OutContext); + return MCOperand::CreateExpr(expr); +} + +static MCOperand LowerOperand(const MachineInstr *MI, + const MachineOperand &MO, + AsmPrinter &AP) { + switch(MO.getType()) { + default: llvm_unreachable("unknown operand type"); break; + case MachineOperand::MO_Register: + if (MO.isImplicit()) + break; + return MCOperand::CreateReg(MO.getReg()); + + case MachineOperand::MO_Immediate: + return MCOperand::CreateImm(MO.getImm()); + + case MachineOperand::MO_MachineBasicBlock: + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_BlockAddress: + case MachineOperand::MO_ExternalSymbol: + case MachineOperand::MO_ConstantPoolIndex: + return LowerSymbolOperand(MI, MO, AP); + + case MachineOperand::MO_RegisterMask: break; + + } + return MCOperand(); +} + +void llvm::LowerSparcMachineInstrToMCInst(const MachineInstr *MI, + MCInst &OutMI, + AsmPrinter &AP) +{ + + OutMI.setOpcode(MI->getOpcode()); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + MCOperand MCOp = LowerOperand(MI, MO, AP); + + if (MCOp.isValid()) + OutMI.addOperand(MCOp); + } +} diff --git a/lib/Target/Sparc/SparcTargetStreamer.h b/lib/Target/Sparc/SparcTargetStreamer.h new file mode 100644 index 00000000000..73339acf8df --- /dev/null +++ b/lib/Target/Sparc/SparcTargetStreamer.h @@ -0,0 +1,47 @@ +//===-- SparcTargetStreamer.h - Sparc Target Streamer ----------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SPARCTARGETSTREAMER_H +#define SPARCTARGETSTREAMER_H + +#include "llvm/MC/MCELFStreamer.h" +#include "llvm/MC/MCStreamer.h" + +namespace llvm { +class SparcTargetStreamer : public MCTargetStreamer { + virtual void anchor(); + +public: + /// Emit ".register , #ignore". + virtual void emitSparcRegisterIgnore(unsigned reg) = 0; + /// Emit ".register , #scratch". + virtual void emitSparcRegisterScratch(unsigned reg) = 0; +}; + +// This part is for ascii assembly output +class SparcTargetAsmStreamer : public SparcTargetStreamer { + formatted_raw_ostream &OS; + +public: + SparcTargetAsmStreamer(formatted_raw_ostream &OS); + virtual void emitSparcRegisterIgnore(unsigned reg); + virtual void emitSparcRegisterScratch(unsigned reg); + +}; + +// This part is for ELF object output +class SparcTargetELFStreamer : public SparcTargetStreamer { +public: + MCELFStreamer &getStreamer(); + virtual void emitSparcRegisterIgnore(unsigned reg) {} + virtual void emitSparcRegisterScratch(unsigned reg) {} +}; +} // end namespace llvm + +#endif diff --git a/test/CodeGen/SPARC/exception.ll b/test/CodeGen/SPARC/exception.ll index cb5b6e5c116..a1d6015b89a 100644 --- a/test/CodeGen/SPARC/exception.ll +++ b/test/CodeGen/SPARC/exception.ll @@ -11,7 +11,7 @@ ; CHECK-LABEL: main: ; CHECK: .cfi_startproc -; CHECK: .cfi_def_cfa_register 30 +; CHECK: .cfi_def_cfa_register {{30|%fp}} ; CHECK: .cfi_window_save ; CHECK: .cfi_register 15, 31