mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 00:32:55 +00:00
[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
This commit is contained in:
parent
f3aeebf4c7
commit
76a1dca38d
@ -23,6 +23,7 @@ add_llvm_target(SparcCodeGen
|
|||||||
SparcSelectionDAGInfo.cpp
|
SparcSelectionDAGInfo.cpp
|
||||||
SparcJITInfo.cpp
|
SparcJITInfo.cpp
|
||||||
SparcCodeEmitter.cpp
|
SparcCodeEmitter.cpp
|
||||||
|
SparcMCInstLower.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(TargetInfo)
|
add_subdirectory(TargetInfo)
|
||||||
|
@ -23,8 +23,7 @@
|
|||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#define GET_INSTRUCTION_NAME
|
#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
|
void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
|
||||||
{
|
{
|
||||||
|
@ -2,4 +2,5 @@ add_llvm_library(LLVMSparcDesc
|
|||||||
SparcMCTargetDesc.cpp
|
SparcMCTargetDesc.cpp
|
||||||
SparcMCAsmInfo.cpp
|
SparcMCAsmInfo.cpp
|
||||||
SparcMCExpr.cpp
|
SparcMCExpr.cpp
|
||||||
|
SparcTargetStreamer.cpp
|
||||||
)
|
)
|
||||||
|
@ -19,5 +19,5 @@
|
|||||||
type = Library
|
type = Library
|
||||||
name = SparcDesc
|
name = SparcDesc
|
||||||
parent = Sparc
|
parent = Sparc
|
||||||
required_libraries = MC SparcInfo Support
|
required_libraries = MC SparcAsmPrinter SparcInfo Support
|
||||||
add_to_library_groups = Sparc
|
add_to_library_groups = Sparc
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
#include "SparcMCTargetDesc.h"
|
#include "SparcMCTargetDesc.h"
|
||||||
#include "SparcMCAsmInfo.h"
|
#include "SparcMCAsmInfo.h"
|
||||||
|
#include "SparcTargetStreamer.h"
|
||||||
|
#include "InstPrinter/SparcInstPrinter.h"
|
||||||
#include "llvm/MC/MCCodeGenInfo.h"
|
#include "llvm/MC/MCCodeGenInfo.h"
|
||||||
#include "llvm/MC/MCInstrInfo.h"
|
#include "llvm/MC/MCInstrInfo.h"
|
||||||
#include "llvm/MC/MCRegisterInfo.h"
|
#include "llvm/MC/MCRegisterInfo.h"
|
||||||
@ -86,6 +88,28 @@ static MCCodeGenInfo *createSparcV9MCCodeGenInfo(StringRef TT, Reloc::Model RM,
|
|||||||
X->InitMCCodeGenInfo(RM, CM, OL);
|
X->InitMCCodeGenInfo(RM, CM, OL);
|
||||||
return X;
|
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() {
|
extern "C" void LLVMInitializeSparcTargetMC() {
|
||||||
// Register the MC asm info.
|
// Register the MC asm info.
|
||||||
RegisterMCAsmInfo<SparcELFMCAsmInfo> X(TheSparcTarget);
|
RegisterMCAsmInfo<SparcELFMCAsmInfo> X(TheSparcTarget);
|
||||||
@ -106,4 +130,15 @@ extern "C" void LLVMInitializeSparcTargetMC() {
|
|||||||
// Register the MC subtarget info.
|
// Register the MC subtarget info.
|
||||||
TargetRegistry::RegisterMCSubtargetInfo(TheSparcTarget,
|
TargetRegistry::RegisterMCSubtargetInfo(TheSparcTarget,
|
||||||
createSparcMCSubtargetInfo);
|
createSparcMCSubtargetInfo);
|
||||||
|
|
||||||
|
TargetRegistry::RegisterAsmStreamer(TheSparcTarget,
|
||||||
|
createMCAsmStreamer);
|
||||||
|
TargetRegistry::RegisterAsmStreamer(TheSparcV9Target,
|
||||||
|
createMCAsmStreamer);
|
||||||
|
|
||||||
|
// Register the MCInstPrinter
|
||||||
|
TargetRegistry::RegisterMCInstPrinter(TheSparcTarget,
|
||||||
|
createSparcMCInstPrinter);
|
||||||
|
TargetRegistry::RegisterMCInstPrinter(TheSparcV9Target,
|
||||||
|
createSparcMCInstPrinter);
|
||||||
}
|
}
|
||||||
|
40
lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp
Normal file
40
lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp
Normal file
@ -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);
|
||||||
|
}
|
@ -23,12 +23,18 @@ namespace llvm {
|
|||||||
class FunctionPass;
|
class FunctionPass;
|
||||||
class SparcTargetMachine;
|
class SparcTargetMachine;
|
||||||
class formatted_raw_ostream;
|
class formatted_raw_ostream;
|
||||||
|
class AsmPrinter;
|
||||||
|
class MCInst;
|
||||||
|
class MachineInstr;
|
||||||
|
|
||||||
FunctionPass *createSparcISelDag(SparcTargetMachine &TM);
|
FunctionPass *createSparcISelDag(SparcTargetMachine &TM);
|
||||||
FunctionPass *createSparcDelaySlotFillerPass(TargetMachine &TM);
|
FunctionPass *createSparcDelaySlotFillerPass(TargetMachine &TM);
|
||||||
FunctionPass *createSparcJITCodeEmitterPass(SparcTargetMachine &TM,
|
FunctionPass *createSparcJITCodeEmitterPass(SparcTargetMachine &TM,
|
||||||
JITCodeEmitter &JCE);
|
JITCodeEmitter &JCE);
|
||||||
|
|
||||||
|
void LowerSparcMachineInstrToMCInst(const MachineInstr *MI,
|
||||||
|
MCInst &OutMI,
|
||||||
|
AsmPrinter &AP);
|
||||||
} // end namespace llvm;
|
} // end namespace llvm;
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
@ -66,11 +66,6 @@ def : Proc<"ultrasparc3", [FeatureV9, FeatureV8Deprecated]>;
|
|||||||
def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>;
|
def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>;
|
||||||
|
|
||||||
|
|
||||||
def SparcAsmWriter : AsmWriter {
|
|
||||||
string AsmWriterClassName = "AsmPrinter";
|
|
||||||
bit isMCAsmWriter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Declare the target which we are implementing
|
// Declare the target which we are implementing
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -78,6 +73,4 @@ def SparcAsmWriter : AsmWriter {
|
|||||||
def Sparc : Target {
|
def Sparc : Target {
|
||||||
// Pull in Instruction Info:
|
// Pull in Instruction Info:
|
||||||
let InstructionSet = SparcInstrInfo;
|
let InstructionSet = SparcInstrInfo;
|
||||||
|
|
||||||
let AssemblyWriters = [SparcAsmWriter];
|
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,17 @@
|
|||||||
#include "Sparc.h"
|
#include "Sparc.h"
|
||||||
#include "SparcInstrInfo.h"
|
#include "SparcInstrInfo.h"
|
||||||
#include "SparcTargetMachine.h"
|
#include "SparcTargetMachine.h"
|
||||||
|
#include "SparcTargetStreamer.h"
|
||||||
|
#include "InstPrinter/SparcInstPrinter.h"
|
||||||
#include "MCTargetDesc/SparcBaseInfo.h"
|
#include "MCTargetDesc/SparcBaseInfo.h"
|
||||||
|
#include "MCTargetDesc/SparcMCExpr.h"
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
#include "llvm/CodeGen/AsmPrinter.h"
|
#include "llvm/CodeGen/AsmPrinter.h"
|
||||||
#include "llvm/CodeGen/MachineInstr.h"
|
#include "llvm/CodeGen/MachineInstr.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
#include "llvm/MC/MCAsmInfo.h"
|
#include "llvm/MC/MCAsmInfo.h"
|
||||||
|
#include "llvm/MC/MCContext.h"
|
||||||
|
#include "llvm/MC/MCInst.h"
|
||||||
#include "llvm/MC/MCStreamer.h"
|
#include "llvm/MC/MCStreamer.h"
|
||||||
#include "llvm/MC/MCSymbol.h"
|
#include "llvm/MC/MCSymbol.h"
|
||||||
#include "llvm/Support/TargetRegistry.h"
|
#include "llvm/Support/TargetRegistry.h"
|
||||||
@ -31,6 +36,9 @@ using namespace llvm;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class SparcAsmPrinter : public AsmPrinter {
|
class SparcAsmPrinter : public AsmPrinter {
|
||||||
|
SparcTargetStreamer &getTargetStreamer() {
|
||||||
|
return static_cast<SparcTargetStreamer&>(OutStreamer.getTargetStreamer());
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
explicit SparcAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
|
explicit SparcAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
|
||||||
: AsmPrinter(TM, Streamer) {}
|
: AsmPrinter(TM, Streamer) {}
|
||||||
@ -45,14 +53,11 @@ namespace {
|
|||||||
void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
|
void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
|
||||||
|
|
||||||
virtual void EmitFunctionBodyStart();
|
virtual void EmitFunctionBodyStart();
|
||||||
virtual void EmitInstruction(const MachineInstr *MI) {
|
virtual void EmitInstruction(const MachineInstr *MI);
|
||||||
SmallString<128> Str;
|
|
||||||
raw_svector_ostream OS(Str);
|
static const char *getRegisterName(unsigned RegNo) {
|
||||||
printInstruction(MI, OS);
|
return SparcInstPrinter::getRegisterName(RegNo);
|
||||||
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,
|
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||||
unsigned AsmVariant, const char *ExtraCode,
|
unsigned AsmVariant, const char *ExtraCode,
|
||||||
@ -61,24 +66,138 @@ namespace {
|
|||||||
unsigned AsmVariant, const char *ExtraCode,
|
unsigned AsmVariant, const char *ExtraCode,
|
||||||
raw_ostream &O);
|
raw_ostream &O);
|
||||||
|
|
||||||
bool printGetPCX(const MachineInstr *MI, unsigned OpNo, raw_ostream &OS);
|
|
||||||
|
|
||||||
virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB)
|
virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB)
|
||||||
const;
|
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
|
} // 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() {
|
void SparcAsmPrinter::EmitFunctionBodyStart() {
|
||||||
if (!TM.getSubtarget<SparcSubtarget>().is64Bit())
|
if (!TM.getSubtarget<SparcSubtarget>().is64Bit())
|
||||||
@ -90,7 +209,11 @@ void SparcAsmPrinter::EmitFunctionBodyStart() {
|
|||||||
unsigned reg = globalRegs[i];
|
unsigned reg = globalRegs[i];
|
||||||
if (MRI.use_empty(reg))
|
if (MRI.use_empty(reg))
|
||||||
continue;
|
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);
|
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.
|
/// PrintAsmOperand - Print out an operand for an inline asm expression.
|
||||||
///
|
///
|
||||||
bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||||
|
141
lib/Target/Sparc/SparcMCInstLower.cpp
Normal file
141
lib/Target/Sparc/SparcMCInstLower.cpp
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
47
lib/Target/Sparc/SparcTargetStreamer.h
Normal file
47
lib/Target/Sparc/SparcTargetStreamer.h
Normal file
@ -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
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
; CHECK-LABEL: main:
|
; CHECK-LABEL: main:
|
||||||
; CHECK: .cfi_startproc
|
; CHECK: .cfi_startproc
|
||||||
; CHECK: .cfi_def_cfa_register 30
|
; CHECK: .cfi_def_cfa_register {{30|%fp}}
|
||||||
; CHECK: .cfi_window_save
|
; CHECK: .cfi_window_save
|
||||||
; CHECK: .cfi_register 15, 31
|
; CHECK: .cfi_register 15, 31
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user