Index: lib/Target/Mips/MipsCallingConv.td =================================================================== --- lib/Target/Mips/MipsCallingConv.td +++ lib/Target/Mips/MipsCallingConv.td @@ -297,6 +297,21 @@ ]>; def CC_Mips_FixedArg : CallingConv<[ + // f128 needs to be handled similarly to f32 and f64 on hard-float. However, + // f128 is not legal and is lowered to i128 which is further lowered to a pair + // of i64's. + // This presents us with a problem for the calling convention since hard-float + // still needs to pass them in FPU registers. We therefore resort to a + // pre-analyze (see PreAnalyzeFormalArgsForF128()) step to pass information on + // whether the argument was originally an f128 into the tablegen-erated code. + // + // f128 should only occur for the N64 ABI where long double is 128-bit. On + // N32, long double is equivalent to double. + CCIfType<[i64], + CCIfSubtargetNot<"abiUsesSoftFloat()", + CCIf<"static_cast(&State)->WasOriginalArgF128(ValNo)", + CCBitConvertToType>>>, + CCIfCC<"CallingConv::Fast", CCDelegateTo>, // FIXME: There wasn't an EABI case in the original code and it seems unlikely Index: lib/Target/Mips/MipsISelLowering.h =================================================================== --- lib/Target/Mips/MipsISelLowering.h +++ lib/Target/Mips/MipsISelLowering.h @@ -366,7 +366,6 @@ CCState &State); void analyzeFormalArguments(const SmallVectorImpl &Ins, bool IsSoftFloat, - Function::const_arg_iterator FuncArg, CCState &State); /// hasByValArg - Returns true if function has byval arguments. Index: lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsISelLowering.cpp +++ lib/Target/Mips/MipsISelLowering.cpp @@ -95,10 +95,52 @@ originalTypeIsF128(MF.getFunction()->getReturnType(), nullptr)); } + /// Identify lowered values that originated from f128 arguments and record + /// this. + void PreAnalyzeCallOperandsForF128( + const SmallVectorImpl &Outs, + std::vector &FuncArgs, SDNode *CallNode) { + const MachineFunction &MF = getMachineFunction(); + for (unsigned i = 0; i < Outs.size(); ++i) + OriginalArgWasF128.push_back( + originalTypeIsF128(FuncArgs[Outs[i].OrigArgIndex].Ty, CallNode)); + } + + /// Identify lowered values that originated from f128 arguments and record + /// this. + void + PreAnalyzeFormalArgumentsForF128(const SmallVectorImpl &Ins) { + const MachineFunction &MF = getMachineFunction(); + for (unsigned i = 0; i < Ins.size(); ++i) { + Function::const_arg_iterator FuncArg = MF.getFunction()->arg_begin(); + std::advance(FuncArg, Ins[i].OrigArgIndex); + + OriginalArgWasF128.push_back( + originalTypeIsF128(FuncArg->getType(), nullptr)); + } + } + /// Records whether the value has been lowered from an f128. SmallVector OriginalArgWasF128; public: + // FIXME: Remove this from a public inteface ASAP. It's a temporary trap door + // to allow analyzeCallOperands to be removed incrementally. + void PreAnalyzeCallOperandsForF128_( + const SmallVectorImpl &Outs, + std::vector &FuncArgs, SDNode *CallNode) { + PreAnalyzeCallOperandsForF128(Outs, FuncArgs, CallNode); + } + // FIXME: Remove this from a public inteface ASAP. It's a temporary trap door + // to allow analyzeFormalArguments to be removed incrementally. + void + PreAnalyzeFormalArgumentsForF128_(const SmallVectorImpl &Ins) { + PreAnalyzeFormalArgumentsForF128(Ins); + } + // FIXME: Remove this from a public inteface ASAP. It's a temporary trap door + // to clean up after the above functions. + void ClearOriginalArgWasF128() { OriginalArgWasF128.clear(); } + MipsCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, SmallVectorImpl &locs, LLVMContext &C) : CCState(CC, isVarArg, MF, locs, C) {} @@ -2546,12 +2588,14 @@ // Analyze operands of the call, assigning locations to each operand. SmallVector ArgLocs; - CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, - *DAG.getContext()); + MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, + *DAG.getContext()); MipsCC MipsCCInfo(CallConv, Subtarget, CCInfo); + CCInfo.PreAnalyzeCallOperandsForF128_(Outs, CLI.getArgs(), Callee.getNode()); MipsCCInfo.analyzeCallOperands(Outs, IsVarArg, Subtarget.abiUsesSoftFloat(), Callee.getNode(), CLI.getArgs(), CCInfo); + CCInfo.ClearOriginalArgWasF128(); // Get a count of how many bytes are to be pushed on the stack. unsigned NextStackOffset = CCInfo.getNextStackOffset(); @@ -2632,6 +2676,9 @@ } } break; + case CCValAssign::BCvt: + Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg); + break; case CCValAssign::SExt: Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, LocVT, Arg); break; @@ -2829,14 +2876,16 @@ // Assign locations to all of the incoming arguments. SmallVector ArgLocs; - CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, - *DAG.getContext()); + MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, + *DAG.getContext()); MipsCC MipsCCInfo(CallConv, Subtarget, CCInfo); Function::const_arg_iterator FuncArg = DAG.getMachineFunction().getFunction()->arg_begin(); bool UseSoftFloat = Subtarget.abiUsesSoftFloat(); - MipsCCInfo.analyzeFormalArguments(Ins, UseSoftFloat, FuncArg, CCInfo); + CCInfo.PreAnalyzeFormalArgumentsForF128_(Ins); + MipsCCInfo.analyzeFormalArguments(Ins, UseSoftFloat, CCInfo); + CCInfo.ClearOriginalArgWasF128(); MipsFI->setFormalArgInfo(CCInfo.getNextStackOffset(), MipsCCInfo.hasByValArg()); @@ -2875,16 +2924,24 @@ // If this is an 8 or 16-bit value, it has been passed promoted // to 32 bits. Insert an assert[sz]ext to capture this, then // truncate to the right size. - if (VA.getLocInfo() != CCValAssign::Full) { - unsigned Opcode = 0; - if (VA.getLocInfo() == CCValAssign::SExt) - Opcode = ISD::AssertSext; - else if (VA.getLocInfo() == CCValAssign::ZExt) - Opcode = ISD::AssertZext; - if (Opcode) - ArgValue = DAG.getNode(Opcode, DL, RegVT, ArgValue, - DAG.getValueType(ValVT)); + switch (VA.getLocInfo()) { + default: + llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: + break; + case CCValAssign::SExt: + ArgValue = DAG.getNode(ISD::AssertSext, DL, RegVT, ArgValue, + DAG.getValueType(ValVT)); + ArgValue = DAG.getNode(ISD::TRUNCATE, DL, ValVT, ArgValue); + break; + case CCValAssign::ZExt: + ArgValue = DAG.getNode(ISD::AssertZext, DL, RegVT, ArgValue, + DAG.getValueType(ValVT)); ArgValue = DAG.getNode(ISD::TRUNCATE, DL, ValVT, ArgValue); + break; + case CCValAssign::BCvt: + ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); + break; } // Handle floating point arguments passed in integer registers and @@ -3562,11 +3619,8 @@ if (IsVarArg && !Args[I].IsFixed) R = CC_Mips_VarArg(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, State); - else { - MVT RegVT = getRegVT(ArgVT, FuncArgs[Args[I].OrigArgIndex].Ty, CallNode, - IsSoftFloat); - R = FixedFn(I, ArgVT, RegVT, CCValAssign::Full, ArgFlags, State); - } + else + R = FixedFn(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, State); if (R) { #ifndef NDEBUG @@ -3580,24 +3634,19 @@ void MipsTargetLowering::MipsCC::analyzeFormalArguments( const SmallVectorImpl &Args, bool IsSoftFloat, - Function::const_arg_iterator FuncArg, CCState &State) { + CCState &State) { unsigned NumArgs = Args.size(); - unsigned CurArgIdx = 0; for (unsigned I = 0; I != NumArgs; ++I) { MVT ArgVT = Args[I].VT; ISD::ArgFlagsTy ArgFlags = Args[I].Flags; - std::advance(FuncArg, Args[I].OrigArgIndex - CurArgIdx); - CurArgIdx = Args[I].OrigArgIndex; if (ArgFlags.isByVal()) { handleByValArg(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, State); continue; } - MVT RegVT = getRegVT(ArgVT, FuncArg->getType(), nullptr, IsSoftFloat); - - if (!CC_Mips_FixedArg(I, ArgVT, RegVT, CCValAssign::Full, ArgFlags, State)) + if (!CC_Mips_FixedArg(I, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, State)) continue; #ifndef NDEBUG