diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 1f001b9e..a7f8776a 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -5660,8 +5660,13 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl& ir { disableLowering = true; auto argTypeInstance = argVal.mType->ToTypeInstance(); - if ((!disableSplat) && (int)irArgs.size() + argVal.mType->GetSplatCount() <= mModule->mCompiler->mOptions.mMaxSplatRegs) - wantSplat = true; + if (!disableSplat) + { + if ((argTypeInstance != NULL) && (argTypeInstance->mIsCRepr)) + wantSplat = true; + else if ((int)irArgs.size() + argVal.mType->GetSplatCount() <= mModule->mCompiler->mOptions.mMaxSplatRegs) + wantSplat = true; + } } if (wantSplat) diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index c5b24b31..133285c6 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -15539,9 +15539,14 @@ BfIRCallingConv BfModule::GetIRCallingConvention(BfMethodInstance* methodInstanc return BfIRCallingConv_StdCall; if (methodInstance->mCallingConvention == BfCallingConvention_Fastcall) return BfIRCallingConv_FastCall; - if ((!methodDef->mIsStatic) && (!owner->IsValuelessType()) && - ((!owner->IsSplattable()) || (methodDef->HasNoThisSplat()))) - return BfIRCallingConv_ThisCall; + if (!methodDef->mIsStatic) + { + if (owner->mIsCRepr) + return BfIRCallingConv_ThisCall; + if ((!owner->IsValuelessType()) && + ((!owner->IsSplattable()) || (methodDef->HasNoThisSplat()))) + return BfIRCallingConv_ThisCall; + } return BfIRCallingConv_CDecl; //return GetIRCallingConvention(owner, methodInstance->mMethodDef); @@ -15629,8 +15634,14 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func // crepr splat is always splattable isSplattable = true; } - else if (resolvedTypeRef->GetSplatCount() + argIdx <= mCompiler->mOptions.mMaxSplatRegs) - isSplattable = true; + else + { + auto resolvedTypeInst = resolvedTypeRef->ToTypeInstance(); + if ((resolvedTypeInst != NULL) && (resolvedTypeInst->mIsCRepr)) + isSplattable = true; + else if (resolvedTypeRef->GetSplatCount() + argIdx <= mCompiler->mOptions.mMaxSplatRegs) + isSplattable = true; + } } } @@ -16881,9 +16892,15 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp { if (methodInstance->AllowsSplatting(paramIdx)) { - int splatCount = resolvedType->GetSplatCount(); - if (argIdx + splatCount <= mCompiler->mOptions.mMaxSplatRegs) + auto resolveTypeInst = resolvedType->ToTypeInstance(); + if ((resolveTypeInst != NULL) && (resolveTypeInst->mIsCRepr)) paramVar->mIsSplat = true; + else + { + int splatCount = resolvedType->GetSplatCount(); + if (argIdx + splatCount <= mCompiler->mOptions.mMaxSplatRegs) + paramVar->mIsSplat = true; + } } } } @@ -21597,8 +21614,14 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var); PopulateType(checkType, BfPopulateType_Data); if (checkType->IsSplattable()) { + bool isSplat = false; + auto checkTypeInstance = checkType->ToTypeInstance(); + if ((checkTypeInstance != NULL) && (checkTypeInstance->mIsCRepr)) + isSplat = true; int splatCount = checkType->GetSplatCount(); if (checkArgIdx + splatCount <= mCompiler->mOptions.mMaxSplatRegs) + isSplat = true; + if (isSplat) { methodParam.mIsSplat = true; argIdx += splatCount; diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index c8b077df..7d36f2b0 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -3700,8 +3700,13 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy splatIterate(typeInstance); if (isCRepr) - { - typeInstance->mIsSplattable = false; + { + if ((mCompiler->mOptions.mMachineType == BfMachineType_x86) && (mCompiler->mOptions.mPlatformType == BfPlatformType_Windows)) + { + typeInstance->mIsSplattable = (dataCount <= 4) && (!hadNonSplattable) && (dataPos > 4); + } + else + typeInstance->mIsSplattable = false; } else typeInstance->mIsSplattable = (dataCount <= 3) && (!hadNonSplattable); diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 61bcdebe..79d8b7f1 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -753,7 +753,29 @@ bool BfMethodInstance::HasSelf() } bool BfMethodInstance::GetLoweredReturnType(BfTypeCode* loweredTypeCode, BfTypeCode* loweredTypeCode2) -{ +{ + // Win32 handler + if ((mMethodDef->mIsStatic) && (mReturnType->IsComposite()) && + ((mReturnType->mSize == 4) || (mReturnType->mSize == 8))) + { + auto returnTypeInst = mReturnType->ToTypeInstance(); + if ((returnTypeInst != NULL) && (returnTypeInst->mIsCRepr)) + { + auto module = GetOwner()->mModule; + auto compiler = module->mCompiler; + if ((compiler->mOptions.mMachineType == BfMachineType_x86) && (compiler->mOptions.mPlatformType == BfPlatformType_Windows)) + { + if (loweredTypeCode != NULL) + { + *loweredTypeCode = BfTypeCode_Int32; + if (mReturnType->mSize == 8) + *loweredTypeCode = BfTypeCode_Int64; + } + return true; + } + } + } + return mReturnType->GetLoweredType(mMethodDef->mIsStatic ? BfTypeUsage_Return_Static : BfTypeUsage_Return_NonStatic, loweredTypeCode, loweredTypeCode2); } @@ -1233,7 +1255,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, continue; if ((doSplat) && (!checkType->IsMethodRef())) - { + { int splatCount = checkType->GetSplatCount(); if ((int)paramTypes.size() + splatCount > module->mCompiler->mOptions.mMaxSplatRegs) { @@ -1738,56 +1760,101 @@ bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCo if (mHasUnderlyingArray) return false; + bool deepCheck = false; + if (mModule->mCompiler->mOptions.mPlatformType == BfPlatformType_Windows) { // Odd Windows rule: composite returns for non-static methods are always sret if (typeUsage == BfTypeUsage_Return_NonStatic) - return false; + return false; } else - { - // Non-Windows systems allow lowered splitting of composites over two int params - if (mModule->mSystem->mPtrSize == 8) - { - if ((mInstSize >= 4) && (mInstSize <= 16)) + { + // Non-Win64 systems allow lowered splitting of composites over multiple params + if (mModule->mSystem->mPtrSize == 8) + deepCheck = true; + else + { + // We know this is correct for Linux x86 and Android armv7 + if (mModule->mCompiler->mOptions.mPlatformType == BfPlatformType_Linux) { - BfTypeCode types[4] = { BfTypeCode_None }; - - std::function _CheckType = [&](BfType* type, int offset) + if ((typeUsage == BfTypeUsage_Return_NonStatic) || (typeUsage == BfTypeUsage_Return_Static)) + return false; + } + } + } + + if (deepCheck) + { + + if ((mInstSize >= 4) && (mInstSize <= 16)) + { + BfTypeCode types[4] = { BfTypeCode_None }; + + std::function _CheckType = [&](BfType* type, int offset) + { + if (auto typeInst = type->ToTypeInstance()) { - if (auto typeInst = type->ToTypeInstance()) + if (typeInst->IsValueType()) { - if (typeInst->IsValueType()) + if (typeInst->mBaseType != NULL) + _CheckType(typeInst->mBaseType, offset); + + for (auto& fieldInstance : typeInst->mFieldInstances) { - if (typeInst->mBaseType != NULL) - _CheckType(typeInst->mBaseType, offset); - - for (auto& fieldInstance : typeInst->mFieldInstances) - { - if (fieldInstance.mDataOffset >= 0) - _CheckType(fieldInstance.mResolvedType, offset + fieldInstance.mDataOffset); - } + if (fieldInstance.mDataOffset >= 0) + _CheckType(fieldInstance.mResolvedType, offset + fieldInstance.mDataOffset); } - else - types[offset / 4] = BfTypeCode_Object; } - else if (type->IsPrimitiveType()) + else + types[offset / 4] = BfTypeCode_Object; + } + else if (type->IsPrimitiveType()) + { + auto primType = (BfPrimitiveType*)type; + types[offset / 4] = primType->mTypeDef->mTypeCode; + } + else if (type->IsSizedArray()) + { + auto sizedArray = (BfSizedArrayType*)type; + for (int i = 0; i < sizedArray->mElementCount; i++) + _CheckType(sizedArray->mElementType, offset + i * sizedArray->mElementType->GetStride()); + } + }; + + _CheckType(this, 0); + + bool handled = false; + + if (mModule->mCompiler->mOptions.mPlatformType == BfPlatformType_Windows) + { + bool hasFloat = false; + for (int type = 0; type < 4; type++) + { + if ((types[type] == BfTypeCode_Float) || + (types[type] == BfTypeCode_Double)) + hasFloat = false; + } + + if (!hasFloat) + { + if (mInstSize == 4) { - auto primType = (BfPrimitiveType*)type; - types[offset / 4] = primType->mTypeDef->mTypeCode; + if (outTypeCode != NULL) + *outTypeCode = BfTypeCode_Int32; + return true; } - else if (type->IsSizedArray()) + + if (mInstSize == 8) { - auto sizedArray = (BfSizedArrayType*)type; - for (int i = 0; i < sizedArray->mElementCount; i++) - _CheckType(sizedArray->mElementType, offset + i * sizedArray->mElementType->GetStride()); + if (outTypeCode != NULL) + *outTypeCode = BfTypeCode_Int64; + return true; } - }; - - _CheckType(this, 0); - - bool handled = false; - + } + } + else + { if (mInstSize >= 8) { if (outTypeCode != NULL) @@ -1803,7 +1870,7 @@ bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCo { handled = true; if (outTypeCode2 != NULL) - *outTypeCode2 = BfTypeCode_Int8; + *outTypeCode2 = BfTypeCode_Int8; } if (mInstSize == 10) { @@ -1812,16 +1879,16 @@ bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCo *outTypeCode2 = BfTypeCode_Int16; } if (mInstSize == 12) - { + { handled = true; if (outTypeCode2 != NULL) - *outTypeCode2 = BfTypeCode_Int32; + *outTypeCode2 = BfTypeCode_Int32; } if (mInstSize == 16) { handled = true; if (outTypeCode2 != NULL) - *outTypeCode2 = BfTypeCode_Int64; + *outTypeCode2 = BfTypeCode_Int64; } if ((types[0] == BfTypeCode_Float) && (types[1] == BfTypeCode_None)) @@ -1831,7 +1898,7 @@ bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCo *outTypeCode = BfTypeCode_Float; } if ((types[0] == BfTypeCode_Float) && (types[1] == BfTypeCode_Float)) - { + { if (outTypeCode != NULL) *outTypeCode = BfTypeCode_Float2; } @@ -1859,15 +1926,6 @@ bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCo if (handled) return true; - } - } - else - { - // We know this is correct for Linux x86 and Android armv7 - if (mModule->mCompiler->mOptions.mPlatformType == BfPlatformType_Linux) - { - if ((typeUsage == BfTypeUsage_Return_NonStatic) || (typeUsage == BfTypeUsage_Return_Static)) - return false; } } }