summaryrefslogtreecommitdiff
path: root/lib/Target
diff options
context:
space:
mode:
authorVenkatraman Govindaraju <venkatra@cs.wisc.edu>2013-12-26 01:49:59 +0000
committerVenkatraman Govindaraju <venkatra@cs.wisc.edu>2013-12-26 01:49:59 +0000
commit76a1dca38dbea9009cc16b6055e53497d3f756e4 (patch)
tree2aadd57e63e8bd261712ecab0234d25571643c0c /lib/Target
parentf3aeebf4c78d97ee0df3b4e0d777248460c8b47c (diff)
downloadllvm-76a1dca38dbea9009cc16b6055e53497d3f756e4.tar.gz
llvm-76a1dca38dbea9009cc16b6055e53497d3f756e4.tar.bz2
llvm-76a1dca38dbea9009cc16b6055e53497d3f756e4.tar.xz
[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
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/Sparc/CMakeLists.txt1
-rw-r--r--lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp3
-rw-r--r--lib/Target/Sparc/MCTargetDesc/CMakeLists.txt1
-rw-r--r--lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt2
-rw-r--r--lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp35
-rw-r--r--lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp40
-rw-r--r--lib/Target/Sparc/Sparc.h6
-rw-r--r--lib/Target/Sparc/Sparc.td7
-rw-r--r--lib/Target/Sparc/SparcAsmPrinter.cpp203
-rw-r--r--lib/Target/Sparc/SparcMCInstLower.cpp141
-rw-r--r--lib/Target/Sparc/SparcTargetStreamer.h47
11 files changed, 416 insertions, 70 deletions
diff --git a/lib/Target/Sparc/CMakeLists.txt b/lib/Target/Sparc/CMakeLists.txt
index fb50656b97..3aad2723ab 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 1c5a334f24..d7bee72b74 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 8bf924e86d..3a40fcaba4 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 97f8f162c2..22515e6d6d 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 1c64e1b0c4..45e1d35369 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<SparcELFMCAsmInfo> 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 0000000000..01043aed5e
--- /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<MCELFStreamer &>(*Streamer);
+}
diff --git a/lib/Target/Sparc/Sparc.h b/lib/Target/Sparc/Sparc.h
index f44b60420d..8d46c60255 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 097b565b88..0df48f60e8 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 d06c894c7e..e787ed20a1 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<SparcTargetStreamer&>(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);
+
+ // <StartLabel>:
+ // call <EndLabel>
+ // <SethiLabel>:
+ // sethi %hi(_GLOBAL_OFFSET_TABLE_+(<SethiLabel>-<StartLabel>)), <MO>
+ // <EndLabel>:
+ // or <MO>, %lo(_GLOBAL_OFFSET_TABLE_+(<EndLabel>-<StartLabel>))), <MO>
+ // add <MO>, %o7, <MO>
+
+ 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<SparcSubtarget>().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 0000000000..f58a83c125
--- /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 0000000000..73339acf8d
--- /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 <reg>, #ignore".
+ virtual void emitSparcRegisterIgnore(unsigned reg) = 0;
+ /// Emit ".register <reg>, #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