X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSparc%2FSparcISelLowering.cpp;h=168640f457ff7366fdcf1c41a6059af1afb48ef3;hb=0b8c9a80f20772c3793201ab5b251d3520b9cea3;hp=959d41ab8b858cdc9b7096289523c6a5a8487a01;hpb=e50ed30282bb5b4a9ed952580523f2dda16215ac;p=oota-llvm.git diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index 959d41ab8b8..168640f457f 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -13,16 +13,18 @@ //===----------------------------------------------------------------------===// #include "SparcISelLowering.h" +#include "SparcMachineFunctionInfo.h" #include "SparcTargetMachine.h" -#include "llvm/Function.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #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/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; @@ -31,30 +33,74 @@ using namespace llvm; // Calling Convention Implementation //===----------------------------------------------------------------------===// +static bool CC_Sparc_Assign_SRet(unsigned &ValNo, MVT &ValVT, + MVT &LocVT, CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, CCState &State) +{ + assert (ArgFlags.isSRet()); + + //Assign SRet argument + State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, + 0, + LocVT, LocInfo)); + return true; +} + +static bool CC_Sparc_Assign_f64(unsigned &ValNo, MVT &ValVT, + MVT &LocVT, CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, CCState &State) +{ + static const uint16_t RegList[] = { + SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 + }; + //Try to get first reg + if (unsigned Reg = State.AllocateReg(RegList, 6)) { + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + } else { + //Assign whole thing in stack + State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, + State.AllocateStack(8,4), + LocVT, LocInfo)); + return true; + } + + //Try to get second reg + if (unsigned Reg = State.AllocateReg(RegList, 6)) + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + else + State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, + State.AllocateStack(4,4), + LocVT, LocInfo)); + return true; +} + #include "SparcGenCallingConv.inc" SDValue SparcTargetLowering::LowerReturn(SDValue Chain, - unsigned CallConv, bool isVarArg, + CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl &Outs, - DebugLoc dl, SelectionDAG &DAG) { + const SmallVectorImpl &OutVals, + DebugLoc dl, SelectionDAG &DAG) const { + + MachineFunction &MF = DAG.getMachineFunction(); // CCValAssign - represent the assignment of the return value to locations. SmallVector RVLocs; // CCState - Info about the registers and stack slot. - CCState CCInfo(CallConv, isVarArg, DAG.getTarget(), - RVLocs, *DAG.getContext()); + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + DAG.getTarget(), RVLocs, *DAG.getContext()); // 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. - if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { + if (MF.getRegInfo().liveout_empty()) { for (unsigned i = 0; i != RVLocs.size(); ++i) if (RVLocs[i].isRegLoc()) - DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); + MF.getRegInfo().addLiveOut(RVLocs[i].getLocReg()); } SDValue Flag; @@ -64,16 +110,35 @@ SparcTargetLowering::LowerReturn(SDValue Chain, CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); - Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), - Outs[i].Val, Flag); + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), + OutVals[i], Flag); // Guarantee that all emitted copies are stuck together with flags. Flag = Chain.getValue(1); } + unsigned RetAddrOffset = 8; //Call Inst + Delay Slot + // If the function returns a struct, copy the SRetReturnReg to I0 + if (MF.getFunction()->hasStructRetAttr()) { + SparcMachineFunctionInfo *SFI = MF.getInfo(); + unsigned Reg = SFI->getSRetReturnReg(); + if (!Reg) + llvm_unreachable("sret virtual register not created in the entry block"); + SDValue Val = DAG.getCopyFromReg(Chain, dl, Reg, getPointerTy()); + Chain = DAG.getCopyToReg(Chain, dl, SP::I0, Val, Flag); + Flag = Chain.getValue(1); + if (MF.getRegInfo().liveout_empty()) + MF.getRegInfo().addLiveOut(SP::I0); + RetAddrOffset = 12; // CallInst + Delay Slot + Unimp + } + + SDValue RetAddrOffsetNode = DAG.getConstant(RetAddrOffset, MVT::i32); + if (Flag.getNode()) - return DAG.getNode(SPISD::RET_FLAG, dl, EVT::Other, Chain, Flag); - return DAG.getNode(SPISD::RET_FLAG, dl, EVT::Other, Chain); + return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain, + RetAddrOffsetNode, Flag); + return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain, + RetAddrOffsetNode); } /// LowerFormalArguments - V8 uses a very simple ABI, where all values are @@ -81,162 +146,197 @@ SparcTargetLowering::LowerReturn(SDValue Chain, /// pass FP values in FP registers for fastcc functions. SDValue SparcTargetLowering::LowerFormalArguments(SDValue Chain, - unsigned CallConv, bool isVarArg, + CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl &Ins, DebugLoc dl, SelectionDAG &DAG, - SmallVectorImpl &InVals) { + SmallVectorImpl &InVals) + const { MachineFunction &MF = DAG.getMachineFunction(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); + SparcMachineFunctionInfo *FuncInfo = MF.getInfo(); // Assign locations to all of the incoming arguments. SmallVector ArgLocs; - CCState CCInfo(CallConv, isVarArg, getTargetMachine(), - ArgLocs, *DAG.getContext()); + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + 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; + const unsigned StackOffset = 92; 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()) { - default: llvm_unreachable("Unhandled argument type!"); - case EVT::i1: - case EVT::i8: - case EVT::i16: - case EVT::i32: - if (!Ins[i].Used) { // Argument is dead. - if (CurArgReg < ArgRegEnd) ++CurArgReg; - 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(Chain, dl, VReg, EVT::i32); - if (ObjectVT != EVT::i32) { - unsigned AssertOp = ISD::AssertSext; - Arg = DAG.getNode(AssertOp, dl, EVT::i32, Arg, - DAG.getValueType(ObjectVT)); - Arg = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Arg); - } - InVals.push_back(Arg); - } else { - int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset); - SDValue FIPtr = DAG.getFrameIndex(FrameIdx, EVT::i32); - SDValue Load; - if (ObjectVT == EVT::i32) { - Load = DAG.getLoad(EVT::i32, dl, Chain, FIPtr, NULL, 0); - } else { - ISD::LoadExtType LoadOp = ISD::SEXTLOAD; - - // Sparc is big endian, so add an offset based on the ObjectVT. - unsigned Offset = 4-std::max(1U, ObjectVT.getSizeInBits()/8); - FIPtr = DAG.getNode(ISD::ADD, dl, EVT::i32, FIPtr, - DAG.getConstant(Offset, EVT::i32)); - Load = DAG.getExtLoad(LoadOp, dl, EVT::i32, Chain, FIPtr, - NULL, 0, ObjectVT); - Load = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Load); - } - InVals.push_back(Load); - } - ArgOffset += 4; - break; - case EVT::f32: - if (!Ins[i].Used) { // Argument is dead. - if (CurArgReg < ArgRegEnd) ++CurArgReg; - 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(Chain, dl, VReg, EVT::i32); - - Arg = DAG.getNode(ISD::BIT_CONVERT, dl, EVT::f32, Arg); - InVals.push_back(Arg); - } else { - int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset); - SDValue FIPtr = DAG.getFrameIndex(FrameIdx, EVT::i32); - SDValue Load = DAG.getLoad(EVT::f32, dl, Chain, FIPtr, NULL, 0); - InVals.push_back(Load); - } - ArgOffset += 4; - break; + if (i == 0 && Ins[i].Flags.isSRet()) { + //Get SRet from [%fp+64] + int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, 64, true); + SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); + SDValue Arg = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, + MachinePointerInfo(), + false, false, false, 0); + InVals.push_back(Arg); + continue; + } - case EVT::i64: - case EVT::f64: - if (!Ins[i].Used) { // Argument is dead. - if (CurArgReg < ArgRegEnd) ++CurArgReg; - if (CurArgReg < ArgRegEnd) ++CurArgReg; - 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(Chain, dl, VRegHi, EVT::i32); - } else { - int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset); - SDValue FIPtr = DAG.getFrameIndex(FrameIdx, EVT::i32); - HiVal = DAG.getLoad(EVT::i32, dl, Chain, FIPtr, NULL, 0); - } + if (VA.isRegLoc()) { + if (VA.needsCustom()) { + assert(VA.getLocVT() == MVT::f64); + unsigned VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); + MF.getRegInfo().addLiveIn(VA.getLocReg(), VRegHi); + SDValue HiVal = DAG.getCopyFromReg(Chain, dl, VRegHi, MVT::i32); + + assert(i+1 < e); + CCValAssign &NextVA = ArgLocs[++i]; SDValue LoVal; - if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR - unsigned VRegLo = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); - MF.getRegInfo().addLiveIn(*CurArgReg++, VRegLo); - LoVal = DAG.getCopyFromReg(Chain, dl, VRegLo, EVT::i32); + if (NextVA.isMemLoc()) { + int FrameIdx = MF.getFrameInfo()-> + CreateFixedObject(4, StackOffset+NextVA.getLocMemOffset(),true); + SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); + LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, + MachinePointerInfo(), + false, false, false, 0); } else { - int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset+4); - SDValue FIPtr = DAG.getFrameIndex(FrameIdx, EVT::i32); - LoVal = DAG.getLoad(EVT::i32, dl, Chain, FIPtr, NULL, 0); + unsigned loReg = MF.addLiveIn(NextVA.getLocReg(), + &SP::IntRegsRegClass); + LoVal = DAG.getCopyFromReg(Chain, dl, loReg, MVT::i32); } - - // Compose the two halves together into an i64 unit. SDValue WholeValue = - DAG.getNode(ISD::BUILD_PAIR, dl, EVT::i64, LoVal, HiVal); + DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal); + WholeValue = DAG.getNode(ISD::BITCAST, dl, MVT::f64, WholeValue); + InVals.push_back(WholeValue); + continue; + } + unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); + MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg); + SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); + if (VA.getLocVT() == MVT::f32) + Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg); + else if (VA.getLocVT() != MVT::i32) { + Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg, + DAG.getValueType(VA.getLocVT())); + Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg); + } + InVals.push_back(Arg); + continue; + } - // If we want a double, do a bit convert. - if (ObjectVT == EVT::f64) - WholeValue = DAG.getNode(ISD::BIT_CONVERT, dl, EVT::f64, WholeValue); + assert(VA.isMemLoc()); - InVals.push_back(WholeValue); + unsigned Offset = VA.getLocMemOffset()+StackOffset; + + if (VA.needsCustom()) { + assert(VA.getValVT() == MVT::f64); + //If it is double-word aligned, just load. + if (Offset % 8 == 0) { + int FI = MF.getFrameInfo()->CreateFixedObject(8, + Offset, + true); + SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy()); + SDValue Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, + MachinePointerInfo(), + false,false, false, 0); + InVals.push_back(Load); + continue; } - ArgOffset += 8; - break; + + int FI = MF.getFrameInfo()->CreateFixedObject(4, + Offset, + true); + SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy()); + SDValue HiVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, + MachinePointerInfo(), + false, false, false, 0); + int FI2 = MF.getFrameInfo()->CreateFixedObject(4, + Offset+4, + true); + SDValue FIPtr2 = DAG.getFrameIndex(FI2, getPointerTy()); + + SDValue LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, + MachinePointerInfo(), + false, false, false, 0); + + SDValue WholeValue = + DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal); + WholeValue = DAG.getNode(ISD::BITCAST, dl, MVT::f64, WholeValue); + InVals.push_back(WholeValue); + continue; } + + int FI = MF.getFrameInfo()->CreateFixedObject(4, + Offset, + true); + SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy()); + SDValue Load ; + if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) { + Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, + MachinePointerInfo(), + false, false, false, 0); + } else { + ISD::LoadExtType LoadOp = ISD::SEXTLOAD; + // Sparc is big endian, so add an offset based on the ObjectVT. + unsigned Offset = 4-std::max(1U, VA.getValVT().getSizeInBits()/8); + FIPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, FIPtr, + DAG.getConstant(Offset, MVT::i32)); + Load = DAG.getExtLoad(LoadOp, dl, MVT::i32, Chain, FIPtr, + MachinePointerInfo(), + VA.getValVT(), false, false,0); + Load = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), Load); + } + InVals.push_back(Load); + } + + if (MF.getFunction()->hasStructRetAttr()) { + //Copy the SRet Argument to SRetReturnReg + SparcMachineFunctionInfo *SFI = MF.getInfo(); + unsigned Reg = SFI->getSRetReturnReg(); + if (!Reg) { + Reg = MF.getRegInfo().createVirtualRegister(&SP::IntRegsRegClass); + SFI->setSRetReturnReg(Reg); + } + SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[0]); + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain); } // Store remaining ArgRegs to the stack if this is a varargs function. if (isVarArg) { + static const uint16_t ArgRegs[] = { + SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 + }; + unsigned NumAllocated = CCInfo.getFirstUnallocated(ArgRegs, 6); + const uint16_t *CurArgReg = ArgRegs+NumAllocated, *ArgRegEnd = ArgRegs+6; + unsigned ArgOffset = CCInfo.getNextStackOffset(); + if (NumAllocated == 6) + ArgOffset += StackOffset; + else { + assert(!ArgOffset); + ArgOffset = 68+4*NumAllocated; + } + // Remember the vararg offset for the va_start implementation. - VarArgsFrameOffset = ArgOffset; + FuncInfo->setVarArgsFrameOffset(ArgOffset); std::vector OutChains; for (; CurArgReg != ArgRegEnd; ++CurArgReg) { unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); MF.getRegInfo().addLiveIn(*CurArgReg, VReg); - SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, EVT::i32); + SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, MVT::i32); - int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset); - SDValue FIPtr = DAG.getFrameIndex(FrameIdx, EVT::i32); + int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset, + true); + SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - OutChains.push_back(DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, NULL, 0)); + OutChains.push_back(DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, + MachinePointerInfo(), + false, false, 0)); ArgOffset += 4; } if (!OutChains.empty()) { OutChains.push_back(Chain); - Chain = DAG.getNode(ISD::TokenFactor, dl, EVT::Other, + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &OutChains[0], OutChains.size()); } } @@ -245,203 +345,207 @@ SparcTargetLowering::LowerFormalArguments(SDValue Chain, } SDValue -SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, - unsigned CallConv, bool isVarArg, - bool isTailCall, - const SmallVectorImpl &Outs, - const SmallVectorImpl &Ins, - DebugLoc dl, SelectionDAG &DAG, - SmallVectorImpl &InVals) { - -#if 0 +SparcTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, + SmallVectorImpl &InVals) const { + SelectionDAG &DAG = CLI.DAG; + DebugLoc &dl = CLI.DL; + SmallVector &Outs = CLI.Outs; + SmallVector &OutVals = CLI.OutVals; + SmallVector &Ins = CLI.Ins; + SDValue Chain = CLI.Chain; + SDValue Callee = CLI.Callee; + bool &isTailCall = CLI.IsTailCall; + CallingConv::ID CallConv = CLI.CallConv; + bool isVarArg = CLI.IsVarArg; + + // Sparc target does not yet support tail call optimization. + isTailCall = false; + // Analyze operands of the call, assigning locations to each operand. SmallVector ArgLocs; - CCState CCInfo(CallConv, isVarArg, DAG.getTarget(), ArgLocs); + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + DAG.getTarget(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeCallOperands(Outs, CC_Sparc32); // Get the size of the outgoing arguments stack space requirement. unsigned ArgsSize = CCInfo.getNextStackOffset(); - // FIXME: We can't use this until f64 is known to take two GPRs. -#else - (void)CC_Sparc32; - - // Count the size of the outgoing arguments. - unsigned ArgsSize = 0; - for (unsigned i = 0, e = Outs.size(); i != e; ++i) { - switch (Outs[i].Val.getValueType().getSimpleVT()) { - default: llvm_unreachable("Unknown value type!"); - case EVT::i1: - case EVT::i8: - case EVT::i16: - case EVT::i32: - case EVT::f32: - ArgsSize += 4; - break; - case EVT::i64: - case EVT::f64: - ArgsSize += 8; - break; - } - } - if (ArgsSize > 4*6) - ArgsSize -= 4*6; // Space for first 6 arguments is prereserved. - else - ArgsSize = 0; -#endif // Keep stack frames 8-byte aligned. ArgsSize = (ArgsSize+7) & ~7; + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + + //Create local copies for byval args. + SmallVector ByValArgs; + for (unsigned i = 0, e = Outs.size(); i != e; ++i) { + ISD::ArgFlagsTy Flags = Outs[i].Flags; + if (!Flags.isByVal()) + continue; + + SDValue Arg = OutVals[i]; + unsigned Size = Flags.getByValSize(); + unsigned Align = Flags.getByValAlign(); + + int FI = MFI->CreateStackObject(Size, Align, false); + SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy()); + SDValue SizeNode = DAG.getConstant(Size, MVT::i32); + + Chain = DAG.getMemcpy(Chain, dl, FIPtr, Arg, SizeNode, Align, + false, //isVolatile, + (Size <= 32), //AlwaysInline if size <= 32 + MachinePointerInfo(), MachinePointerInfo()); + ByValArgs.push_back(FIPtr); + } + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(ArgsSize, true)); SmallVector, 8> RegsToPass; SmallVector MemOpChains; -#if 0 + const unsigned StackOffset = 92; + bool hasStructRetAttr = false; // Walk the register/memloc assignments, inserting copies/loads. - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size(); + i != e; + ++i, ++realArgIdx) { CCValAssign &VA = ArgLocs[i]; - SDValue Arg = Outs[i].Val; + SDValue Arg = OutVals[realArgIdx]; + + ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags; + + //Use local copy if it is a byval arg. + if (Flags.isByVal()) + Arg = ByValArgs[byvalArgIdx++]; // Promote the value if needed. switch (VA.getLocInfo()) { default: llvm_unreachable("Unknown loc info!"); case CCValAssign::Full: break; case CCValAssign::SExt: - Arg = DAG.getNode(ISD::SIGN_EXTEND, VA.getLocVT(), Arg); + Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); break; case CCValAssign::ZExt: - Arg = DAG.getNode(ISD::ZERO_EXTEND, VA.getLocVT(), Arg); + Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); break; case CCValAssign::AExt: - Arg = DAG.getNode(ISD::ANY_EXTEND, VA.getLocVT(), Arg); + Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::BCvt: + Arg = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), Arg); break; } - // Arguments that can be passed on register must be kept at - // RegsToPass vector - if (VA.isRegLoc()) { - RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + if (Flags.isSRet()) { + assert(VA.needsCustom()); + // store SRet argument in %sp+64 + SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); + SDValue PtrOff = DAG.getIntPtrConstant(64); + PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, + MachinePointerInfo(), + false, false, 0)); + hasStructRetAttr = true; continue; } - assert(VA.isMemLoc()); - - // Create a store off the stack pointer for this argument. - SDValue StackPtr = DAG.getRegister(SP::O6, EVT::i32); - // FIXME: VERIFY THAT 68 IS RIGHT. - SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset()+68); - PtrOff = DAG.getNode(ISD::ADD, EVT::i32, StackPtr, PtrOff); - MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0)); - } - -#else - static const unsigned ArgRegs[] = { - SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 - }; - unsigned ArgOffset = 68; - - 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: llvm_unreachable("Unhandled argument type!"); - case EVT::i32: - ObjSize = 4; - - if (RegsToPass.size() >= 6) { - ValToStore = Val; - } else { - RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Val)); - } - break; - case EVT::f32: - ObjSize = 4; - if (RegsToPass.size() >= 6) { - ValToStore = Val; - } else { - // Convert this to a FP value in an int reg. - Val = DAG.getNode(ISD::BIT_CONVERT, dl, EVT::i32, Val); - RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Val)); - } - break; - case EVT::f64: { - ObjSize = 8; - if (RegsToPass.size() >= 6) { - ValToStore = Val; // Whole thing is passed in memory. - break; + if (VA.needsCustom()) { + assert(VA.getLocVT() == MVT::f64); + + if (VA.isMemLoc()) { + unsigned Offset = VA.getLocMemOffset() + StackOffset; + //if it is double-word aligned, just store. + if (Offset % 8 == 0) { + SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); + SDValue PtrOff = DAG.getIntPtrConstant(Offset); + PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, + MachinePointerInfo(), + false, false, 0)); + continue; + } } - // Break into top and bottom parts by storing to the stack and loading - // out the parts as integers. Top part goes in a reg. - SDValue StackPtr = DAG.CreateStackTemporary(EVT::f64, EVT::i32); - SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, - Val, StackPtr, NULL, 0); + SDValue StackPtr = DAG.CreateStackTemporary(MVT::f64, MVT::i32); + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, + Arg, StackPtr, MachinePointerInfo(), + false, false, 0); // Sparc is big-endian, so the high part comes first. - SDValue Hi = DAG.getLoad(EVT::i32, dl, Store, StackPtr, NULL, 0, 0); + SDValue Hi = DAG.getLoad(MVT::i32, dl, Store, StackPtr, + MachinePointerInfo(), false, false, false, 0); // Increment the pointer to the other half. StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr, DAG.getIntPtrConstant(4)); // Load the low part. - SDValue Lo = DAG.getLoad(EVT::i32, dl, Store, StackPtr, NULL, 0, 0); - - RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi)); - - if (RegsToPass.size() >= 6) { - ValToStore = Lo; - ArgOffset += 4; - ObjSize = 4; + SDValue Lo = DAG.getLoad(MVT::i32, dl, Store, StackPtr, + MachinePointerInfo(), false, false, false, 0); + + if (VA.isRegLoc()) { + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Hi)); + assert(i+1 != e); + CCValAssign &NextVA = ArgLocs[++i]; + if (NextVA.isRegLoc()) { + RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), Lo)); + } else { + //Store the low part in stack. + unsigned Offset = NextVA.getLocMemOffset() + StackOffset; + SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); + SDValue PtrOff = DAG.getIntPtrConstant(Offset); + PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); + MemOpChains.push_back(DAG.getStore(Chain, dl, Lo, PtrOff, + MachinePointerInfo(), + false, false, 0)); + } } else { - RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Lo)); + unsigned Offset = VA.getLocMemOffset() + StackOffset; + // Store the high part. + SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); + SDValue PtrOff = DAG.getIntPtrConstant(Offset); + PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); + MemOpChains.push_back(DAG.getStore(Chain, dl, Hi, PtrOff, + MachinePointerInfo(), + false, false, 0)); + // Store the low part. + PtrOff = DAG.getIntPtrConstant(Offset+4); + PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); + MemOpChains.push_back(DAG.getStore(Chain, dl, Lo, PtrOff, + MachinePointerInfo(), + false, false, 0)); } - break; + continue; } - case EVT::i64: { - ObjSize = 8; - if (RegsToPass.size() >= 6) { - ValToStore = Val; // Whole thing is passed in memory. - break; - } - // Split the value into top and bottom part. Top part goes in a reg. - SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, EVT::i32, Val, - DAG.getConstant(1, EVT::i32)); - SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, EVT::i32, Val, - DAG.getConstant(0, EVT::i32)); - RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi)); - - if (RegsToPass.size() >= 6) { - ValToStore = Lo; - ArgOffset += 4; - ObjSize = 4; - } else { - RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Lo)); + // Arguments that can be passed on register must be kept at + // RegsToPass vector + if (VA.isRegLoc()) { + if (VA.getLocVT() != MVT::f32) { + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + continue; } - break; - } + Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg); + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + continue; } - if (ValToStore.getNode()) { - SDValue StackPtr = DAG.getRegister(SP::O6, EVT::i32); - SDValue PtrOff = DAG.getConstant(ArgOffset, EVT::i32); - PtrOff = DAG.getNode(ISD::ADD, dl, EVT::i32, StackPtr, PtrOff); - MemOpChains.push_back(DAG.getStore(Chain, dl, ValToStore, - PtrOff, NULL, 0)); - } - ArgOffset += ObjSize; + assert(VA.isMemLoc()); + + // Create a store off the stack pointer for this argument. + SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32); + SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset()+StackOffset); + PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, + MachinePointerInfo(), + false, false, 0)); } -#endif + // Emit all stores, make sure the occur before any copies into physregs. if (!MemOpChains.empty()) - Chain = DAG.getNode(ISD::TokenFactor, dl, EVT::Other, + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOpChains[0], MemOpChains.size()); // Build a sequence of copy-to-reg nodes chained together with token // chain and flag operands which copy the outgoing args into registers. - // The InFlag in necessary since all emited instructions must be + // The InFlag in necessary since all emitted instructions must be // stuck together. SDValue InFlag; for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { @@ -454,19 +558,34 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, InFlag = Chain.getValue(1); } + unsigned SRetArgSize = (hasStructRetAttr)? getSRetArgSize(DAG, Callee):0; + // If the callee is a GlobalAddress node (quite common, every direct call is) // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. // Likewise ExternalSymbol -> TargetExternalSymbol. if (GlobalAddressSDNode *G = dyn_cast(Callee)) - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), EVT::i32); + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32); else if (ExternalSymbolSDNode *E = dyn_cast(Callee)) - Callee = DAG.getTargetExternalSymbol(E->getSymbol(), EVT::i32); + Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32); + + // Returns a chain & a flag for retval copy to use + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); + SmallVector Ops; + Ops.push_back(Chain); + Ops.push_back(Callee); + if (hasStructRetAttr) + Ops.push_back(DAG.getTargetConstant(SRetArgSize, MVT::i32)); + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + unsigned Reg = RegsToPass[i].first; + if (Reg >= SP::I0 && Reg <= SP::I7) + Reg = Reg-SP::I0+SP::O0; - std::vector NodeTys; - NodeTys.push_back(EVT::Other); // Returns a chain - NodeTys.push_back(EVT::Flag); // Returns a flag for retval copy to use. - SDValue Ops[] = { Chain, Callee, InFlag }; - Chain = DAG.getNode(SPISD::CALL, dl, NodeTys, Ops, InFlag.getNode() ? 3 : 2); + Ops.push_back(DAG.getRegister(Reg, RegsToPass[i].second.getValueType())); + } + if (InFlag.getNode()) + Ops.push_back(InFlag); + + Chain = DAG.getNode(SPISD::CALL, dl, NodeTys, &Ops[0], Ops.size()); InFlag = Chain.getValue(1); Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, true), @@ -475,8 +594,8 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Assign locations to each value returned by this call. SmallVector RVLocs; - CCState RVInfo(CallConv, isVarArg, DAG.getTarget(), - RVLocs, *DAG.getContext()); + CCState RVInfo(CallConv, isVarArg, DAG.getMachineFunction(), + DAG.getTarget(), RVLocs, *DAG.getContext()); RVInfo.AnalyzeCallResult(Ins, RetCC_Sparc32); @@ -497,7 +616,29 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, return Chain; } +unsigned +SparcTargetLowering::getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const +{ + const Function *CalleeFn = 0; + if (GlobalAddressSDNode *G = dyn_cast(Callee)) { + CalleeFn = dyn_cast(G->getGlobal()); + } else if (ExternalSymbolSDNode *E = + dyn_cast(Callee)) { + const Function *Fn = DAG.getMachineFunction().getFunction(); + const Module *M = Fn->getParent(); + CalleeFn = M->getFunction(E->getSymbol()); + } + + if (!CalleeFn) + return 0; + + assert(CalleeFn->hasStructRetAttr() && + "Callee does not have the StructRet attribute."); + PointerType *Ty = cast(CalleeFn->arg_begin()->getType()); + Type *ElementTy = Ty->getElementType(); + return getDataLayout()->getTypeAllocSize(ElementTy); +} //===----------------------------------------------------------------------===// // TargetLowering Implementation @@ -553,120 +694,121 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) : TargetLowering(TM, new TargetLoweringObjectFileELF()) { // Set up the register classes. - addRegisterClass(EVT::i32, SP::IntRegsRegisterClass); - addRegisterClass(EVT::f32, SP::FPRegsRegisterClass); - addRegisterClass(EVT::f64, SP::DFPRegsRegisterClass); + addRegisterClass(MVT::i32, &SP::IntRegsRegClass); + addRegisterClass(MVT::f32, &SP::FPRegsRegClass); + addRegisterClass(MVT::f64, &SP::DFPRegsRegClass); // Turn FP extload into load/fextend - setLoadExtAction(ISD::EXTLOAD, EVT::f32, Expand); + setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); // Sparc doesn't have i1 sign extending load - setLoadExtAction(ISD::SEXTLOAD, EVT::i1, Promote); + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); // Turn FP truncstore into trunc + store. - setTruncStoreAction(EVT::f64, EVT::f32, Expand); + setTruncStoreAction(MVT::f64, MVT::f32, Expand); // Custom legalize GlobalAddress nodes into LO/HI parts. - setOperationAction(ISD::GlobalAddress, EVT::i32, Custom); - setOperationAction(ISD::GlobalTLSAddress, EVT::i32, Custom); - setOperationAction(ISD::ConstantPool , EVT::i32, Custom); + setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); + setOperationAction(ISD::ConstantPool , MVT::i32, Custom); // Sparc doesn't have sext_inreg, replace them with shl/sra - setOperationAction(ISD::SIGN_EXTEND_INREG, EVT::i16, Expand); - setOperationAction(ISD::SIGN_EXTEND_INREG, EVT::i8 , Expand); - setOperationAction(ISD::SIGN_EXTEND_INREG, EVT::i1 , Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand); // Sparc has no REM or DIVREM operations. - setOperationAction(ISD::UREM, EVT::i32, Expand); - setOperationAction(ISD::SREM, EVT::i32, Expand); - setOperationAction(ISD::SDIVREM, EVT::i32, Expand); - setOperationAction(ISD::UDIVREM, EVT::i32, Expand); + setOperationAction(ISD::UREM, MVT::i32, Expand); + setOperationAction(ISD::SREM, MVT::i32, Expand); + setOperationAction(ISD::SDIVREM, MVT::i32, Expand); + setOperationAction(ISD::UDIVREM, MVT::i32, Expand); // Custom expand fp<->sint - setOperationAction(ISD::FP_TO_SINT, EVT::i32, Custom); - setOperationAction(ISD::SINT_TO_FP, EVT::i32, Custom); + setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); + setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); // Expand fp<->uint - setOperationAction(ISD::FP_TO_UINT, EVT::i32, Expand); - setOperationAction(ISD::UINT_TO_FP, EVT::i32, Expand); + setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); + setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); - setOperationAction(ISD::BIT_CONVERT, EVT::f32, Expand); - setOperationAction(ISD::BIT_CONVERT, EVT::i32, Expand); + setOperationAction(ISD::BITCAST, MVT::f32, Expand); + setOperationAction(ISD::BITCAST, MVT::i32, Expand); // Sparc has no select or setcc: expand to SELECT_CC. - setOperationAction(ISD::SELECT, EVT::i32, Expand); - setOperationAction(ISD::SELECT, EVT::f32, Expand); - setOperationAction(ISD::SELECT, EVT::f64, Expand); - setOperationAction(ISD::SETCC, EVT::i32, Expand); - setOperationAction(ISD::SETCC, EVT::f32, Expand); - setOperationAction(ISD::SETCC, EVT::f64, Expand); + setOperationAction(ISD::SELECT, MVT::i32, Expand); + setOperationAction(ISD::SELECT, MVT::f32, Expand); + setOperationAction(ISD::SELECT, MVT::f64, Expand); + setOperationAction(ISD::SETCC, MVT::i32, Expand); + setOperationAction(ISD::SETCC, MVT::f32, Expand); + setOperationAction(ISD::SETCC, MVT::f64, Expand); // Sparc doesn't have BRCOND either, it has BR_CC. - setOperationAction(ISD::BRCOND, EVT::Other, Expand); - setOperationAction(ISD::BRIND, EVT::Other, Expand); - setOperationAction(ISD::BR_JT, EVT::Other, Expand); - setOperationAction(ISD::BR_CC, EVT::i32, Custom); - setOperationAction(ISD::BR_CC, EVT::f32, Custom); - setOperationAction(ISD::BR_CC, EVT::f64, Custom); - - setOperationAction(ISD::SELECT_CC, EVT::i32, Custom); - setOperationAction(ISD::SELECT_CC, EVT::f32, Custom); - setOperationAction(ISD::SELECT_CC, EVT::f64, Custom); - - // SPARC has no intrinsics for these particular operations. - setOperationAction(ISD::MEMBARRIER, EVT::Other, Expand); - - setOperationAction(ISD::FSIN , EVT::f64, Expand); - setOperationAction(ISD::FCOS , EVT::f64, Expand); - setOperationAction(ISD::FREM , EVT::f64, Expand); - setOperationAction(ISD::FSIN , EVT::f32, Expand); - setOperationAction(ISD::FCOS , EVT::f32, Expand); - setOperationAction(ISD::FREM , EVT::f32, Expand); - setOperationAction(ISD::CTPOP, EVT::i32, Expand); - setOperationAction(ISD::CTTZ , EVT::i32, Expand); - setOperationAction(ISD::CTLZ , EVT::i32, Expand); - setOperationAction(ISD::ROTL , EVT::i32, Expand); - setOperationAction(ISD::ROTR , EVT::i32, Expand); - setOperationAction(ISD::BSWAP, EVT::i32, Expand); - setOperationAction(ISD::FCOPYSIGN, EVT::f64, Expand); - setOperationAction(ISD::FCOPYSIGN, EVT::f32, Expand); - setOperationAction(ISD::FPOW , EVT::f64, Expand); - setOperationAction(ISD::FPOW , EVT::f32, Expand); - - setOperationAction(ISD::SHL_PARTS, EVT::i32, Expand); - setOperationAction(ISD::SRA_PARTS, EVT::i32, Expand); - setOperationAction(ISD::SRL_PARTS, EVT::i32, Expand); + setOperationAction(ISD::BRCOND, MVT::Other, Expand); + setOperationAction(ISD::BRIND, MVT::Other, Expand); + setOperationAction(ISD::BR_JT, MVT::Other, Expand); + setOperationAction(ISD::BR_CC, MVT::i32, Custom); + setOperationAction(ISD::BR_CC, MVT::f32, Custom); + setOperationAction(ISD::BR_CC, MVT::f64, Custom); + + setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); + + // FIXME: There are instructions available for ATOMIC_FENCE + // on SparcV8 and later. + setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); + setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand); + + setOperationAction(ISD::FSIN , MVT::f64, Expand); + setOperationAction(ISD::FCOS , MVT::f64, Expand); + setOperationAction(ISD::FREM , MVT::f64, Expand); + setOperationAction(ISD::FMA , MVT::f64, Expand); + setOperationAction(ISD::FSIN , MVT::f32, Expand); + setOperationAction(ISD::FCOS , MVT::f32, Expand); + setOperationAction(ISD::FREM , MVT::f32, Expand); + setOperationAction(ISD::FMA , MVT::f32, Expand); + setOperationAction(ISD::CTPOP, MVT::i32, Expand); + setOperationAction(ISD::CTTZ , MVT::i32, Expand); + setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); + setOperationAction(ISD::CTLZ , MVT::i32, Expand); + setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); + setOperationAction(ISD::ROTL , MVT::i32, Expand); + setOperationAction(ISD::ROTR , MVT::i32, Expand); + setOperationAction(ISD::BSWAP, MVT::i32, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); + setOperationAction(ISD::FPOW , MVT::f64, Expand); + setOperationAction(ISD::FPOW , MVT::f32, Expand); + + setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); // FIXME: Sparc provides these multiplies, but we don't have them yet. - setOperationAction(ISD::UMUL_LOHI, EVT::i32, Expand); - setOperationAction(ISD::SMUL_LOHI, EVT::i32, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); + setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); - // We don't have line number support yet. - setOperationAction(ISD::DBG_STOPPOINT, EVT::Other, Expand); - setOperationAction(ISD::DEBUG_LOC, EVT::Other, Expand); - setOperationAction(ISD::DBG_LABEL, EVT::Other, Expand); - setOperationAction(ISD::EH_LABEL, EVT::Other, Expand); + setOperationAction(ISD::EH_LABEL, MVT::Other, Expand); // VASTART needs to be custom lowered to use the VarArgsFrameIndex. - setOperationAction(ISD::VASTART , EVT::Other, Custom); + setOperationAction(ISD::VASTART , MVT::Other, Custom); // VAARG needs to be lowered to not do unaligned accesses for doubles. - setOperationAction(ISD::VAARG , EVT::Other, Custom); + setOperationAction(ISD::VAARG , MVT::Other, Custom); // Use the default implementation. - setOperationAction(ISD::VACOPY , EVT::Other, Expand); - setOperationAction(ISD::VAEND , EVT::Other, Expand); - setOperationAction(ISD::STACKSAVE , EVT::Other, Expand); - setOperationAction(ISD::STACKRESTORE , EVT::Other, Expand); - setOperationAction(ISD::DYNAMIC_STACKALLOC, EVT::i32 , Custom); + setOperationAction(ISD::VACOPY , MVT::Other, Expand); + setOperationAction(ISD::VAEND , MVT::Other, Expand); + setOperationAction(ISD::STACKSAVE , MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand); + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom); // No debug info support yet. - setOperationAction(ISD::DBG_STOPPOINT, EVT::Other, Expand); - setOperationAction(ISD::DBG_LABEL, EVT::Other, Expand); - setOperationAction(ISD::EH_LABEL, EVT::Other, Expand); - setOperationAction(ISD::DECLARE, EVT::Other, Expand); + setOperationAction(ISD::EH_LABEL, MVT::Other, Expand); setStackPointerRegisterToSaveRestore(SP::O6); if (TM.getSubtarget().isV9()) - setOperationAction(ISD::CTPOP, EVT::i32, Legal); + setOperationAction(ISD::CTPOP, MVT::i32, Legal); + + setMinFunctionAlignment(2); computeRegisterProperties(); } @@ -686,6 +828,8 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const { case SPISD::ITOF: return "SPISD::ITOF"; case SPISD::CALL: return "SPISD::CALL"; case SPISD::RET_FLAG: return "SPISD::RET_FLAG"; + case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG"; + case SPISD::FLUSHW: return "SPISD::FLUSHW"; } } @@ -693,22 +837,19 @@ const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const { /// be zero. Op is expected to be a target specific node. Used by DAG /// combiner. void SparcTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, - const APInt &Mask, APInt &KnownZero, APInt &KnownOne, const SelectionDAG &DAG, unsigned Depth) const { APInt KnownZero2, KnownOne2; - KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); // Don't know anything. + KnownZero = KnownOne = APInt(KnownZero.getBitWidth(), 0); switch (Op.getOpcode()) { default: break; case SPISD::SELECT_ICC: case SPISD::SELECT_FCC: - DAG.ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, - Depth+1); - DAG.ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero2, KnownOne2, - Depth+1); + DAG.ComputeMaskedBits(Op.getOperand(1), KnownZero, KnownOne, Depth+1); + DAG.ComputeMaskedBits(Op.getOperand(0), KnownZero2, KnownOne2, Depth+1); assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); @@ -724,7 +865,7 @@ void SparcTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, static void LookThroughSetCC(SDValue &LHS, SDValue &RHS, ISD::CondCode CC, unsigned &SPCC) { if (isa(RHS) && - cast(RHS)->getZExtValue() == 0 && + cast(RHS)->isNullValue() && CC == ISD::SETNE && ((LHS.getOpcode() == SPISD::SELECT_ICC && LHS.getOperand(3).getOpcode() == SPISD::CMPICC) || @@ -732,8 +873,8 @@ static void LookThroughSetCC(SDValue &LHS, SDValue &RHS, LHS.getOperand(3).getOpcode() == SPISD::CMPFCC)) && isa(LHS.getOperand(0)) && isa(LHS.getOperand(1)) && - cast(LHS.getOperand(0))->getZExtValue() == 1 && - cast(LHS.getOperand(1))->getZExtValue() == 0) { + cast(LHS.getOperand(0))->isOne() && + cast(LHS.getOperand(1))->isNullValue()) { SDValue CMPCC = LHS.getOperand(3); SPCC = cast(LHS.getOperand(2))->getZExtValue(); LHS = CMPCC.getOperand(0); @@ -741,39 +882,60 @@ static void LookThroughSetCC(SDValue &LHS, SDValue &RHS, } } -static SDValue LowerGLOBALADDRESS(SDValue Op, SelectionDAG &DAG) { - GlobalValue *GV = cast(Op)->getGlobal(); +SDValue SparcTargetLowering::LowerGlobalAddress(SDValue Op, + SelectionDAG &DAG) const { + const GlobalValue *GV = cast(Op)->getGlobal(); // FIXME there isn't really any debug info here DebugLoc dl = Op.getDebugLoc(); - SDValue GA = DAG.getTargetGlobalAddress(GV, EVT::i32); - SDValue Hi = DAG.getNode(SPISD::Hi, dl, EVT::i32, GA); - SDValue Lo = DAG.getNode(SPISD::Lo, dl, EVT::i32, GA); - return DAG.getNode(ISD::ADD, dl, EVT::i32, Lo, Hi); + SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32); + SDValue Hi = DAG.getNode(SPISD::Hi, dl, MVT::i32, GA); + SDValue Lo = DAG.getNode(SPISD::Lo, dl, MVT::i32, GA); + + 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, MachinePointerInfo(), false, false, false, 0); } -static SDValue LowerCONSTANTPOOL(SDValue Op, SelectionDAG &DAG) { +SDValue SparcTargetLowering::LowerConstantPool(SDValue Op, + SelectionDAG &DAG) const { ConstantPoolSDNode *N = cast(Op); // FIXME there isn't really any debug info here DebugLoc dl = Op.getDebugLoc(); - Constant *C = N->getConstVal(); - SDValue CP = DAG.getTargetConstantPool(C, EVT::i32, N->getAlignment()); - SDValue Hi = DAG.getNode(SPISD::Hi, dl, EVT::i32, CP); - SDValue Lo = DAG.getNode(SPISD::Lo, dl, EVT::i32, CP); - return DAG.getNode(ISD::ADD, dl, EVT::i32, Lo, Hi); + const Constant *C = N->getConstVal(); + 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); + 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, MachinePointerInfo(), false, false, false, 0); } static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) { DebugLoc dl = Op.getDebugLoc(); // Convert the fp value to integer in an FP register. - assert(Op.getValueType() == EVT::i32); - Op = DAG.getNode(SPISD::FTOI, dl, EVT::f32, Op.getOperand(0)); - return DAG.getNode(ISD::BIT_CONVERT, dl, EVT::i32, Op); + assert(Op.getValueType() == MVT::i32); + Op = DAG.getNode(SPISD::FTOI, dl, MVT::f32, Op.getOperand(0)); + return DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op); } static SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) { DebugLoc dl = Op.getDebugLoc(); - assert(Op.getOperand(0).getValueType() == EVT::i32); - SDValue Tmp = DAG.getNode(ISD::BIT_CONVERT, dl, EVT::f32, Op.getOperand(0)); + assert(Op.getOperand(0).getValueType() == MVT::i32); + SDValue Tmp = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Op.getOperand(0)); // Convert the int value to FP in an FP register. return DAG.getNode(SPISD::ITOF, dl, Op.getValueType(), Tmp); } @@ -793,21 +955,21 @@ static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) { // Get the condition flag. SDValue CompareFlag; - if (LHS.getValueType() == EVT::i32) { + if (LHS.getValueType() == MVT::i32) { std::vector VTs; - VTs.push_back(EVT::i32); - VTs.push_back(EVT::Flag); + VTs.push_back(MVT::i32); + VTs.push_back(MVT::Glue); SDValue Ops[2] = { LHS, RHS }; CompareFlag = DAG.getNode(SPISD::CMPICC, dl, VTs, Ops, 2).getValue(1); if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); Opc = SPISD::BRICC; } else { - CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, EVT::Flag, LHS, RHS); + CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS); if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); Opc = SPISD::BRFCC; } - return DAG.getNode(Opc, dl, EVT::Other, Chain, Dest, - DAG.getConstant(SPCC, EVT::i32), CompareFlag); + return DAG.getNode(Opc, dl, MVT::Other, Chain, Dest, + DAG.getConstant(SPCC, MVT::i32), CompareFlag); } static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) { @@ -824,34 +986,39 @@ static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) { LookThroughSetCC(LHS, RHS, CC, SPCC); SDValue CompareFlag; - if (LHS.getValueType() == EVT::i32) { + if (LHS.getValueType() == MVT::i32) { std::vector VTs; VTs.push_back(LHS.getValueType()); // subcc returns a value - VTs.push_back(EVT::Flag); + VTs.push_back(MVT::Glue); SDValue Ops[2] = { LHS, RHS }; CompareFlag = DAG.getNode(SPISD::CMPICC, dl, VTs, Ops, 2).getValue(1); Opc = SPISD::SELECT_ICC; if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC); } else { - CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, EVT::Flag, LHS, RHS); + CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Glue, LHS, RHS); Opc = SPISD::SELECT_FCC; if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC); } return DAG.getNode(Opc, dl, TrueVal.getValueType(), TrueVal, FalseVal, - DAG.getConstant(SPCC, EVT::i32), CompareFlag); + DAG.getConstant(SPCC, MVT::i32), CompareFlag); } static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG, - SparcTargetLowering &TLI) { + const SparcTargetLowering &TLI) { + MachineFunction &MF = DAG.getMachineFunction(); + SparcMachineFunctionInfo *FuncInfo = MF.getInfo(); + // vastart just stores the address of the VarArgsFrameIndex slot into the // memory location argument. DebugLoc dl = Op.getDebugLoc(); - SDValue Offset = DAG.getNode(ISD::ADD, dl, EVT::i32, - DAG.getRegister(SP::I6, EVT::i32), - DAG.getConstant(TLI.getVarArgsFrameOffset(), - EVT::i32)); + SDValue Offset = + DAG.getNode(ISD::ADD, dl, MVT::i32, + DAG.getRegister(SP::I6, MVT::i32), + DAG.getConstant(FuncInfo->getVarArgsFrameOffset(), + MVT::i32)); const Value *SV = cast(Op.getOperand(2))->getValue(); - return DAG.getStore(Op.getOperand(0), dl, Offset, Op.getOperand(1), SV, 0); + return DAG.getStore(Op.getOperand(0), dl, Offset, Op.getOperand(1), + MachinePointerInfo(SV), false, false, 0); } static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) { @@ -861,25 +1028,28 @@ static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) { SDValue VAListPtr = Node->getOperand(1); const Value *SV = cast(Node->getOperand(2))->getValue(); DebugLoc dl = Node->getDebugLoc(); - SDValue VAList = DAG.getLoad(EVT::i32, dl, InChain, VAListPtr, SV, 0); + SDValue VAList = DAG.getLoad(MVT::i32, dl, InChain, VAListPtr, + MachinePointerInfo(SV), false, false, false, 0); // Increment the pointer, VAList, to the next vaarg - SDValue NextPtr = DAG.getNode(ISD::ADD, dl, EVT::i32, VAList, + SDValue NextPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, VAList, DAG.getConstant(VT.getSizeInBits()/8, - EVT::i32)); + MVT::i32)); // Store the incremented VAList to the legalized pointer InChain = DAG.getStore(VAList.getValue(1), dl, NextPtr, - VAListPtr, SV, 0); + VAListPtr, MachinePointerInfo(SV), false, false, 0); // Load the actual argument out of the pointer VAList, unless this is an // f64 load. - if (VT != EVT::f64) - return DAG.getLoad(VT, dl, InChain, VAList, NULL, 0); + if (VT != MVT::f64) + return DAG.getLoad(VT, dl, InChain, VAList, MachinePointerInfo(), + false, false, false, 0); // Otherwise, load it as i64, then do a bitconvert. - SDValue V = DAG.getLoad(EVT::i64, dl, InChain, VAList, NULL, 0); + SDValue V = DAG.getLoad(MVT::i64, dl, InChain, VAList, MachinePointerInfo(), + false, false, false, 0); // Bit-Convert the value to f64. SDValue Ops[2] = { - DAG.getNode(ISD::BIT_CONVERT, dl, EVT::f64, V), + DAG.getNode(ISD::BITCAST, dl, MVT::f64, V), V.getValue(1) }; return DAG.getMergeValues(Ops, 2, dl); @@ -891,30 +1061,99 @@ static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) { DebugLoc dl = Op.getDebugLoc(); unsigned SPReg = SP::O6; - SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, EVT::i32); - SDValue NewSP = DAG.getNode(ISD::SUB, dl, EVT::i32, SP, Size); // Value + SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, MVT::i32); + SDValue NewSP = DAG.getNode(ISD::SUB, dl, MVT::i32, SP, Size); // Value Chain = DAG.getCopyToReg(SP.getValue(1), dl, SPReg, NewSP); // Output chain // The resultant pointer is actually 16 words from the bottom of the stack, // to provide a register spill area. - SDValue NewVal = DAG.getNode(ISD::ADD, dl, EVT::i32, NewSP, - DAG.getConstant(96, EVT::i32)); + SDValue NewVal = DAG.getNode(ISD::ADD, dl, MVT::i32, NewSP, + DAG.getConstant(96, MVT::i32)); SDValue Ops[2] = { NewVal, Chain }; return DAG.getMergeValues(Ops, 2, dl); } +static SDValue getFLUSHW(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + SDValue Chain = DAG.getNode(SPISD::FLUSHW, + dl, MVT::Other, DAG.getEntryNode()); + return Chain; +} + +static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + MFI->setFrameAddressIsTaken(true); + + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + unsigned FrameReg = SP::I6; + + uint64_t depth = Op.getConstantOperandVal(0); + + SDValue FrameAddr; + if (depth == 0) + FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); + else { + // flush first to make sure the windowed registers' values are in stack + SDValue Chain = getFLUSHW(Op, DAG); + FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT); + + for (uint64_t i = 0; i != depth; ++i) { + SDValue Ptr = DAG.getNode(ISD::ADD, + dl, MVT::i32, + FrameAddr, DAG.getIntPtrConstant(56)); + FrameAddr = DAG.getLoad(MVT::i32, dl, + Chain, + Ptr, + MachinePointerInfo(), false, false, false, 0); + } + } + return FrameAddr; +} + +static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) { + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + MFI->setReturnAddressIsTaken(true); + + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + unsigned RetReg = SP::I7; + + uint64_t depth = Op.getConstantOperandVal(0); + + SDValue RetAddr; + if (depth == 0) + RetAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, RetReg, VT); + else { + // flush first to make sure the windowed registers' values are in stack + SDValue Chain = getFLUSHW(Op, DAG); + RetAddr = DAG.getCopyFromReg(Chain, dl, SP::I6, VT); + + for (uint64_t i = 0; i != depth; ++i) { + SDValue Ptr = DAG.getNode(ISD::ADD, + dl, MVT::i32, + RetAddr, + DAG.getIntPtrConstant((i == depth-1)?60:56)); + RetAddr = DAG.getLoad(MVT::i32, dl, + Chain, + Ptr, + MachinePointerInfo(), false, false, false, 0); + } + } + return RetAddr; +} + SDValue SparcTargetLowering:: -LowerOperation(SDValue Op, SelectionDAG &DAG) { +LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { 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::RETURNADDR: return LowerRETURNADDR(Op, DAG); + case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); case ISD::GlobalTLSAddress: llvm_unreachable("TLS not implemented for Sparc."); - case ISD::GlobalAddress: return LowerGLOBALADDRESS(Op, DAG); - case ISD::ConstantPool: return LowerCONSTANTPOOL(Op, DAG); + 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); @@ -966,16 +1205,21 @@ SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, MachineFunction *F = BB->getParent(); MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); - 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 - // block to the new block which will contain the Phi node for the select. - sinkMBB->transferSuccessors(BB); - // Next, add the true and fallthrough blocks as its successors. + + // Transfer the remainder of BB and its successor edges to sinkMBB. + sinkMBB->splice(sinkMBB->begin(), BB, + llvm::next(MachineBasicBlock::iterator(MI)), + BB->end()); + sinkMBB->transferSuccessorsAndUpdatePHIs(BB); + + // Add the true and fallthrough blocks as its successors. BB->addSuccessor(copy0MBB); BB->addSuccessor(sinkMBB); + BuildMI(BB, dl, TII.get(BROpcode)).addMBB(sinkMBB).addImm(CC); + // copy0MBB: // %FalseValue = ... // # fallthrough to sinkMBB @@ -988,11 +1232,11 @@ SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] // ... BB = sinkMBB; - BuildMI(BB, dl, TII.get(SP::PHI), MI->getOperand(0).getReg()) + BuildMI(*BB, BB->begin(), dl, TII.get(SP::PHI), MI->getOperand(0).getReg()) .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB) .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB); - F->DeleteMachineInstr(MI); // The pseudo instruction is gone now. + MI->eraseFromParent(); // The pseudo instruction is gone now. return BB; } @@ -1020,40 +1264,15 @@ SparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, if (Constraint.size() == 1) { switch (Constraint[0]) { case 'r': - return std::make_pair(0U, SP::IntRegsRegisterClass); + return std::make_pair(0U, &SP::IntRegsRegClass); } } return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); } -std::vector SparcTargetLowering:: -getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const { - if (Constraint.size() != 1) - return std::vector(); - - switch (Constraint[0]) { - default: break; - case 'r': - return make_vector(SP::L0, SP::L1, SP::L2, SP::L3, - SP::L4, SP::L5, SP::L6, SP::L7, - SP::I0, SP::I1, SP::I2, SP::I3, - SP::I4, SP::I5, - SP::O0, SP::O1, SP::O2, SP::O3, - SP::O4, SP::O5, SP::O7, 0); - } - - return std::vector(); -} - bool SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { // The Sparc target isn't yet aware of offsets. return false; } - -/// getFunctionAlignment - Return the Log2 alignment of this function. -unsigned SparcTargetLowering::getFunctionAlignment(const Function *) const { - return 4; -}