diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2009-10-14 17:57:32 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2009-10-14 17:57:32 +0000 |
commit | cd749a9c07f1de2fb8affde90537efa4bc3e7c54 (patch) | |
tree | b21f6de4e08b89bb7931806bab798fc2a5e3a686 /lib/Target/Sparc | |
parent | 72621d11de5b873f1695f391eb95f0b336c3d2d4 (diff) | |
download | FreeBSD-src-cd749a9c07f1de2fb8affde90537efa4bc3e7c54.zip FreeBSD-src-cd749a9c07f1de2fb8affde90537efa4bc3e7c54.tar.gz |
Update llvm to r84119.
Diffstat (limited to 'lib/Target/Sparc')
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"); +} |