void AlphaTargetLowering::LowerVAARG(SDNode *N, SDValue &Chain, SDValue &DataPtr, SelectionDAG &DAG) { Chain = N->getOperand(0); SDValue VAListP = N->getOperand(1); const Value *VAListS = cast<SrcValueSDNode>(N->getOperand(2))->getValue(); DebugLoc dl = N->getDebugLoc(); SDValue Base = DAG.getLoad(MVT::i64, dl, Chain, VAListP, VAListS, 0); SDValue Tmp = DAG.getNode(ISD::ADD, dl, MVT::i64, VAListP, DAG.getConstant(8, MVT::i64)); SDValue Offset = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Base.getValue(1), Tmp, NULL, 0, MVT::i32); DataPtr = DAG.getNode(ISD::ADD, dl, MVT::i64, Base, Offset); if (N->getValueType(0).isFloatingPoint()) { //if fp && Offset < 6*8, then subtract 6*8 from DataPtr SDValue FPDataPtr = DAG.getNode(ISD::SUB, dl, MVT::i64, DataPtr, DAG.getConstant(8*6, MVT::i64)); SDValue CC = DAG.getSetCC(dl, MVT::i64, Offset, DAG.getConstant(8*6, MVT::i64), ISD::SETLT); DataPtr = DAG.getNode(ISD::SELECT, dl, MVT::i64, CC, FPDataPtr, DataPtr); } SDValue NewOffset = DAG.getNode(ISD::ADD, dl, MVT::i64, Offset, DAG.getConstant(8, MVT::i64)); Chain = DAG.getTruncStore(Offset.getValue(1), dl, NewOffset, Tmp, NULL, 0, MVT::i32); }
/// LowerOperation - Provide custom lowering hooks for some operations. /// SDValue AlphaTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { DebugLoc dl = Op.getDebugLoc(); switch (Op.getOpcode()) { default: llvm_unreachable("Wasn't expecting to be able to lower this!"); case ISD::JumpTable: return LowerJumpTable(Op, DAG); case ISD::INTRINSIC_WO_CHAIN: { unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); switch (IntNo) { default: break; // Don't custom lower most intrinsics. case Intrinsic::alpha_umulh: return DAG.getNode(ISD::MULHU, dl, MVT::i64, Op.getOperand(1), Op.getOperand(2)); } } case ISD::SRL_PARTS: { SDValue ShOpLo = Op.getOperand(0); SDValue ShOpHi = Op.getOperand(1); SDValue ShAmt = Op.getOperand(2); SDValue bm = DAG.getNode(ISD::SUB, dl, MVT::i64, DAG.getConstant(64, MVT::i64), ShAmt); SDValue BMCC = DAG.getSetCC(dl, MVT::i64, bm, DAG.getConstant(0, MVT::i64), ISD::SETLE); // if 64 - shAmt <= 0 SDValue Hi_Neg = DAG.getConstant(0, MVT::i64); SDValue ShAmt_Neg = DAG.getNode(ISD::SUB, dl, MVT::i64, DAG.getConstant(0, MVT::i64), bm); SDValue Lo_Neg = DAG.getNode(ISD::SRL, dl, MVT::i64, ShOpHi, ShAmt_Neg); // else SDValue carries = DAG.getNode(ISD::SHL, dl, MVT::i64, ShOpHi, bm); SDValue Hi_Pos = DAG.getNode(ISD::SRL, dl, MVT::i64, ShOpHi, ShAmt); SDValue Lo_Pos = DAG.getNode(ISD::SRL, dl, MVT::i64, ShOpLo, ShAmt); Lo_Pos = DAG.getNode(ISD::OR, dl, MVT::i64, Lo_Pos, carries); // Merge SDValue Hi = DAG.getNode(ISD::SELECT, dl, MVT::i64, BMCC, Hi_Neg, Hi_Pos); SDValue Lo = DAG.getNode(ISD::SELECT, dl, MVT::i64, BMCC, Lo_Neg, Lo_Pos); SDValue Ops[2] = { Lo, Hi }; return DAG.getMergeValues(Ops, 2, dl); } // case ISD::SRA_PARTS: // case ISD::SHL_PARTS: case ISD::SINT_TO_FP: { assert(Op.getOperand(0).getValueType() == MVT::i64 && "Unhandled SINT_TO_FP type in custom expander!"); SDValue LD; bool isDouble = Op.getValueType() == MVT::f64; LD = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, Op.getOperand(0)); SDValue FP = DAG.getNode(isDouble?AlphaISD::CVTQT_:AlphaISD::CVTQS_, dl, isDouble?MVT::f64:MVT::f32, LD); return FP; } case ISD::FP_TO_SINT: { bool isDouble = Op.getOperand(0).getValueType() == MVT::f64; SDValue src = Op.getOperand(0); if (!isDouble) //Promote src = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, src); src = DAG.getNode(AlphaISD::CVTTQ_, dl, MVT::f64, src); return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i64, src); } case ISD::ConstantPool: { ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); Constant *C = CP->getConstVal(); SDValue CPI = DAG.getTargetConstantPool(C, MVT::i64, CP->getAlignment()); // FIXME there isn't really any debug info here SDValue Hi = DAG.getNode(AlphaISD::GPRelHi, dl, MVT::i64, CPI, DAG.getGLOBAL_OFFSET_TABLE(MVT::i64)); SDValue Lo = DAG.getNode(AlphaISD::GPRelLo, dl, MVT::i64, CPI, Hi); return Lo; } case ISD::GlobalTLSAddress: llvm_unreachable("TLS not implemented for Alpha."); case ISD::GlobalAddress: { GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op); GlobalValue *GV = GSDN->getGlobal(); SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i64, GSDN->getOffset()); // FIXME there isn't really any debug info here // if (!GV->hasWeakLinkage() && !GV->isDeclaration() && !GV->hasLinkOnceLinkage()) { if (GV->hasLocalLinkage()) { SDValue Hi = DAG.getNode(AlphaISD::GPRelHi, dl, MVT::i64, GA, DAG.getGLOBAL_OFFSET_TABLE(MVT::i64)); SDValue Lo = DAG.getNode(AlphaISD::GPRelLo, dl, MVT::i64, GA, Hi); return Lo; } else return DAG.getNode(AlphaISD::RelLit, dl, MVT::i64, GA, DAG.getGLOBAL_OFFSET_TABLE(MVT::i64)); } case ISD::ExternalSymbol: { return DAG.getNode(AlphaISD::RelLit, dl, MVT::i64, DAG.getTargetExternalSymbol(cast<ExternalSymbolSDNode>(Op) ->getSymbol(), MVT::i64), DAG.getGLOBAL_OFFSET_TABLE(MVT::i64)); } case ISD::UREM: case ISD::SREM: //Expand only on constant case if (Op.getOperand(1).getOpcode() == ISD::Constant) { EVT VT = Op.getNode()->getValueType(0); SDValue Tmp1 = Op.getNode()->getOpcode() == ISD::UREM ? BuildUDIV(Op.getNode(), DAG, NULL) : BuildSDIV(Op.getNode(), DAG, NULL); Tmp1 = DAG.getNode(ISD::MUL, dl, VT, Tmp1, Op.getOperand(1)); Tmp1 = DAG.getNode(ISD::SUB, dl, VT, Op.getOperand(0), Tmp1); return Tmp1; } //fall through case ISD::SDIV: case ISD::UDIV: if (Op.getValueType().isInteger()) { if (Op.getOperand(1).getOpcode() == ISD::Constant) return Op.getOpcode() == ISD::SDIV ? BuildSDIV(Op.getNode(), DAG, NULL) : BuildUDIV(Op.getNode(), DAG, NULL); const char* opstr = 0; switch (Op.getOpcode()) { case ISD::UREM: opstr = "__remqu"; break; case ISD::SREM: opstr = "__remq"; break; case ISD::UDIV: opstr = "__divqu"; break; case ISD::SDIV: opstr = "__divq"; break; } SDValue Tmp1 = Op.getOperand(0), Tmp2 = Op.getOperand(1), Addr = DAG.getExternalSymbol(opstr, MVT::i64); return DAG.getNode(AlphaISD::DivCall, dl, MVT::i64, Addr, Tmp1, Tmp2); } break; case ISD::VAARG: { SDValue Chain, DataPtr; LowerVAARG(Op.getNode(), Chain, DataPtr, DAG); SDValue Result; if (Op.getValueType() == MVT::i32) Result = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Chain, DataPtr, NULL, 0, MVT::i32); else Result = DAG.getLoad(Op.getValueType(), dl, Chain, DataPtr, NULL, 0); return Result; } case ISD::VACOPY: { SDValue Chain = Op.getOperand(0); SDValue DestP = Op.getOperand(1); SDValue SrcP = Op.getOperand(2); const Value *DestS = cast<SrcValueSDNode>(Op.getOperand(3))->getValue(); const Value *SrcS = cast<SrcValueSDNode>(Op.getOperand(4))->getValue(); SDValue Val = DAG.getLoad(getPointerTy(), dl, Chain, SrcP, SrcS, 0); SDValue Result = DAG.getStore(Val.getValue(1), dl, Val, DestP, DestS, 0); SDValue NP = DAG.getNode(ISD::ADD, dl, MVT::i64, SrcP, DAG.getConstant(8, MVT::i64)); Val = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Result, NP, NULL,0, MVT::i32); SDValue NPD = DAG.getNode(ISD::ADD, dl, MVT::i64, DestP, DAG.getConstant(8, MVT::i64)); return DAG.getTruncStore(Val.getValue(1), dl, Val, NPD, NULL, 0, MVT::i32); } case ISD::VASTART: { SDValue Chain = Op.getOperand(0); SDValue VAListP = Op.getOperand(1); const Value *VAListS = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); // vastart stores the address of the VarArgsBase and VarArgsOffset SDValue FR = DAG.getFrameIndex(VarArgsBase, MVT::i64); SDValue S1 = DAG.getStore(Chain, dl, FR, VAListP, VAListS, 0); SDValue SA2 = DAG.getNode(ISD::ADD, dl, MVT::i64, VAListP, DAG.getConstant(8, MVT::i64)); return DAG.getTruncStore(S1, dl, DAG.getConstant(VarArgsOffset, MVT::i64), SA2, NULL, 0, MVT::i32); } case ISD::RETURNADDR: return DAG.getNode(AlphaISD::GlobalRetAddr, DebugLoc::getUnknownLoc(), MVT::i64); //FIXME: implement case ISD::FRAMEADDR: break; } return SDValue(); }
SDValue AVM2TargetLowering:: LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc DL, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); AVM2MachineFunctionInfo *FuncInfo = MF.getInfo<AVM2MachineFunctionInfo>(); // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeFormalArguments(Ins, CC_AVM2_32); SDValue Root = DAG.getRoot(); unsigned ArgOffset = 0; 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: assert(0 && "Unhandled argument type!"); case MVT::i1: case MVT::i8: case MVT::i16: case MVT::i32: if (!Ins[i].Used) { // Argument is dead. InVals.push_back(DAG.getNode(ISD::UNDEF, DL, ObjectVT)); } else { int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset, true); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); SDValue Load; if (ObjectVT == MVT::i32) { Load = DAG.getLoad(MVT::i32, DL, Root, FIPtr, MachinePointerInfo(), false, false, 0); } else { ISD::LoadExtType LoadOp = ISD::SEXTLOAD; unsigned Offset = 0; // LE FIPtr = DAG.getNode(ISD::ADD, DL, MVT::i32, FIPtr, DAG.getConstant(Offset, MVT::i32)); Load = DAG.getExtLoad(LoadOp, DL, MVT::i32, Root, FIPtr, MachinePointerInfo(), ObjectVT, false, false, 0); Load = DAG.getNode(ISD::TRUNCATE, DL, ObjectVT, Load); } InVals.push_back(Load); } ArgOffset += 4; break; case MVT::f32: if (!Ins[i].Used) { // Argument is dead. InVals.push_back(DAG.getNode(ISD::UNDEF, DL, ObjectVT)); } else { int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset, true); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); InVals.push_back(DAG.getLoad(ObjectVT, DL, Root, FIPtr, MachinePointerInfo(), false, false, 0)); } ArgOffset += 4; break; case MVT::i64: if (!Ins[i].Used) { // Argument is dead. InVals.push_back(DAG.getNode(ISD::UNDEF, DL, ObjectVT)); } else { int FrameIdx = MF.getFrameInfo()->CreateFixedObject(8, ArgOffset, true); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); SDValue FIPtr4 = DAG.getNode(ISD::ADD, DL, MVT::i32, FIPtr, DAG.getConstant(4, MVT::i32)); SDValue Lo = DAG.getLoad(MVT::i32, DL, Root, FIPtr, MachinePointerInfo(), false, false, 0); SDValue Hi = DAG.getLoad(MVT::i32, DL, Root, FIPtr4, MachinePointerInfo(), false, false, 0); InVals.push_back(DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi)); } ArgOffset += 8; break; case MVT::f64: if (!Ins[i].Used) { // Argument is dead. InVals.push_back(DAG.getNode(ISD::UNDEF, DL, ObjectVT)); } else { int FrameIdx = MF.getFrameInfo()->CreateFixedObject(8, ArgOffset, true); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); InVals.push_back(DAG.getLoad(ObjectVT, DL, Root, FIPtr, MachinePointerInfo(), false, false, 0)); } ArgOffset += 8; break; } } if (isVarArg) { // Remember the vararg offset for the va_start implementation. FuncInfo->setVarArgsFrameOffset(ArgOffset); } return Chain; }
/// LowerOperation - Provide custom lowering hooks for some operations. /// SDOperand AlphaTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { default: assert(0 && "Wasn't expecting to be able to lower this!"); case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsBase, VarArgsOffset); case ISD::RET: return LowerRET(Op,DAG); case ISD::JumpTable: return LowerJumpTable(Op, DAG); case ISD::SINT_TO_FP: { assert(MVT::i64 == Op.getOperand(0).getValueType() && "Unhandled SINT_TO_FP type in custom expander!"); SDOperand LD; bool isDouble = MVT::f64 == Op.getValueType(); LD = DAG.getNode(ISD::BIT_CONVERT, MVT::f64, Op.getOperand(0)); SDOperand FP = DAG.getNode(isDouble?AlphaISD::CVTQT_:AlphaISD::CVTQS_, isDouble?MVT::f64:MVT::f32, LD); return FP; } case ISD::FP_TO_SINT: { bool isDouble = MVT::f64 == Op.getOperand(0).getValueType(); SDOperand src = Op.getOperand(0); if (!isDouble) //Promote src = DAG.getNode(ISD::FP_EXTEND, MVT::f64, src); src = DAG.getNode(AlphaISD::CVTTQ_, MVT::f64, src); return DAG.getNode(ISD::BIT_CONVERT, MVT::i64, src); } case ISD::ConstantPool: { ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); Constant *C = CP->getConstVal(); SDOperand CPI = DAG.getTargetConstantPool(C, MVT::i64, CP->getAlignment()); SDOperand Hi = DAG.getNode(AlphaISD::GPRelHi, MVT::i64, CPI, DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); SDOperand Lo = DAG.getNode(AlphaISD::GPRelLo, MVT::i64, CPI, Hi); return Lo; } case ISD::GlobalAddress: { GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op); GlobalValue *GV = GSDN->getGlobal(); SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i64, GSDN->getOffset()); // if (!GV->hasWeakLinkage() && !GV->isDeclaration() && !GV->hasLinkOnceLinkage()) { if (GV->hasInternalLinkage()) { SDOperand Hi = DAG.getNode(AlphaISD::GPRelHi, MVT::i64, GA, DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); SDOperand Lo = DAG.getNode(AlphaISD::GPRelLo, MVT::i64, GA, Hi); return Lo; } else return DAG.getNode(AlphaISD::RelLit, MVT::i64, GA, DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); } case ISD::ExternalSymbol: { return DAG.getNode(AlphaISD::RelLit, MVT::i64, DAG.getTargetExternalSymbol(cast<ExternalSymbolSDNode>(Op) ->getSymbol(), MVT::i64), DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i64)); } case ISD::UREM: case ISD::SREM: //Expand only on constant case if (Op.getOperand(1).getOpcode() == ISD::Constant) { MVT::ValueType VT = Op.Val->getValueType(0); SDOperand Tmp1 = Op.Val->getOpcode() == ISD::UREM ? BuildUDIV(Op.Val, DAG, NULL) : BuildSDIV(Op.Val, DAG, NULL); Tmp1 = DAG.getNode(ISD::MUL, VT, Tmp1, Op.getOperand(1)); Tmp1 = DAG.getNode(ISD::SUB, VT, Op.getOperand(0), Tmp1); return Tmp1; } //fall through case ISD::SDIV: case ISD::UDIV: if (MVT::isInteger(Op.getValueType())) { if (Op.getOperand(1).getOpcode() == ISD::Constant) return Op.getOpcode() == ISD::SDIV ? BuildSDIV(Op.Val, DAG, NULL) : BuildUDIV(Op.Val, DAG, NULL); const char* opstr = 0; switch (Op.getOpcode()) { case ISD::UREM: opstr = "__remqu"; break; case ISD::SREM: opstr = "__remq"; break; case ISD::UDIV: opstr = "__divqu"; break; case ISD::SDIV: opstr = "__divq"; break; } SDOperand Tmp1 = Op.getOperand(0), Tmp2 = Op.getOperand(1), Addr = DAG.getExternalSymbol(opstr, MVT::i64); return DAG.getNode(AlphaISD::DivCall, MVT::i64, Addr, Tmp1, Tmp2); } break; case ISD::VAARG: { SDOperand Chain = Op.getOperand(0); SDOperand VAListP = Op.getOperand(1); SrcValueSDNode *VAListS = cast<SrcValueSDNode>(Op.getOperand(2)); SDOperand Base = DAG.getLoad(MVT::i64, Chain, VAListP, VAListS->getValue(), VAListS->getOffset()); SDOperand Tmp = DAG.getNode(ISD::ADD, MVT::i64, VAListP, DAG.getConstant(8, MVT::i64)); SDOperand Offset = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Base.getValue(1), Tmp, NULL, 0, MVT::i32); SDOperand DataPtr = DAG.getNode(ISD::ADD, MVT::i64, Base, Offset); if (MVT::isFloatingPoint(Op.getValueType())) { //if fp && Offset < 6*8, then subtract 6*8 from DataPtr SDOperand FPDataPtr = DAG.getNode(ISD::SUB, MVT::i64, DataPtr, DAG.getConstant(8*6, MVT::i64)); SDOperand CC = DAG.getSetCC(MVT::i64, Offset, DAG.getConstant(8*6, MVT::i64), ISD::SETLT); DataPtr = DAG.getNode(ISD::SELECT, MVT::i64, CC, FPDataPtr, DataPtr); } SDOperand NewOffset = DAG.getNode(ISD::ADD, MVT::i64, Offset, DAG.getConstant(8, MVT::i64)); SDOperand Update = DAG.getTruncStore(Offset.getValue(1), NewOffset, Tmp, NULL, 0, MVT::i32); SDOperand Result; if (Op.getValueType() == MVT::i32) Result = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Update, DataPtr, NULL, 0, MVT::i32); else Result = DAG.getLoad(Op.getValueType(), Update, DataPtr, NULL, 0); return Result; } case ISD::VACOPY: { SDOperand Chain = Op.getOperand(0); SDOperand DestP = Op.getOperand(1); SDOperand SrcP = Op.getOperand(2); SrcValueSDNode *DestS = cast<SrcValueSDNode>(Op.getOperand(3)); SrcValueSDNode *SrcS = cast<SrcValueSDNode>(Op.getOperand(4)); SDOperand Val = DAG.getLoad(getPointerTy(), Chain, SrcP, SrcS->getValue(), SrcS->getOffset()); SDOperand Result = DAG.getStore(Val.getValue(1), Val, DestP, DestS->getValue(), DestS->getOffset()); SDOperand NP = DAG.getNode(ISD::ADD, MVT::i64, SrcP, DAG.getConstant(8, MVT::i64)); Val = DAG.getExtLoad(ISD::SEXTLOAD, MVT::i64, Result, NP, NULL,0, MVT::i32); SDOperand NPD = DAG.getNode(ISD::ADD, MVT::i64, DestP, DAG.getConstant(8, MVT::i64)); return DAG.getTruncStore(Val.getValue(1), Val, NPD, NULL, 0, MVT::i32); } case ISD::VASTART: { SDOperand Chain = Op.getOperand(0); SDOperand VAListP = Op.getOperand(1); SrcValueSDNode *VAListS = cast<SrcValueSDNode>(Op.getOperand(2)); // vastart stores the address of the VarArgsBase and VarArgsOffset SDOperand FR = DAG.getFrameIndex(VarArgsBase, MVT::i64); SDOperand S1 = DAG.getStore(Chain, FR, VAListP, VAListS->getValue(), VAListS->getOffset()); SDOperand SA2 = DAG.getNode(ISD::ADD, MVT::i64, VAListP, DAG.getConstant(8, MVT::i64)); return DAG.getTruncStore(S1, DAG.getConstant(VarArgsOffset, MVT::i64), SA2, NULL, 0, MVT::i32); } case ISD::RETURNADDR: return DAG.getNode(AlphaISD::GlobalRetAddr, MVT::i64); //FIXME: implement case ISD::FRAMEADDR: break; } return SDOperand(); }
/// 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) const { MachineFunction &MF = DAG.getMachineFunction(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); // 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; 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 (!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, 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); } InVals.push_back(Arg); } else { int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset, true, false); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); SDValue Load; if (ObjectVT == MVT::i32) { Load = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0, 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, ObjectVT.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, NULL, 0, ObjectVT, false, false, 0); Load = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Load); } InVals.push_back(Load); } ArgOffset += 4; break; case MVT::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, MVT::i32); Arg = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, Arg); InVals.push_back(Arg); } else { int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset, true, false); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); SDValue Load = DAG.getLoad(MVT::f32, dl, Chain, FIPtr, NULL, 0, false, false, 0); InVals.push_back(Load); } ArgOffset += 4; break; case MVT::i64: case MVT::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, MVT::i32); } else { int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset, true, false); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); HiVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0, false, false, 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(Chain, dl, VRegLo, MVT::i32); } else { int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset+4, true, false); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0, false, false, 0); } // Compose the two halves together into an i64 unit. SDValue WholeValue = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal); // If we want a double, do a bit convert. if (ObjectVT == MVT::f64) WholeValue = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, WholeValue); InVals.push_back(WholeValue); } ArgOffset += 8; break; } } // Store remaining ArgRegs to the stack if this is a varargs function. if (isVarArg) { // Remember the vararg offset for the va_start implementation. FuncInfo->setVarArgsFrameOffset(ArgOffset); std::vector<SDValue> OutChains; for (; CurArgReg != ArgRegEnd; ++CurArgReg) { unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); MF.getRegInfo().addLiveIn(*CurArgReg, VReg); SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, MVT::i32); int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset, true, false); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); OutChains.push_back(DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, NULL, 0, false, false, 0)); ArgOffset += 4; } if (!OutChains.empty()) { OutChains.push_back(Chain); Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &OutChains[0], OutChains.size()); } } return 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) { MachineFunction &MF = DAG.getMachineFunction(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); 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!"); case MVT::i1: case MVT::i8: case MVT::i16: case MVT::i32: if (I->use_empty()) { // Argument is dead. if (CurArgReg < ArgRegEnd) ++CurArgReg; ArgValues.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); 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); } 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); } 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, MVT::i32, FIPtr, DAG.getConstant(Offset, MVT::i32)); Load = DAG.getExtLoad(LoadOp, dl, MVT::i32, Root, FIPtr, NULL, 0, ObjectVT); Load = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Load); } ArgValues.push_back(Load); } ArgOffset += 4; break; case MVT::f32: if (I->use_empty()) { // Argument is dead. if (CurArgReg < ArgRegEnd) ++CurArgReg; ArgValues.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); Arg = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, Arg); ArgValues.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); } ArgOffset += 4; break; case MVT::i64: case MVT::f64: if (I->use_empty()) { // Argument is dead. if (CurArgReg < ArgRegEnd) ++CurArgReg; if (CurArgReg < ArgRegEnd) ++CurArgReg; ArgValues.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); } 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); } 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); } 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); } // Compose the two halves together into an i64 unit. SDValue WholeValue = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal); // If we want a double, do a bit convert. if (ObjectVT == MVT::f64) WholeValue = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, WholeValue); ArgValues.push_back(WholeValue); } ArgOffset += 8; break; } } // Store remaining ArgRegs to the stack if this is a varargs function. if (F.isVarArg()) { // Remember the vararg offset for the va_start implementation. VarArgsFrameOffset = ArgOffset; for (; CurArgReg != ArgRegEnd; ++CurArgReg) { unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); MF.getRegInfo().addLiveIn(*CurArgReg, VReg); SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, MVT::i32); int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); OutChains.push_back(DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, NULL, 0)); ArgOffset += 4; } } if (!OutChains.empty()) DAG.setRoot(DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &OutChains[0], OutChains.size())); }
/// 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) const { MachineFunction &MF = DAG.getMachineFunction(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); // 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); const unsigned StackOffset = 92; for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; 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, 0); InVals.push_back(Arg); continue; } 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 (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, 0); } else { unsigned loReg = MF.addLiveIn(NextVA.getLocReg(), &SP::IntRegsRegClass); LoVal = DAG.getCopyFromReg(Chain, dl, loReg, MVT::i32); } 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; } 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; } assert(VA.isMemLoc()); 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, 0); InVals.push_back(Load); continue; } 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, 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, 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, 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<SparcMachineFunctionInfo>(); 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 unsigned ArgRegs[] = { SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 }; unsigned NumAllocated = CCInfo.getFirstUnallocated(ArgRegs, 6); const unsigned *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. FuncInfo->setVarArgsFrameOffset(ArgOffset); std::vector<SDValue> OutChains; for (; CurArgReg != ArgRegEnd; ++CurArgReg) { unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); MF.getRegInfo().addLiveIn(*CurArgReg, VReg); SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, MVT::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, MachinePointerInfo(), false, false, 0)); ArgOffset += 4; } if (!OutChains.empty()) { OutChains.push_back(Chain); Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &OutChains[0], OutChains.size()); } } return Chain; }
SDValue VectorProcTargetLowering:: LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); // Analyze operands of the call, assigning locations to each operand. // VectorProcCallingConv.td will auto-generate CC_VectorProc32, which // knows how to handle operands (what go in registers vs. stack, etc). SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), getTargetMachine(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeFormalArguments(Ins, CC_VectorProc32); // Walk through each parameter and push into InVals for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; if (i == 0 && Ins[i].Flags.isSRet()) { // Structure return? 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; } if (VA.isRegLoc()) { // Argument is in register EVT RegVT = VA.getLocVT(); const TargetRegisterClass *RC; if (RegVT == MVT::i32 || RegVT == MVT::f32 || RegVT == MVT::v16i1) RC = &VectorProc::ScalarRegRegClass; else if (RegVT == MVT::v16i32 || RegVT == MVT::v16f32) RC = &VectorProc::VectorRegRegClass; else llvm_unreachable("Unsupported formal argument type"); unsigned VReg = RegInfo.createVirtualRegister(RC); MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg); SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, VA.getLocVT()); InVals.push_back(Arg); continue; } // Otherwise this parameter is on the stack assert(VA.isMemLoc()); int FI = MF.getFrameInfo()->CreateFixedObject(VA.getValVT().getSizeInBits() / 8, VA.getLocMemOffset(), true); SDValue FIPtr = DAG.getFrameIndex(FI, getPointerTy()); SDValue Load; if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32 || VA.getValVT() == MVT::v16i32) { // Primitive types are loaded directly from the stack Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo(), false, false, false, 0); } else { // This is a smaller type (char, etc). Sign extend. ISD::LoadExtType LoadOp = ISD::SEXTLOAD; 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()) { // When a function returns a structure, the address of the return value // is placed in the first physical register. VectorProcMachineFunctionInfo *SFI = MF.getInfo<VectorProcMachineFunctionInfo>(); unsigned Reg = SFI->getSRetReturnReg(); if (!Reg) { Reg = MF.getRegInfo().createVirtualRegister(&VectorProc::ScalarRegRegClass); SFI->setSRetReturnReg(Reg); } SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[0]); Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain); } // Here is where variable arguments would be handled. if (isVarArg) { llvm_unreachable("variable arguments not implemented yet"); } return Chain; }