summaryrefslogtreecommitdiffstats
path: root/lib/Target/Sparc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Sparc')
-rw-r--r--lib/Target/Sparc/AsmPrinter/Makefile2
-rw-r--r--lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp203
-rw-r--r--lib/Target/Sparc/CMakeLists.txt2
-rw-r--r--lib/Target/Sparc/FPMover.cpp10
-rw-r--r--lib/Target/Sparc/Makefile2
-rw-r--r--lib/Target/Sparc/Sparc.h10
-rw-r--r--lib/Target/Sparc/SparcISelDAGToDAG.cpp33
-rw-r--r--lib/Target/Sparc/SparcISelLowering.cpp257
-rw-r--r--lib/Target/Sparc/SparcISelLowering.h39
-rw-r--r--lib/Target/Sparc/SparcInstrInfo.cpp73
-rw-r--r--lib/Target/Sparc/SparcInstrInfo.h12
-rw-r--r--lib/Target/Sparc/SparcInstrInfo.td65
-rw-r--r--lib/Target/Sparc/SparcMCAsmInfo.cpp38
-rw-r--r--lib/Target/Sparc/SparcMCAsmInfo.h28
-rw-r--r--lib/Target/Sparc/SparcMachineFunctionInfo.h32
-rw-r--r--lib/Target/Sparc/SparcRegisterInfo.cpp21
-rw-r--r--lib/Target/Sparc/SparcRegisterInfo.h5
-rw-r--r--lib/Target/Sparc/SparcRegisterInfo.td12
-rw-r--r--lib/Target/Sparc/SparcSubtarget.cpp2
-rw-r--r--lib/Target/Sparc/SparcSubtarget.h5
-rw-r--r--lib/Target/Sparc/SparcTargetMachine.cpp66
-rw-r--r--lib/Target/Sparc/SparcTargetMachine.h24
-rw-r--r--lib/Target/Sparc/TargetInfo/CMakeLists.txt7
-rw-r--r--lib/Target/Sparc/TargetInfo/Makefile15
-rw-r--r--lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp19
25 files changed, 582 insertions, 400 deletions
diff --git a/lib/Target/Sparc/AsmPrinter/Makefile b/lib/Target/Sparc/AsmPrinter/Makefile
index f12a6ac..a856828 100644
--- a/lib/Target/Sparc/AsmPrinter/Makefile
+++ b/lib/Target/Sparc/AsmPrinter/Makefile
@@ -1,4 +1,4 @@
-##===- lib/Target/Sparc/Makefile ---------------------------*- Makefile -*-===##
+##===- lib/Target/Sparc/AsmPrinter/Makefile ----------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
diff --git a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp
index 71bd0de..a3e5fba 100644
--- a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp
+++ b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp
@@ -19,18 +19,22 @@
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
-#include "llvm/MDNode.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/Mangler.h"
#include "llvm/Support/MathExtras.h"
#include <cctype>
#include <cstring>
@@ -49,45 +53,36 @@ namespace {
ValueMapTy NumberForBB;
unsigned BBNumber;
public:
- explicit SparcAsmPrinter(raw_ostream &O, TargetMachine &TM,
- const TargetAsmInfo *T, bool V)
+ explicit SparcAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
+ const MCAsmInfo *T, bool V)
: AsmPrinter(O, TM, T, V), BBNumber(0) {}
virtual const char *getPassName() const {
return "Sparc Assembly Printer";
}
- void printModuleLevelGV(const GlobalVariable* GVar);
+ void PrintGlobalVariable(const GlobalVariable *GVar);
void printOperand(const MachineInstr *MI, int opNum);
void printMemOperand(const MachineInstr *MI, int opNum,
const char *Modifier = 0);
void printCCOperand(const MachineInstr *MI, int opNum);
- bool printInstruction(const MachineInstr *MI); // autogenerated.
+ void printInstruction(const MachineInstr *MI); // autogenerated.
+ static const char *getRegisterName(unsigned RegNo);
+
bool runOnMachineFunction(MachineFunction &F);
- bool doInitialization(Module &M);
- bool doFinalization(Module &M);
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode);
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode);
+
+ void emitFunctionHeader(const MachineFunction &MF);
+ bool printGetPCX(const MachineInstr *MI, unsigned OpNo);
};
} // end of anonymous namespace
#include "SparcGenAsmWriter.inc"
-/// createSparcCodePrinterPass - Returns a pass that prints the SPARC
-/// assembly code for a MachineFunction to the given output stream,
-/// using the given target machine description. This should work
-/// regardless of whether the function is in SSA form.
-///
-FunctionPass *llvm::createSparcCodePrinterPass(raw_ostream &o,
- TargetMachine &tm,
- bool verbose) {
- return new SparcAsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
-}
-
-
/// runOnMachineFunction - This uses the printInstruction()
/// method to print assembly for each instruction.
///
@@ -103,17 +98,11 @@ bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// BBs the same name. (If you have a better way, please let me know!)
O << "\n\n";
-
- // Print out the label for the function.
- const Function *F = MF.getFunction();
- SwitchToSection(TAI->SectionForGlobal(F));
- EmitAlignment(MF.getAlignment(), F);
- O << "\t.globl\t" << CurrentFnName << '\n';
-
- printVisibility(CurrentFnName, F->getVisibility());
-
- O << "\t.type\t" << CurrentFnName << ", #function\n";
- O << CurrentFnName << ":\n";
+ emitFunctionHeader(MF);
+
+
+ // Emit pre-function debug information.
+ DW->BeginFunction(&MF);
// Number each basic block so that we can consistently refer to them
// in PC-relative references.
@@ -129,24 +118,65 @@ bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
I != E; ++I) {
// Print a label for the basic block.
if (I != MF.begin()) {
- printBasicBlockLabel(I, true, true);
- O << '\n';
+ EmitBasicBlockStart(I);
}
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
+ processDebugLoc(II, true);
printInstruction(II);
+
+ if (VerboseAsm && !II->getDebugLoc().isUnknown())
+ EmitComments(*II);
+ O << '\n';
+ processDebugLoc(II, false);
++EmittedInsts;
}
}
+ // Emit post-function debug information.
+ DW->EndFunction(&MF);
+
// We didn't modify anything.
+ O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
return false;
}
+void SparcAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
+ const Function *F = MF.getFunction();
+ OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
+ EmitAlignment(MF.getAlignment(), F);
+
+ switch (F->getLinkage()) {
+ default: llvm_unreachable("Unknown linkage type");
+ case Function::PrivateLinkage:
+ case Function::InternalLinkage:
+ // Function is internal.
+ break;
+ case Function::DLLExportLinkage:
+ case Function::ExternalLinkage:
+ // Function is externally visible
+ O << "\t.global\t" << CurrentFnName << '\n';
+ break;
+ case Function::LinkerPrivateLinkage:
+ case Function::LinkOnceAnyLinkage:
+ case Function::LinkOnceODRLinkage:
+ case Function::WeakAnyLinkage:
+ case Function::WeakODRLinkage:
+ // Function is weak
+ O << "\t.weak\t" << CurrentFnName << '\n' ;
+ break;
+ }
+
+ printVisibility(CurrentFnName, F->getVisibility());
+
+ O << "\t.type\t" << CurrentFnName << ", #function\n";
+ O << CurrentFnName << ":\n";
+}
+
+
void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
const MachineOperand &MO = MI->getOperand (opNum);
- const TargetRegisterInfo &RI = *TM.getRegisterInfo();
bool CloseParen = false;
if (MI->getOpcode() == SP::SETHIi && !MO.isReg() && !MO.isImm()) {
O << "%hi(";
@@ -158,33 +188,27 @@ void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
}
switch (MO.getType()) {
case MachineOperand::MO_Register:
- if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
- O << "%" << LowercaseString (RI.get(MO.getReg()).AsmName);
- else
- O << "%reg" << MO.getReg();
+ O << "%" << LowercaseString(getRegisterName(MO.getReg()));
break;
case MachineOperand::MO_Immediate:
O << (int)MO.getImm();
break;
case MachineOperand::MO_MachineBasicBlock:
- printBasicBlockLabel(MO.getMBB());
+ GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
return;
case MachineOperand::MO_GlobalAddress:
- {
- const GlobalValue *GV = MO.getGlobal();
- O << Mang->getValueName(GV);
- }
+ O << Mang->getMangledName(MO.getGlobal());
break;
case MachineOperand::MO_ExternalSymbol:
O << MO.getSymbolName();
break;
case MachineOperand::MO_ConstantPoolIndex:
- O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
+ O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
<< MO.getIndex();
break;
default:
- O << "<unknown operand type>"; abort (); break;
+ llvm_unreachable("<unknown operand type>");
}
if (CloseParen) O << ")";
}
@@ -218,28 +242,42 @@ void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
}
}
-void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
- int CC = (int)MI->getOperand(opNum).getImm();
- O << SPARCCondCodeToString((SPCC::CondCodes)CC);
-}
+bool SparcAsmPrinter::printGetPCX(const MachineInstr *MI, unsigned opNum) {
+ 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;
+ }
-bool SparcAsmPrinter::doInitialization(Module &M) {
- Mang = new Mangler(M, "", TAI->getPrivateGlobalPrefix());
- return false; // success
-}
+ unsigned bbNum = NumberForBB[MI->getParent()->getBasicBlock()];
-bool SparcAsmPrinter::doFinalization(Module &M) {
- // Print out module-level global variables here.
- for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
- I != E; ++I)
- printModuleLevelGV(I);
+ O << '\n' << ".LLGETPCH" << bbNum << ":\n";
+ O << "\tcall\t.LLGETPC" << bbNum << '\n' ;
- O << '\n';
+ O << "\t sethi\t"
+ << "%hi(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << bbNum << ")), "
+ << operand << '\n' ;
+
+ O << ".LLGETPC" << bbNum << ":\n" ;
+ O << "\tor\t" << operand
+ << ", %lo(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << bbNum << ")), "
+ << operand << '\n';
+ O << "\tadd\t" << operand << ", %o7, " << operand << '\n';
+
+ return true;
+}
- return AsmPrinter::doFinalization(M);
+void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
+ int CC = (int)MI->getOperand(opNum).getImm();
+ O << SPARCCondCodeToString((SPCC::CondCodes)CC);
}
-void SparcAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
+void SparcAsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) {
const TargetData *TD = TM.getTargetData();
if (!GVar->hasInitializer())
@@ -250,16 +288,15 @@ void SparcAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
return;
O << "\n\n";
- std::string name = Mang->getValueName(GVar);
+ std::string name = Mang->getMangledName(GVar);
Constant *C = GVar->getInitializer();
- if (isa<MDNode>(C) || isa<MDString>(C))
- return;
unsigned Size = TD->getTypeAllocSize(C->getType());
unsigned Align = TD->getPreferredAlignment(GVar);
printVisibility(name, GVar->getVisibility());
- SwitchToSection(TAI->SectionForGlobal(GVar));
+ OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang,
+ TM));
if (C->isNullValue() && !GVar->hasSection()) {
if (!GVar->isThreadLocal() &&
@@ -269,8 +306,8 @@ void SparcAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
if (GVar->hasLocalLinkage())
O << "\t.local " << name << '\n';
- O << TAI->getCOMMDirective() << name << ',' << Size;
- if (TAI->getCOMMDirectiveTakesAlignment())
+ O << MAI->getCOMMDirective() << name << ',' << Size;
+ if (MAI->getCOMMDirectiveTakesAlignment())
O << ',' << (1 << Align);
O << '\n';
@@ -292,27 +329,25 @@ void SparcAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
// their name or something. For now, just emit them as external.
case GlobalValue::ExternalLinkage:
// If external or appending, declare as a global symbol
- O << TAI->getGlobalDirective() << name << '\n';
+ O << MAI->getGlobalDirective() << name << '\n';
// FALL THROUGH
case GlobalValue::PrivateLinkage:
+ case GlobalValue::LinkerPrivateLinkage:
case GlobalValue::InternalLinkage:
break;
case GlobalValue::GhostLinkage:
- cerr << "Should not have any unmaterialized functions!\n";
- abort();
+ llvm_unreachable("Should not have any unmaterialized functions!");
case GlobalValue::DLLImportLinkage:
- cerr << "DLLImport linkage is not supported by this target!\n";
- abort();
+ llvm_unreachable("DLLImport linkage is not supported by this target!");
case GlobalValue::DLLExportLinkage:
- cerr << "DLLExport linkage is not supported by this target!\n";
- abort();
+ llvm_unreachable("DLLExport linkage is not supported by this target!");
default:
- assert(0 && "Unknown linkage type!");
+ llvm_unreachable("Unknown linkage type!");
}
EmitAlignment(Align, GVar);
- if (TAI->hasDotTypeDotSizeDirective()) {
+ if (MAI->hasDotTypeDotSizeDirective()) {
O << "\t.type " << name << ",#object\n";
O << "\t.size " << name << ',' << Size << '\n';
}
@@ -355,13 +390,7 @@ bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
return false;
}
-namespace {
- static struct Register {
- Register() {
- SparcTargetMachine::registerAsmPrinter(createSparcCodePrinterPass);
- }
- } Registrator;
-}
-
// Force static initialization.
-extern "C" void LLVMInitializeSparcAsmPrinter() { }
+extern "C" void LLVMInitializeSparcAsmPrinter() {
+ RegisterAsmPrinter<SparcAsmPrinter> X(TheSparcTarget);
+}
diff --git a/lib/Target/Sparc/CMakeLists.txt b/lib/Target/Sparc/CMakeLists.txt
index eb045e2..74f320a 100644
--- a/lib/Target/Sparc/CMakeLists.txt
+++ b/lib/Target/Sparc/CMakeLists.txt
@@ -16,9 +16,9 @@ add_llvm_target(SparcCodeGen
SparcInstrInfo.cpp
SparcISelDAGToDAG.cpp
SparcISelLowering.cpp
+ SparcMCAsmInfo.cpp
SparcRegisterInfo.cpp
SparcSubtarget.cpp
- SparcTargetAsmInfo.cpp
SparcTargetMachine.cpp
)
diff --git a/lib/Target/Sparc/FPMover.cpp b/lib/Target/Sparc/FPMover.cpp
index f72a4c4..88b0927 100644
--- a/lib/Target/Sparc/FPMover.cpp
+++ b/lib/Target/Sparc/FPMover.cpp
@@ -20,6 +20,8 @@
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
STATISTIC(NumFpDs , "Number of instructions translated");
@@ -75,7 +77,7 @@ static void getDoubleRegPair(unsigned DoubleReg, unsigned &EvenReg,
OddReg = OddHalvesOfPairs[i];
return;
}
- assert(0 && "Can't find reg");
+ llvm_unreachable("Can't find reg");
}
/// runOnMachineBasicBlock - Fixup FpMOVD instructions in this MBB.
@@ -108,16 +110,16 @@ bool FPMover::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
else if (MI->getOpcode() == SP::FpABSD)
MI->setDesc(TII->get(SP::FABSS));
else
- assert(0 && "Unknown opcode!");
+ llvm_unreachable("Unknown opcode!");
MI->getOperand(0).setReg(EvenDestReg);
MI->getOperand(1).setReg(EvenSrcReg);
- DOUT << "FPMover: the modified instr is: " << *MI;
+ DEBUG(errs() << "FPMover: the modified instr is: " << *MI);
// Insert copy for the other half of the double.
if (DestDReg != SrcDReg) {
MI = BuildMI(MBB, I, dl, TM.getInstrInfo()->get(SP::FMOVS), OddDestReg)
.addReg(OddSrcReg);
- DOUT << "FPMover: the inserted instr is: " << *MI;
+ DEBUG(errs() << "FPMover: the inserted instr is: " << *MI);
}
++NumFpDs;
}
diff --git a/lib/Target/Sparc/Makefile b/lib/Target/Sparc/Makefile
index fdf6afa..6714b4d 100644
--- a/lib/Target/Sparc/Makefile
+++ b/lib/Target/Sparc/Makefile
@@ -16,7 +16,7 @@ BUILT_SOURCES = SparcGenRegisterInfo.h.inc SparcGenRegisterNames.inc \
SparcGenInstrInfo.inc SparcGenAsmWriter.inc \
SparcGenDAGISel.inc SparcGenSubtarget.inc SparcGenCallingConv.inc
-DIRS = AsmPrinter
+DIRS = AsmPrinter TargetInfo
include $(LEVEL)/Makefile.common
diff --git a/lib/Target/Sparc/Sparc.h b/lib/Target/Sparc/Sparc.h
index c7d0ca8..bb5155e1 100644
--- a/lib/Target/Sparc/Sparc.h
+++ b/lib/Target/Sparc/Sparc.h
@@ -15,19 +15,21 @@
#ifndef TARGET_SPARC_H
#define TARGET_SPARC_H
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetMachine.h"
#include <cassert>
namespace llvm {
class FunctionPass;
class SparcTargetMachine;
- class raw_ostream;
+ class formatted_raw_ostream;
FunctionPass *createSparcISelDag(SparcTargetMachine &TM);
- FunctionPass *createSparcCodePrinterPass(raw_ostream &OS, TargetMachine &TM,
- bool Verbose);
FunctionPass *createSparcDelaySlotFillerPass(TargetMachine &TM);
FunctionPass *createSparcFPMoverPass(TargetMachine &TM);
+
+ extern Target TheSparcTarget;
+
} // end namespace llvm;
// Defines symbolic names for Sparc registers. This defines a mapping from
@@ -83,7 +85,7 @@ namespace llvm {
inline static const char *SPARCCondCodeToString(SPCC::CondCodes CC) {
switch (CC) {
- default: assert(0 && "Unknown condition code");
+ default: llvm_unreachable("Unknown condition code");
case SPCC::ICC_NE: return "ne";
case SPCC::ICC_E: return "e";
case SPCC::ICC_G: return "g";
diff --git a/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/lib/Target/Sparc/SparcISelDAGToDAG.cpp
index c9bd62d..a1a4a8e 100644
--- a/lib/Target/Sparc/SparcISelDAGToDAG.cpp
+++ b/lib/Target/Sparc/SparcISelDAGToDAG.cpp
@@ -17,6 +17,8 @@
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
@@ -32,10 +34,13 @@ class SparcDAGToDAGISel : public SelectionDAGISel {
/// Subtarget - Keep a pointer to the Sparc Subtarget around so that we can
/// make the right decision when generating code for different targets.
const SparcSubtarget &Subtarget;
+ SparcTargetMachine& TM;
+ MachineBasicBlock *CurBB;
public:
- explicit SparcDAGToDAGISel(SparcTargetMachine &TM)
- : SelectionDAGISel(TM),
- Subtarget(TM.getSubtarget<SparcSubtarget>()) {
+ explicit SparcDAGToDAGISel(SparcTargetMachine &tm)
+ : SelectionDAGISel(tm),
+ Subtarget(tm.getSubtarget<SparcSubtarget>()),
+ TM(tm) {
}
SDNode *Select(SDValue Op);
@@ -61,6 +66,9 @@ public:
// Include the pieces autogenerated from the target description.
#include "SparcGenDAGISel.inc"
+
+private:
+ SDNode* getGlobalBaseReg();
};
} // end anonymous namespace
@@ -68,12 +76,18 @@ public:
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void SparcDAGToDAGISel::InstructionSelect() {
DEBUG(BB->dump());
-
+ CurBB = BB;
// Select target instructions for the DAG.
SelectRoot(*CurDAG);
CurDAG->RemoveDeadNodes();
}
+SDNode* SparcDAGToDAGISel::getGlobalBaseReg() {
+ MachineFunction *MF = CurBB->getParent();
+ unsigned GlobalBaseReg = TM.getInstrInfo()->getGlobalBaseReg(MF);
+ return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode();
+}
+
bool SparcDAGToDAGISel::SelectADDRri(SDValue Op, SDValue Addr,
SDValue &Base, SDValue &Offset) {
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
@@ -147,6 +161,9 @@ SDNode *SparcDAGToDAGISel::Select(SDValue Op) {
switch (N->getOpcode()) {
default: break;
+ case SPISD::GLOBAL_BASE_REG:
+ return getGlobalBaseReg();
+
case ISD::SDIV:
case ISD::UDIV: {
// FIXME: should use a custom expander to expose the SRA to the dag.
@@ -156,12 +173,12 @@ SDNode *SparcDAGToDAGISel::Select(SDValue Op) {
// Set the Y register to the high-part.
SDValue TopPart;
if (N->getOpcode() == ISD::SDIV) {
- TopPart = SDValue(CurDAG->getTargetNode(SP::SRAri, dl, MVT::i32, DivLHS,
+ TopPart = SDValue(CurDAG->getMachineNode(SP::SRAri, dl, MVT::i32, DivLHS,
CurDAG->getTargetConstant(31, MVT::i32)), 0);
} else {
TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
}
- TopPart = SDValue(CurDAG->getTargetNode(SP::WRYrr, dl, MVT::Flag, TopPart,
+ TopPart = SDValue(CurDAG->getMachineNode(SP::WRYrr, dl, MVT::Flag, TopPart,
CurDAG->getRegister(SP::G0, MVT::i32)), 0);
// FIXME: Handle div by immediate.
@@ -175,8 +192,8 @@ SDNode *SparcDAGToDAGISel::Select(SDValue Op) {
SDValue MulLHS = N->getOperand(0);
SDValue MulRHS = N->getOperand(1);
unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr;
- SDNode *Mul = CurDAG->getTargetNode(Opcode, dl, MVT::i32, MVT::Flag,
- MulLHS, MulRHS);
+ SDNode *Mul = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Flag,
+ MulLHS, MulRHS);
// The high part is in the Y register.
return CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDValue(Mul, 1));
return NULL;
diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp
index 4c3efde..164770d 100644
--- a/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/lib/Target/Sparc/SparcISelLowering.cpp
@@ -21,7 +21,9 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/ADT/VectorExtras.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
@@ -31,18 +33,21 @@ using namespace llvm;
#include "SparcGenCallingConv.inc"
-static SDValue LowerRET(SDValue Op, SelectionDAG &DAG) {
+SDValue
+SparcTargetLowering::LowerReturn(SDValue Chain,
+ CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ DebugLoc dl, SelectionDAG &DAG) {
+
// CCValAssign - represent the assignment of the return value to locations.
SmallVector<CCValAssign, 16> RVLocs;
- unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
- bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
- DebugLoc dl = Op.getDebugLoc();
// CCState - Info about the registers and stack slot.
- CCState CCInfo(CC, isVarArg, DAG.getTarget(), RVLocs);
+ CCState CCInfo(CallConv, isVarArg, DAG.getTarget(),
+ RVLocs, *DAG.getContext());
- // Analize return values of ISD::RET
- CCInfo.AnalyzeReturn(Op.getNode(), RetCC_Sparc32);
+ // Analize return values.
+ CCInfo.AnalyzeReturn(Outs, RetCC_Sparc32);
// If this is the first return lowered for this function, add the regs to the
// liveout set for the function.
@@ -52,7 +57,6 @@ static SDValue LowerRET(SDValue Op, SelectionDAG &DAG) {
DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
}
- SDValue Chain = Op.getOperand(0);
SDValue Flag;
// Copy the result values into the output registers.
@@ -60,10 +64,8 @@ static SDValue LowerRET(SDValue Op, SelectionDAG &DAG) {
CCValAssign &VA = RVLocs[i];
assert(VA.isRegLoc() && "Can only return in registers!");
- // ISD::RET => ret chain, (regnum1,val1), ...
- // So i*2+1 index only the regnums.
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
- Op.getOperand(i*2+1), Flag);
+ Outs[i].Val, Flag);
// Guarantee that all emitted copies are stuck together with flags.
Flag = Chain.getValue(1);
@@ -74,55 +76,64 @@ static SDValue LowerRET(SDValue Op, SelectionDAG &DAG) {
return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain);
}
-/// LowerArguments - V8 uses a very simple ABI, where all values are passed in
-/// either one or two GPRs, including FP values. TODO: we should pass FP values
-/// in FP registers for fastcc functions.
-void
-SparcTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &ArgValues,
- DebugLoc dl) {
+/// LowerFormalArguments - V8 uses a very simple ABI, where all values are
+/// passed in either one or two GPRs, including FP values. TODO: we should
+/// pass FP values in FP registers for fastcc functions.
+SDValue
+SparcTargetLowering::LowerFormalArguments(SDValue Chain,
+ CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg>
+ &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) {
+
MachineFunction &MF = DAG.getMachineFunction();
MachineRegisterInfo &RegInfo = MF.getRegInfo();
+ // Assign locations to all of the incoming arguments.
+ SmallVector<CCValAssign, 16> ArgLocs;
+ CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
+ ArgLocs, *DAG.getContext());
+ CCInfo.AnalyzeFormalArguments(Ins, CC_Sparc32);
+
static const unsigned ArgRegs[] = {
SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
};
-
const unsigned *CurArgReg = ArgRegs, *ArgRegEnd = ArgRegs+6;
unsigned ArgOffset = 68;
- SDValue Root = DAG.getRoot();
- std::vector<SDValue> OutChains;
-
- for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
- MVT ObjectVT = getValueType(I->getType());
-
- switch (ObjectVT.getSimpleVT()) {
- default: assert(0 && "Unhandled argument type!");
+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+ SDValue ArgValue;
+ CCValAssign &VA = ArgLocs[i];
+ // FIXME: We ignore the register assignments of AnalyzeFormalArguments
+ // because it doesn't know how to split a double into two i32 registers.
+ EVT ObjectVT = VA.getValVT();
+ switch (ObjectVT.getSimpleVT().SimpleTy) {
+ default: llvm_unreachable("Unhandled argument type!");
case MVT::i1:
case MVT::i8:
case MVT::i16:
case MVT::i32:
- if (I->use_empty()) { // Argument is dead.
+ if (!Ins[i].Used) { // Argument is dead.
if (CurArgReg < ArgRegEnd) ++CurArgReg;
- ArgValues.push_back(DAG.getUNDEF(ObjectVT));
+ InVals.push_back(DAG.getUNDEF(ObjectVT));
} else if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
MF.getRegInfo().addLiveIn(*CurArgReg++, VReg);
- SDValue Arg = DAG.getCopyFromReg(Root, dl, VReg, MVT::i32);
+ SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
if (ObjectVT != MVT::i32) {
unsigned AssertOp = ISD::AssertSext;
Arg = DAG.getNode(AssertOp, dl, MVT::i32, Arg,
DAG.getValueType(ObjectVT));
Arg = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Arg);
}
- ArgValues.push_back(Arg);
+ InVals.push_back(Arg);
} else {
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
SDValue Load;
if (ObjectVT == MVT::i32) {
- Load = DAG.getLoad(MVT::i32, dl, Root, FIPtr, NULL, 0);
+ Load = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0);
} else {
ISD::LoadExtType LoadOp = ISD::SEXTLOAD;
@@ -130,63 +141,63 @@ SparcTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG,
unsigned Offset = 4-std::max(1U, ObjectVT.getSizeInBits()/8);
FIPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, FIPtr,
DAG.getConstant(Offset, MVT::i32));
- Load = DAG.getExtLoad(LoadOp, dl, MVT::i32, Root, FIPtr,
+ Load = DAG.getExtLoad(LoadOp, dl, MVT::i32, Chain, FIPtr,
NULL, 0, ObjectVT);
Load = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Load);
}
- ArgValues.push_back(Load);
+ InVals.push_back(Load);
}
ArgOffset += 4;
break;
case MVT::f32:
- if (I->use_empty()) { // Argument is dead.
+ if (!Ins[i].Used) { // Argument is dead.
if (CurArgReg < ArgRegEnd) ++CurArgReg;
- ArgValues.push_back(DAG.getUNDEF(ObjectVT));
+ InVals.push_back(DAG.getUNDEF(ObjectVT));
} else if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
// FP value is passed in an integer register.
unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
MF.getRegInfo().addLiveIn(*CurArgReg++, VReg);
- SDValue Arg = DAG.getCopyFromReg(Root, dl, VReg, MVT::i32);
+ SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
Arg = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, Arg);
- ArgValues.push_back(Arg);
+ InVals.push_back(Arg);
} else {
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
- SDValue Load = DAG.getLoad(MVT::f32, dl, Root, FIPtr, NULL, 0);
- ArgValues.push_back(Load);
+ SDValue Load = DAG.getLoad(MVT::f32, dl, Chain, FIPtr, NULL, 0);
+ InVals.push_back(Load);
}
ArgOffset += 4;
break;
case MVT::i64:
case MVT::f64:
- if (I->use_empty()) { // Argument is dead.
+ if (!Ins[i].Used) { // Argument is dead.
if (CurArgReg < ArgRegEnd) ++CurArgReg;
if (CurArgReg < ArgRegEnd) ++CurArgReg;
- ArgValues.push_back(DAG.getUNDEF(ObjectVT));
+ InVals.push_back(DAG.getUNDEF(ObjectVT));
} else {
SDValue HiVal;
if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
unsigned VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
MF.getRegInfo().addLiveIn(*CurArgReg++, VRegHi);
- HiVal = DAG.getCopyFromReg(Root, dl, VRegHi, MVT::i32);
+ HiVal = DAG.getCopyFromReg(Chain, dl, VRegHi, MVT::i32);
} else {
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
- HiVal = DAG.getLoad(MVT::i32, dl, Root, FIPtr, NULL, 0);
+ HiVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0);
}
SDValue LoVal;
if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
unsigned VRegLo = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
MF.getRegInfo().addLiveIn(*CurArgReg++, VRegLo);
- LoVal = DAG.getCopyFromReg(Root, dl, VRegLo, MVT::i32);
+ LoVal = DAG.getCopyFromReg(Chain, dl, VRegLo, MVT::i32);
} else {
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset+4);
SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
- LoVal = DAG.getLoad(MVT::i32, dl, Root, FIPtr, NULL, 0);
+ LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0);
}
// Compose the two halves together into an i64 unit.
@@ -197,7 +208,7 @@ SparcTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG,
if (ObjectVT == MVT::f64)
WholeValue = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, WholeValue);
- ArgValues.push_back(WholeValue);
+ InVals.push_back(WholeValue);
}
ArgOffset += 8;
break;
@@ -205,10 +216,12 @@ SparcTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG,
}
// Store remaining ArgRegs to the stack if this is a varargs function.
- if (F.isVarArg()) {
+ if (isVarArg) {
// Remember the vararg offset for the va_start implementation.
VarArgsFrameOffset = ArgOffset;
+ std::vector<SDValue> OutChains;
+
for (; CurArgReg != ArgRegEnd; ++CurArgReg) {
unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
MF.getRegInfo().addLiveIn(*CurArgReg, VReg);
@@ -220,26 +233,31 @@ SparcTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG,
OutChains.push_back(DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, NULL, 0));
ArgOffset += 4;
}
+
+ if (!OutChains.empty()) {
+ OutChains.push_back(Chain);
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ &OutChains[0], OutChains.size());
+ }
}
- if (!OutChains.empty())
- DAG.setRoot(DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
- &OutChains[0], OutChains.size()));
+ return Chain;
}
-static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
- CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
- unsigned CallingConv = TheCall->getCallingConv();
- SDValue Chain = TheCall->getChain();
- SDValue Callee = TheCall->getCallee();
- bool isVarArg = TheCall->isVarArg();
- DebugLoc dl = TheCall->getDebugLoc();
+SDValue
+SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
+ CallingConv::ID CallConv, bool isVarArg,
+ bool isTailCall,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) {
#if 0
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
- CCState CCInfo(CallingConv, isVarArg, DAG.getTarget(), ArgLocs);
- CCInfo.AnalyzeCallOperands(Op.getNode(), CC_Sparc32);
+ CCState CCInfo(CallConv, isVarArg, DAG.getTarget(), ArgLocs);
+ CCInfo.AnalyzeCallOperands(Outs, CC_Sparc32);
// Get the size of the outgoing arguments stack space requirement.
unsigned ArgsSize = CCInfo.getNextStackOffset();
@@ -249,9 +267,9 @@ static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Count the size of the outgoing arguments.
unsigned ArgsSize = 0;
- for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; ++i) {
- switch (TheCall->getArg(i).getValueType().getSimpleVT()) {
- default: assert(0 && "Unknown value type!");
+ for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
+ switch (Outs[i].Val.getValueType().getSimpleVT().SimpleTy) {
+ default: llvm_unreachable("Unknown value type!");
case MVT::i1:
case MVT::i8:
case MVT::i16:
@@ -283,13 +301,11 @@ static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Walk the register/memloc assignments, inserting copies/loads.
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
-
- // Arguments start after the 5 first operands of ISD::CALL
- SDValue Arg = TheCall->getArg(i);
+ SDValue Arg = Outs[i].Val;
// Promote the value if needed.
switch (VA.getLocInfo()) {
- default: assert(0 && "Unknown loc info!");
+ default: llvm_unreachable("Unknown loc info!");
case CCValAssign::Full: break;
case CCValAssign::SExt:
Arg = DAG.getNode(ISD::SIGN_EXTEND, VA.getLocVT(), Arg);
@@ -325,13 +341,13 @@ static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
};
unsigned ArgOffset = 68;
- for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; ++i) {
- SDValue Val = TheCall->getArg(i);
- MVT ObjectVT = Val.getValueType();
+ for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
+ SDValue Val = Outs[i].Val;
+ EVT ObjectVT = Val.getValueType();
SDValue ValToStore(0, 0);
unsigned ObjSize;
- switch (ObjectVT.getSimpleVT()) {
- default: assert(0 && "Unhandled argument type!");
+ switch (ObjectVT.getSimpleVT().SimpleTy) {
+ default: llvm_unreachable("Unhandled argument type!");
case MVT::i32:
ObjSize = 4;
@@ -446,7 +462,7 @@ static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
- std::vector<MVT> NodeTys;
+ std::vector<EVT> NodeTys;
NodeTys.push_back(MVT::Other); // Returns a chain
NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
SDValue Ops[] = { Chain, Callee, InFlag };
@@ -459,10 +475,10 @@ static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> RVLocs;
- CCState RVInfo(CallingConv, isVarArg, DAG.getTarget(), RVLocs);
+ CCState RVInfo(CallConv, isVarArg, DAG.getTarget(),
+ RVLocs, *DAG.getContext());
- RVInfo.AnalyzeCallResult(TheCall, RetCC_Sparc32);
- SmallVector<SDValue, 8> ResultVals;
+ RVInfo.AnalyzeCallResult(Ins, RetCC_Sparc32);
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
@@ -475,15 +491,10 @@ static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
Chain = DAG.getCopyFromReg(Chain, dl, Reg,
RVLocs[i].getValVT(), InFlag).getValue(1);
InFlag = Chain.getValue(2);
- ResultVals.push_back(Chain.getValue(0));
+ InVals.push_back(Chain.getValue(0));
}
- ResultVals.push_back(Chain);
-
- // Merge everything together with a MERGE_VALUES node.
- return DAG.getNode(ISD::MERGE_VALUES, dl,
- TheCall->getVTList(), &ResultVals[0],
- ResultVals.size());
+ return Chain;
}
@@ -496,7 +507,7 @@ static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
/// condition.
static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) {
switch (CC) {
- default: assert(0 && "Unknown integer condition code!");
+ default: llvm_unreachable("Unknown integer condition code!");
case ISD::SETEQ: return SPCC::ICC_E;
case ISD::SETNE: return SPCC::ICC_NE;
case ISD::SETLT: return SPCC::ICC_L;
@@ -514,7 +525,7 @@ static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) {
/// FCC condition.
static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) {
switch (CC) {
- default: assert(0 && "Unknown fp condition code!");
+ default: llvm_unreachable("Unknown fp condition code!");
case ISD::SETEQ:
case ISD::SETOEQ: return SPCC::FCC_E;
case ISD::SETNE:
@@ -538,9 +549,8 @@ static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) {
}
}
-
SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
- : TargetLowering(TM) {
+ : TargetLowering(TM, new TargetLoweringObjectFileELF()) {
// Set up the register classes.
addRegisterClass(MVT::i32, SP::IntRegsRegisterClass);
@@ -635,9 +645,6 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
setOperationAction(ISD::DBG_LABEL, MVT::Other, Expand);
setOperationAction(ISD::EH_LABEL, MVT::Other, Expand);
- // RET must be custom lowered, to meet ABI requirements
- setOperationAction(ISD::RET , MVT::Other, Custom);
-
// VASTART needs to be custom lowered to use the VarArgsFrameIndex.
setOperationAction(ISD::VASTART , MVT::Other, Custom);
// VAARG needs to be lowered to not do unaligned accesses for doubles.
@@ -654,7 +661,6 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
setOperationAction(ISD::DBG_LABEL, MVT::Other, Expand);
setOperationAction(ISD::EH_LABEL, MVT::Other, Expand);
- setOperationAction(ISD::DECLARE, MVT::Other, Expand);
setStackPointerRegisterToSaveRestore(SP::O6);
@@ -734,17 +740,29 @@ static void LookThroughSetCC(SDValue &LHS, SDValue &RHS,
}
}
-static SDValue LowerGLOBALADDRESS(SDValue Op, SelectionDAG &DAG) {
+SDValue SparcTargetLowering::LowerGlobalAddress(SDValue Op,
+ SelectionDAG &DAG) {
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
// FIXME there isn't really any debug info here
DebugLoc dl = Op.getDebugLoc();
SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
SDValue Hi = DAG.getNode(SPISD::Hi, dl, MVT::i32, GA);
SDValue Lo = DAG.getNode(SPISD::Lo, dl, MVT::i32, GA);
- return DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi);
+
+ if (getTargetMachine().getRelocationModel() != Reloc::PIC_)
+ return DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi);
+
+ SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, dl,
+ getPointerTy());
+ SDValue RelAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi);
+ SDValue AbsAddr = DAG.getNode(ISD::ADD, dl, MVT::i32,
+ GlobalBase, RelAddr);
+ return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(),
+ AbsAddr, NULL, 0);
}
-static SDValue LowerCONSTANTPOOL(SDValue Op, SelectionDAG &DAG) {
+SDValue SparcTargetLowering::LowerConstantPool(SDValue Op,
+ SelectionDAG &DAG) {
ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
// FIXME there isn't really any debug info here
DebugLoc dl = Op.getDebugLoc();
@@ -752,7 +770,16 @@ static SDValue LowerCONSTANTPOOL(SDValue Op, SelectionDAG &DAG) {
SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment());
SDValue Hi = DAG.getNode(SPISD::Hi, dl, MVT::i32, CP);
SDValue Lo = DAG.getNode(SPISD::Lo, dl, MVT::i32, CP);
- return DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi);
+ if (getTargetMachine().getRelocationModel() != Reloc::PIC_)
+ return DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi);
+
+ SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, dl,
+ getPointerTy());
+ SDValue RelAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi);
+ SDValue AbsAddr = DAG.getNode(ISD::ADD, dl, MVT::i32,
+ GlobalBase, RelAddr);
+ return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(),
+ AbsAddr, NULL, 0);
}
static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) {
@@ -787,7 +814,7 @@ static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) {
// Get the condition flag.
SDValue CompareFlag;
if (LHS.getValueType() == MVT::i32) {
- std::vector<MVT> VTs;
+ std::vector<EVT> VTs;
VTs.push_back(MVT::i32);
VTs.push_back(MVT::Flag);
SDValue Ops[2] = { LHS, RHS };
@@ -818,7 +845,7 @@ static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
SDValue CompareFlag;
if (LHS.getValueType() == MVT::i32) {
- std::vector<MVT> VTs;
+ std::vector<EVT> VTs;
VTs.push_back(LHS.getValueType()); // subcc returns a value
VTs.push_back(MVT::Flag);
SDValue Ops[2] = { LHS, RHS };
@@ -849,7 +876,7 @@ static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG,
static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) {
SDNode *Node = Op.getNode();
- MVT VT = Node->getValueType(0);
+ EVT VT = Node->getValueType(0);
SDValue InChain = Node->getOperand(0);
SDValue VAListPtr = Node->getOperand(1);
const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
@@ -900,14 +927,14 @@ static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) {
SDValue SparcTargetLowering::
LowerOperation(SDValue Op, SelectionDAG &DAG) {
switch (Op.getOpcode()) {
- default: assert(0 && "Should not custom lower this!");
+ default: llvm_unreachable("Should not custom lower this!");
// Frame & Return address. Currently unimplemented
case ISD::RETURNADDR: return SDValue();
case ISD::FRAMEADDR: return SDValue();
case ISD::GlobalTLSAddress:
- assert(0 && "TLS not implemented for Sparc.");
- case ISD::GlobalAddress: return LowerGLOBALADDRESS(Op, DAG);
- case ISD::ConstantPool: return LowerCONSTANTPOOL(Op, DAG);
+ llvm_unreachable("TLS not implemented for Sparc.");
+ case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
+ case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG);
case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG);
case ISD::BR_CC: return LowerBR_CC(Op, DAG);
@@ -915,21 +942,20 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) {
case ISD::VASTART: return LowerVASTART(Op, DAG, *this);
case ISD::VAARG: return LowerVAARG(Op, DAG);
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
- case ISD::CALL: return LowerCALL(Op, DAG);
- case ISD::RET: return LowerRET(Op, DAG);
}
}
MachineBasicBlock *
SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
- MachineBasicBlock *BB) const {
+ MachineBasicBlock *BB,
+ DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const {
const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
unsigned BROpcode;
unsigned CC;
DebugLoc dl = MI->getDebugLoc();
// Figure out the conditional branch opcode to use for this select_cc.
switch (MI->getOpcode()) {
- default: assert(0 && "Unknown SELECT_CC!");
+ default: llvm_unreachable("Unknown SELECT_CC!");
case SP::SELECT_CC_Int_ICC:
case SP::SELECT_CC_FP_ICC:
case SP::SELECT_CC_DFP_ICC:
@@ -964,9 +990,18 @@ SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
BuildMI(BB, dl, TII.get(BROpcode)).addMBB(sinkMBB).addImm(CC);
F->insert(It, copy0MBB);
F->insert(It, sinkMBB);
- // Update machine-CFG edges by transferring all successors of the current
+ // Update machine-CFG edges by first adding all successors of the current
// block to the new block which will contain the Phi node for the select.
- sinkMBB->transferSuccessors(BB);
+ // Also inform sdisel of the edge changes.
+ for (MachineBasicBlock::succ_iterator I = BB->succ_begin(),
+ E = BB->succ_end(); I != E; ++I) {
+ EM->insert(std::make_pair(*I, sinkMBB));
+ sinkMBB->addSuccessor(*I);
+ }
+ // Next, remove all successors of the current block, and add the true
+ // and fallthrough blocks as its successors.
+ while (!BB->succ_empty())
+ BB->removeSuccessor(BB->succ_begin());
// Next, add the true and fallthrough blocks as its successors.
BB->addSuccessor(copy0MBB);
BB->addSuccessor(sinkMBB);
@@ -1011,7 +1046,7 @@ SparcTargetLowering::getConstraintType(const std::string &Constraint) const {
std::pair<unsigned, const TargetRegisterClass*>
SparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
- MVT VT) const {
+ EVT VT) const {
if (Constraint.size() == 1) {
switch (Constraint[0]) {
case 'r':
@@ -1024,7 +1059,7 @@ SparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
std::vector<unsigned> SparcTargetLowering::
getRegClassForInlineAsmConstraint(const std::string &Constraint,
- MVT VT) const {
+ EVT VT) const {
if (Constraint.size() != 1)
return std::vector<unsigned>();
@@ -1050,5 +1085,5 @@ SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
/// getFunctionAlignment - Return the Log2 alignment of this function.
unsigned SparcTargetLowering::getFunctionAlignment(const Function *) const {
- return 4;
+ return 2;
}
diff --git a/lib/Target/Sparc/SparcISelLowering.h b/lib/Target/Sparc/SparcISelLowering.h
index 27ce1b7..55781be 100644
--- a/lib/Target/Sparc/SparcISelLowering.h
+++ b/lib/Target/Sparc/SparcISelLowering.h
@@ -35,7 +35,8 @@ namespace llvm {
ITOF, // Int to FP within a FP register.
CALL, // A call instruction.
- RET_FLAG // Return with a flag operand.
+ RET_FLAG, // Return with a flag operand.
+ GLOBAL_BASE_REG // Global base reg for PIC
};
}
@@ -57,25 +58,49 @@ namespace llvm {
const SelectionDAG &DAG,
unsigned Depth = 0) const;
- virtual void LowerArguments(Function &F, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &ArgValues,
- DebugLoc dl);
virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI,
- MachineBasicBlock *MBB) const;
+ MachineBasicBlock *MBB,
+ DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const;
virtual const char *getTargetNodeName(unsigned Opcode) const;
ConstraintType getConstraintType(const std::string &Constraint) const;
std::pair<unsigned, const TargetRegisterClass*>
- getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const;
+ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const;
std::vector<unsigned>
getRegClassForInlineAsmConstraint(const std::string &Constraint,
- MVT VT) const;
+ EVT VT) const;
virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
/// getFunctionAlignment - Return the Log2 alignment of this function.
virtual unsigned getFunctionAlignment(const Function *F) const;
+
+ virtual SDValue
+ LowerFormalArguments(SDValue Chain,
+ CallingConv::ID CallConv,
+ bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals);
+
+ virtual SDValue
+ LowerCall(SDValue Chain, SDValue Callee,
+ CallingConv::ID CallConv, bool isVarArg,
+ bool isTailCall,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals);
+
+ virtual SDValue
+ LowerReturn(SDValue Chain,
+ CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ DebugLoc dl, SelectionDAG &DAG);
+
+ SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG);
+ SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG);
};
} // end namespace llvm
diff --git a/lib/Target/Sparc/SparcInstrInfo.cpp b/lib/Target/Sparc/SparcInstrInfo.cpp
index 12c286a..8667bca 100644
--- a/lib/Target/Sparc/SparcInstrInfo.cpp
+++ b/lib/Target/Sparc/SparcInstrInfo.cpp
@@ -17,7 +17,10 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Support/ErrorHandling.h"
#include "SparcGenInstrInfo.inc"
+#include "SparcMachineFunctionInfo.h"
using namespace llvm;
SparcInstrInfo::SparcInstrInfo(SparcSubtarget &ST)
@@ -160,30 +163,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
BuildMI(MBB, I, DL, get(SP::STDFri)).addFrameIndex(FI).addImm(0)
.addReg(SrcReg, getKillRegState(isKill));
else
- assert(0 && "Can't store this register to stack slot");
-}
-
-void SparcInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
- bool isKill,
- SmallVectorImpl<MachineOperand> &Addr,
- const TargetRegisterClass *RC,
- SmallVectorImpl<MachineInstr*> &NewMIs) const {
- unsigned Opc = 0;
- DebugLoc DL = DebugLoc::getUnknownLoc();
- if (RC == SP::IntRegsRegisterClass)
- Opc = SP::STri;
- else if (RC == SP::FPRegsRegisterClass)
- Opc = SP::STFri;
- else if (RC == SP::DFPRegsRegisterClass)
- Opc = SP::STDFri;
- else
- assert(0 && "Can't load this register");
- MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc));
- for (unsigned i = 0, e = Addr.size(); i != e; ++i)
- MIB.addOperand(Addr[i]);
- MIB.addReg(SrcReg, getKillRegState(isKill));
- NewMIs.push_back(MIB);
- return;
+ llvm_unreachable("Can't store this register to stack slot");
}
void SparcInstrInfo::
@@ -200,28 +180,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
else if (RC == SP::DFPRegsRegisterClass)
BuildMI(MBB, I, DL, get(SP::LDDFri), DestReg).addFrameIndex(FI).addImm(0);
else
- assert(0 && "Can't load this register from stack slot");
-}
-
-void SparcInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
- SmallVectorImpl<MachineOperand> &Addr,
- const TargetRegisterClass *RC,
- SmallVectorImpl<MachineInstr*> &NewMIs) const {
- unsigned Opc = 0;
- if (RC == SP::IntRegsRegisterClass)
- Opc = SP::LDri;
- else if (RC == SP::FPRegsRegisterClass)
- Opc = SP::LDFri;
- else if (RC == SP::DFPRegsRegisterClass)
- Opc = SP::LDDFri;
- else
- assert(0 && "Can't load this register");
- DebugLoc DL = DebugLoc::getUnknownLoc();
- MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg);
- for (unsigned i = 0, e = Addr.size(); i != e; ++i)
- MIB.addOperand(Addr[i]);
- NewMIs.push_back(MIB);
- return;
+ llvm_unreachable("Can't load this register from stack slot");
}
MachineInstr *SparcInstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
@@ -278,3 +237,25 @@ MachineInstr *SparcInstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
return NewMI;
}
+
+unsigned SparcInstrInfo::getGlobalBaseReg(MachineFunction *MF) const
+{
+ SparcMachineFunctionInfo *SparcFI = MF->getInfo<SparcMachineFunctionInfo>();
+ unsigned GlobalBaseReg = SparcFI->getGlobalBaseReg();
+ if (GlobalBaseReg != 0)
+ return GlobalBaseReg;
+
+ // Insert the set of GlobalBaseReg into the first MBB of the function
+ MachineBasicBlock &FirstMBB = MF->front();
+ MachineBasicBlock::iterator MBBI = FirstMBB.begin();
+ MachineRegisterInfo &RegInfo = MF->getRegInfo();
+
+ GlobalBaseReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
+
+
+ DebugLoc dl = DebugLoc::getUnknownLoc();
+
+ BuildMI(FirstMBB, MBBI, dl, get(SP::GETPCX), GlobalBaseReg);
+ SparcFI->setGlobalBaseReg(GlobalBaseReg);
+ return GlobalBaseReg;
+}
diff --git a/lib/Target/Sparc/SparcInstrInfo.h b/lib/Target/Sparc/SparcInstrInfo.h
index ab661b9..345674b 100644
--- a/lib/Target/Sparc/SparcInstrInfo.h
+++ b/lib/Target/Sparc/SparcInstrInfo.h
@@ -81,20 +81,10 @@ public:
unsigned SrcReg, bool isKill, int FrameIndex,
const TargetRegisterClass *RC) const;
- virtual void storeRegToAddr(MachineFunction &MF, unsigned SrcReg, bool isKill,
- SmallVectorImpl<MachineOperand> &Addr,
- const TargetRegisterClass *RC,
- SmallVectorImpl<MachineInstr*> &NewMIs) const;
-
virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned DestReg, int FrameIndex,
const TargetRegisterClass *RC) const;
-
- virtual void loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
- SmallVectorImpl<MachineOperand> &Addr,
- const TargetRegisterClass *RC,
- SmallVectorImpl<MachineInstr*> &NewMIs) const;
virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
MachineInstr* MI,
@@ -107,6 +97,8 @@ public:
MachineInstr* LoadMI) const {
return 0;
}
+
+ unsigned getGlobalBaseReg(MachineFunction *MF) const;
};
}
diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td
index 2d6c920..44821b8 100644
--- a/lib/Target/Sparc/SparcInstrInfo.td
+++ b/lib/Target/Sparc/SparcInstrInfo.td
@@ -117,7 +117,7 @@ def SPitof : SDNode<"SPISD::ITOF", SDTSPITOF>;
def SPselecticc : SDNode<"SPISD::SELECT_ICC", SDTSPselectcc, [SDNPInFlag]>;
def SPselectfcc : SDNode<"SPISD::SELECT_FCC", SDTSPselectcc, [SDNPInFlag]>;
-// These are target-independent nodes, but have target-specific formats.
+// These are target-independent nodes, but have target-specific formats.
def SDT_SPCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>;
def SDT_SPCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>,
SDTCisVT<1, i32> ]>;
@@ -134,6 +134,10 @@ def call : SDNode<"SPISD::CALL", SDT_SPCall,
def retflag : SDNode<"SPISD::RET_FLAG", SDTNone,
[SDNPHasChain, SDNPOptInFlag]>;
+def getPCX : Operand<i32> {
+ let PrintMethod = "printGetPCX";
+}
+
//===----------------------------------------------------------------------===//
// SPARC Flag Conditions
//===----------------------------------------------------------------------===//
@@ -207,6 +211,11 @@ multiclass F3_12np<string OpcStr, bits<6> Op3Val> {
class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSP<outs, ins, asmstr, pattern>;
+// GETPCX for PIC
+let Defs = [O7], Uses = [O7] in {
+ def GETPCX : Pseudo<(outs getPCX:$getpcseq), (ins), "$getpcseq", [] >;
+}
+
let Defs = [O6], Uses = [O6] in {
def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt),
"!ADJCALLSTACKDOWN $amt",
@@ -431,18 +440,23 @@ def LEA_ADDri : F3_2<2, 0b000000,
(outs IntRegs:$dst), (ins MEMri:$addr),
"add ${addr:arith}, $dst",
[(set IntRegs:$dst, ADDRri:$addr)]>;
-
-defm ADDCC : F3_12<"addcc", 0b010000, addc>;
+
+let Defs = [ICC] in
+ defm ADDCC : F3_12<"addcc", 0b010000, addc>;
+
defm ADDX : F3_12<"addx", 0b001000, adde>;
// Section B.15 - Subtract Instructions, p. 110
defm SUB : F3_12 <"sub" , 0b000100, sub>;
defm SUBX : F3_12 <"subx" , 0b001100, sube>;
-defm SUBCC : F3_12 <"subcc", 0b010100, SPcmpicc>;
-def SUBXCCrr: F3_1<2, 0b011100,
- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
- "subxcc $b, $c, $dst", []>;
+let Defs = [ICC] in {
+ defm SUBCC : F3_12 <"subcc", 0b010100, SPcmpicc>;
+
+ def SUBXCCrr: F3_1<2, 0b011100,
+ (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
+ "subxcc $b, $c, $dst", []>;
+}
// Section B.18 - Multiply Instructions, p. 113
defm UMUL : F3_12np<"umul", 0b001010>;
@@ -471,11 +485,12 @@ let isBarrier = 1 in
def BA : BranchSP<0b1000, (ins brtarget:$dst),
"ba $dst",
[(br bb:$dst)]>;
-
+
// FIXME: the encoding for the JIT should look at the condition field.
-def BCOND : BranchSP<0, (ins brtarget:$dst, CCOp:$cc),
- "b$cc $dst",
- [(SPbricc bb:$dst, imm:$cc)]>;
+let Uses = [ICC] in
+ def BCOND : BranchSP<0, (ins brtarget:$dst, CCOp:$cc),
+ "b$cc $dst",
+ [(SPbricc bb:$dst, imm:$cc)]>;
// Section B.22 - Branch on Floating-point Condition Codes Instructions, p. 121
@@ -489,9 +504,10 @@ class FPBranchSP<bits<4> cc, dag ins, string asmstr, list<dag> pattern>
}
// FIXME: the encoding for the JIT should look at the condition field.
-def FBCOND : FPBranchSP<0, (ins brtarget:$dst, CCOp:$cc),
- "fb$cc $dst",
- [(SPbrfcc bb:$dst, imm:$cc)]>;
+let Uses = [FCC] in
+ def FBCOND : FPBranchSP<0, (ins brtarget:$dst, CCOp:$cc),
+ "fb$cc $dst",
+ [(SPbrfcc bb:$dst, imm:$cc)]>;
// Section B.24 - Call and Link Instruction, p. 125
@@ -633,15 +649,16 @@ def FDIVD : F3_3<2, 0b110100, 0b001001110,
// Note 2: the result of a FCMP is not available until the 2nd cycle
// after the instr is retired, but there is no interlock. This behavior
// is modelled with a forced noop after the instruction.
-def FCMPS : F3_3<2, 0b110101, 0b001010001,
- (outs), (ins FPRegs:$src1, FPRegs:$src2),
- "fcmps $src1, $src2\n\tnop",
- [(SPcmpfcc FPRegs:$src1, FPRegs:$src2)]>;
-def FCMPD : F3_3<2, 0b110101, 0b001010010,
- (outs), (ins DFPRegs:$src1, DFPRegs:$src2),
- "fcmpd $src1, $src2\n\tnop",
- [(SPcmpfcc DFPRegs:$src1, DFPRegs:$src2)]>;
-
+let Defs = [FCC] in {
+ def FCMPS : F3_3<2, 0b110101, 0b001010001,
+ (outs), (ins FPRegs:$src1, FPRegs:$src2),
+ "fcmps $src1, $src2\n\tnop",
+ [(SPcmpfcc FPRegs:$src1, FPRegs:$src2)]>;
+ def FCMPD : F3_3<2, 0b110101, 0b001010010,
+ (outs), (ins DFPRegs:$src1, DFPRegs:$src2),
+ "fcmpd $src1, $src2\n\tnop",
+ [(SPcmpfcc DFPRegs:$src1, DFPRegs:$src2)]>;
+}
//===----------------------------------------------------------------------===//
// V9 Instructions
@@ -754,8 +771,6 @@ def : Pat<(call tglobaladdr:$dst),
def : Pat<(call texternalsym:$dst),
(CALL texternalsym:$dst)>;
-def : Pat<(ret), (RETL)>;
-
// Map integer extload's to zextloads.
def : Pat<(i32 (extloadi1 ADDRrr:$src)), (LDUBrr ADDRrr:$src)>;
def : Pat<(i32 (extloadi1 ADDRri:$src)), (LDUBri ADDRri:$src)>;
diff --git a/lib/Target/Sparc/SparcMCAsmInfo.cpp b/lib/Target/Sparc/SparcMCAsmInfo.cpp
new file mode 100644
index 0000000..b67537c
--- /dev/null
+++ b/lib/Target/Sparc/SparcMCAsmInfo.cpp
@@ -0,0 +1,38 @@
+//===-- SparcMCAsmInfo.cpp - Sparc asm properties -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declarations of the SparcMCAsmInfo properties.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SparcMCAsmInfo.h"
+#include "llvm/ADT/SmallVector.h"
+using namespace llvm;
+
+SparcELFMCAsmInfo::SparcELFMCAsmInfo(const Target &T, const StringRef &TT) {
+ Data16bitsDirective = "\t.half\t";
+ Data32bitsDirective = "\t.word\t";
+ Data64bitsDirective = 0; // .xword is only supported by V9.
+ ZeroDirective = "\t.skip\t";
+ CommentString = "!";
+ COMMDirectiveTakesAlignment = true;
+ HasLEB128 = true;
+ AbsoluteDebugSectionOffsets = true;
+ SupportsDebugInformation = true;
+
+ SunStyleELFSectionSwitchSyntax = true;
+ UsesELFSectionDirectiveForBSS = true;
+
+ WeakRefDirective = "\t.weak\t";
+ SetDirective = "\t.set\t";
+
+ PrivateGlobalPrefix = ".L";
+}
+
+
diff --git a/lib/Target/Sparc/SparcMCAsmInfo.h b/lib/Target/Sparc/SparcMCAsmInfo.h
new file mode 100644
index 0000000..12d6ef4
--- /dev/null
+++ b/lib/Target/Sparc/SparcMCAsmInfo.h
@@ -0,0 +1,28 @@
+//=====-- SparcMCAsmInfo.h - Sparc asm properties -------------*- C++ -*--====//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the SparcMCAsmInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SPARCTARGETASMINFO_H
+#define SPARCTARGETASMINFO_H
+
+#include "llvm/MC/MCAsmInfo.h"
+
+namespace llvm {
+ class Target;
+ class StringRef;
+ struct SparcELFMCAsmInfo : public MCAsmInfo {
+ explicit SparcELFMCAsmInfo(const Target &T, const StringRef &TT);
+ };
+
+} // namespace llvm
+
+#endif
diff --git a/lib/Target/Sparc/SparcMachineFunctionInfo.h b/lib/Target/Sparc/SparcMachineFunctionInfo.h
new file mode 100644
index 0000000..e457235
--- /dev/null
+++ b/lib/Target/Sparc/SparcMachineFunctionInfo.h
@@ -0,0 +1,32 @@
+//===- SparcMachineFunctionInfo.h - Sparc Machine Function Info -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares Sparc specific per-machine-function information.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SPARCMACHINEFUNCTIONINFO_H
+#define SPARCMACHINEFUNCTIONINFO_H
+
+#include "llvm/CodeGen/MachineFunction.h"
+
+namespace llvm {
+
+ class SparcMachineFunctionInfo : public MachineFunctionInfo {
+ private:
+ unsigned GlobalBaseReg;
+ public:
+ SparcMachineFunctionInfo() : GlobalBaseReg(0) {}
+ SparcMachineFunctionInfo(MachineFunction &MF) : GlobalBaseReg(0) {}
+
+ unsigned getGlobalBaseReg() const { return GlobalBaseReg; }
+ void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; }
+ };
+}
+
+#endif
diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp
index 59efb19..7883260 100644
--- a/lib/Target/Sparc/SparcRegisterInfo.cpp
+++ b/lib/Target/Sparc/SparcRegisterInfo.cpp
@@ -18,6 +18,7 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineLocation.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Type.h"
#include "llvm/ADT/BitVector.h"
@@ -75,8 +76,10 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MBB.erase(I);
}
-void SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, RegScavenger *RS) const {
+unsigned
+SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
+ int SPAdj, int *Value,
+ RegScavenger *RS) const {
assert(SPAdj == 0 && "Unexpected");
unsigned i = 0;
@@ -112,6 +115,7 @@ void SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
MI.getOperand(i).ChangeToRegister(SP::G1, false);
MI.getOperand(i+1).ChangeToImmediate(Offset & ((1 << 10)-1));
}
+ return 0;
}
void SparcRegisterInfo::
@@ -168,28 +172,25 @@ void SparcRegisterInfo::emitEpilogue(MachineFunction &MF,
}
unsigned SparcRegisterInfo::getRARegister() const {
- assert(0 && "What is the return address register");
- return 0;
+ return SP::I7;
}
unsigned SparcRegisterInfo::getFrameRegister(MachineFunction &MF) const {
- assert(0 && "What is the frame register");
- return SP::G1;
+ return SP::I6;
}
unsigned SparcRegisterInfo::getEHExceptionRegister() const {
- assert(0 && "What is the exception register");
+ llvm_unreachable("What is the exception register");
return 0;
}
unsigned SparcRegisterInfo::getEHHandlerRegister() const {
- assert(0 && "What is the exception handler register");
+ llvm_unreachable("What is the exception handler register");
return 0;
}
int SparcRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
- assert(0 && "What is the dwarf register number");
- return -1;
+ return SparcGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
}
#include "SparcGenRegisterInfo.inc"
diff --git a/lib/Target/Sparc/SparcRegisterInfo.h b/lib/Target/Sparc/SparcRegisterInfo.h
index fc863f3..753b1c0 100644
--- a/lib/Target/Sparc/SparcRegisterInfo.h
+++ b/lib/Target/Sparc/SparcRegisterInfo.h
@@ -43,8 +43,9 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo {
MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
- void eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, RegScavenger *RS = NULL) const;
+ unsigned eliminateFrameIndex(MachineBasicBlock::iterator II,
+ int SPAdj, int *Value = NULL,
+ RegScavenger *RS = NULL) const;
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
diff --git a/lib/Target/Sparc/SparcRegisterInfo.td b/lib/Target/Sparc/SparcRegisterInfo.td
index e3a50ca..2b05c19 100644
--- a/lib/Target/Sparc/SparcRegisterInfo.td
+++ b/lib/Target/Sparc/SparcRegisterInfo.td
@@ -16,6 +16,10 @@ class SparcReg<string n> : Register<n> {
let Namespace = "SP";
}
+class SparcCtrlReg<string n>: Register<n> {
+ let Namespace = "SP";
+}
+
// Registers are identified with 5-bit ID numbers.
// Ri - 32-bit integer registers
class Ri<bits<5> num, string n> : SparcReg<n> {
@@ -31,6 +35,10 @@ class Rd<bits<5> num, string n, list<Register> subregs> : SparcReg<n> {
let SubRegs = subregs;
}
+// Control Registers
+def ICC : SparcCtrlReg<"ICC">;
+def FCC : SparcCtrlReg<"FCC">;
+
// Integer registers
def G0 : Ri< 0, "G0">, DwarfRegNum<[0]>;
def G1 : Ri< 1, "G1">, DwarfRegNum<[1]>;
@@ -46,7 +54,7 @@ def O2 : Ri<10, "O2">, DwarfRegNum<[10]>;
def O3 : Ri<11, "O3">, DwarfRegNum<[11]>;
def O4 : Ri<12, "O4">, DwarfRegNum<[12]>;
def O5 : Ri<13, "O5">, DwarfRegNum<[13]>;
-def O6 : Ri<14, "O6">, DwarfRegNum<[14]>;
+def O6 : Ri<14, "SP">, DwarfRegNum<[14]>;
def O7 : Ri<15, "O7">, DwarfRegNum<[15]>;
def L0 : Ri<16, "L0">, DwarfRegNum<[16]>;
def L1 : Ri<17, "L1">, DwarfRegNum<[17]>;
@@ -62,7 +70,7 @@ def I2 : Ri<26, "I2">, DwarfRegNum<[26]>;
def I3 : Ri<27, "I3">, DwarfRegNum<[27]>;
def I4 : Ri<28, "I4">, DwarfRegNum<[28]>;
def I5 : Ri<29, "I5">, DwarfRegNum<[29]>;
-def I6 : Ri<30, "I6">, DwarfRegNum<[30]>;
+def I6 : Ri<30, "FP">, DwarfRegNum<[30]>;
def I7 : Ri<31, "I7">, DwarfRegNum<[31]>;
// Floating-point registers
diff --git a/lib/Target/Sparc/SparcSubtarget.cpp b/lib/Target/Sparc/SparcSubtarget.cpp
index aaddbff..8a88cc0 100644
--- a/lib/Target/Sparc/SparcSubtarget.cpp
+++ b/lib/Target/Sparc/SparcSubtarget.cpp
@@ -22,7 +22,7 @@ namespace {
cl::desc("Enable V9 instructions in the V8 target"));
}
-SparcSubtarget::SparcSubtarget(const Module &M, const std::string &FS) {
+SparcSubtarget::SparcSubtarget(const std::string &TT, const std::string &FS) {
// Set the default features.
IsV9 = false;
V8DeprecatedInsts = false;
diff --git a/lib/Target/Sparc/SparcSubtarget.h b/lib/Target/Sparc/SparcSubtarget.h
index e5a5ba4..4377034 100644
--- a/lib/Target/Sparc/SparcSubtarget.h
+++ b/lib/Target/Sparc/SparcSubtarget.h
@@ -18,14 +18,13 @@
#include <string>
namespace llvm {
- class Module;
-
+
class SparcSubtarget : public TargetSubtarget {
bool IsV9;
bool V8DeprecatedInsts;
bool IsVIS;
public:
- SparcSubtarget(const Module &M, const std::string &FS);
+ SparcSubtarget(const std::string &TT, const std::string &FS);
bool isV9() const { return IsV9; }
bool isVIS() const { return IsVIS; }
diff --git a/lib/Target/Sparc/SparcTargetMachine.cpp b/lib/Target/Sparc/SparcTargetMachine.cpp
index 1343bcc..3a38115 100644
--- a/lib/Target/Sparc/SparcTargetMachine.cpp
+++ b/lib/Target/Sparc/SparcTargetMachine.cpp
@@ -10,63 +10,30 @@
//
//===----------------------------------------------------------------------===//
-#include "SparcTargetAsmInfo.h"
+#include "SparcMCAsmInfo.h"
#include "SparcTargetMachine.h"
#include "Sparc.h"
-#include "llvm/Module.h"
#include "llvm/PassManager.h"
-#include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/Target/TargetRegistry.h"
using namespace llvm;
-// Register the target.
-static RegisterTarget<SparcTargetMachine> X("sparc", "SPARC");
+extern "C" void LLVMInitializeSparcTarget() {
+ // Register the target.
+ RegisterTargetMachine<SparcTargetMachine> X(TheSparcTarget);
+ RegisterAsmInfo<SparcELFMCAsmInfo> Y(TheSparcTarget);
-// No assembler printer by default
-SparcTargetMachine::AsmPrinterCtorFn SparcTargetMachine::AsmPrinterCtor = 0;
-
-
-// Force static initialization.
-extern "C" void LLVMInitializeSparcTarget() { }
-
-const TargetAsmInfo *SparcTargetMachine::createTargetAsmInfo() const {
- // FIXME: Handle Solaris subtarget someday :)
- return new SparcELFTargetAsmInfo(*this);
}
/// SparcTargetMachine ctor - Create an ILP32 architecture model
///
-SparcTargetMachine::SparcTargetMachine(const Module &M, const std::string &FS)
- : DataLayout("E-p:32:32-f128:128:128"),
- Subtarget(M, FS), TLInfo(*this), InstrInfo(Subtarget),
+SparcTargetMachine::SparcTargetMachine(const Target &T, const std::string &TT,
+ const std::string &FS)
+ : LLVMTargetMachine(T, TT),
+ DataLayout("E-p:32:32-f128:128:128"),
+ Subtarget(TT, FS), TLInfo(*this), InstrInfo(Subtarget),
FrameInfo(TargetFrameInfo::StackGrowsDown, 8, 0) {
}
-unsigned SparcTargetMachine::getModuleMatchQuality(const Module &M) {
- std::string TT = M.getTargetTriple();
- if (TT.size() >= 6 && std::string(TT.begin(), TT.begin()+6) == "sparc-")
- return 20;
-
- // If the target triple is something non-sparc, we don't match.
- if (!TT.empty()) return 0;
-
- if (M.getEndianness() == Module::BigEndian &&
- M.getPointerSize() == Module::Pointer32)
-#ifdef __sparc__
- return 20; // BE/32 ==> Prefer sparc on sparc
-#else
- return 5; // BE/32 ==> Prefer ppc elsewhere
-#endif
- else if (M.getEndianness() != Module::AnyEndianness ||
- M.getPointerSize() != Module::AnyPointerSize)
- return 0; // Match for some other target
-
-#if defined(__sparc__)
- return 10;
-#else
- return 0;
-#endif
-}
-
bool SparcTargetMachine::addInstSelector(PassManagerBase &PM,
CodeGenOpt::Level OptLevel) {
PM.add(createSparcISelDag(*this));
@@ -82,14 +49,3 @@ bool SparcTargetMachine::addPreEmitPass(PassManagerBase &PM,
PM.add(createSparcDelaySlotFillerPass(*this));
return true;
}
-
-bool SparcTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
- CodeGenOpt::Level OptLevel,
- bool Verbose,
- raw_ostream &Out) {
- // Output assembly language.
- assert(AsmPrinterCtor && "AsmPrinter was not linked in");
- if (AsmPrinterCtor)
- PM.add(AsmPrinterCtor(Out, *this, Verbose));
- return false;
-}
diff --git a/lib/Target/Sparc/SparcTargetMachine.h b/lib/Target/Sparc/SparcTargetMachine.h
index ee55d3c..cce5510 100644
--- a/lib/Target/Sparc/SparcTargetMachine.h
+++ b/lib/Target/Sparc/SparcTargetMachine.h
@@ -23,27 +23,15 @@
namespace llvm {
-class Module;
-
class SparcTargetMachine : public LLVMTargetMachine {
const TargetData DataLayout; // Calculates type size & alignment
SparcSubtarget Subtarget;
SparcTargetLowering TLInfo;
SparcInstrInfo InstrInfo;
TargetFrameInfo FrameInfo;
-
-protected:
- virtual const TargetAsmInfo *createTargetAsmInfo() const;
-
- // To avoid having target depend on the asmprinter stuff libraries, asmprinter
- // set this functions to ctor pointer at startup time if they are linked in.
- typedef FunctionPass *(*AsmPrinterCtorFn)(raw_ostream &o,
- TargetMachine &tm,
- bool verbose);
- static AsmPrinterCtorFn AsmPrinterCtor;
-
public:
- SparcTargetMachine(const Module &M, const std::string &FS);
+ SparcTargetMachine(const Target &T, const std::string &TT,
+ const std::string &FS);
virtual const SparcInstrInfo *getInstrInfo() const { return &InstrInfo; }
virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; }
@@ -55,18 +43,10 @@ public:
return const_cast<SparcTargetLowering*>(&TLInfo);
}
virtual const TargetData *getTargetData() const { return &DataLayout; }
- static unsigned getModuleMatchQuality(const Module &M);
// Pass Pipeline Configuration
virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
- virtual bool addAssemblyEmitter(PassManagerBase &PM,
- CodeGenOpt::Level OptLevel,
- bool Verbose, raw_ostream &Out);
-
- static void registerAsmPrinter(AsmPrinterCtorFn F) {
- AsmPrinterCtor = F;
- }
};
} // end namespace llvm
diff --git a/lib/Target/Sparc/TargetInfo/CMakeLists.txt b/lib/Target/Sparc/TargetInfo/CMakeLists.txt
new file mode 100644
index 0000000..870b56a
--- /dev/null
+++ b/lib/Target/Sparc/TargetInfo/CMakeLists.txt
@@ -0,0 +1,7 @@
+include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. )
+
+add_llvm_library(LLVMSparcInfo
+ SparcTargetInfo.cpp
+ )
+
+add_dependencies(LLVMSparcInfo SparcCodeGenTable_gen)
diff --git a/lib/Target/Sparc/TargetInfo/Makefile b/lib/Target/Sparc/TargetInfo/Makefile
new file mode 100644
index 0000000..641ed87
--- /dev/null
+++ b/lib/Target/Sparc/TargetInfo/Makefile
@@ -0,0 +1,15 @@
+##===- lib/Target/Sparc/TargetInfo/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 = LLVMSparcInfo
+
+# Hack: we need to include 'main' target directory to grab private headers
+CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
+
+include $(LEVEL)/Makefile.common
diff --git a/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp b/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp
new file mode 100644
index 0000000..5d697bd
--- /dev/null
+++ b/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp
@@ -0,0 +1,19 @@
+//===-- SparcTargetInfo.cpp - Sparc Target Implementation -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sparc.h"
+#include "llvm/Module.h"
+#include "llvm/Target/TargetRegistry.h"
+using namespace llvm;
+
+Target llvm::TheSparcTarget;
+
+extern "C" void LLVMInitializeSparcTargetInfo() {
+ RegisterTarget<Triple::sparc> X(TheSparcTarget, "sparc", "Sparc");
+}
OpenPOWER on IntegriCloud