From 686050a68bdb9b6abc9ebb4092cd7221831e3f9f Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 9 Mar 2020 11:46:40 -0700 Subject: [PATCH] Fixed some lowering of Win32 structs by value --- IDEHelper/Compiler/BfExprEvaluator.cpp | 25 ++++++++++++---- IDEHelper/Compiler/BfModule.cpp | 23 ++++++++++++--- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 33 ++++++++++++++++++++++ IDEHelper/Compiler/BfResolvedTypeUtils.cpp | 10 ++++++- 4 files changed, 81 insertions(+), 10 deletions(-) diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 21b9e596..3dd43a64 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -4564,10 +4564,19 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV //byval } else - { - mModule->mBfIRBuilder->Call_AddAttribute(callInst, argIdx + 1, BfIRAttribute_NoCapture); + { mModule->PopulateType(paramType, BfPopulateType_Data); - addDeref = paramType->mSize; + + auto typeInst = paramType->ToTypeInstance(); + if ((typeInst != NULL) && (typeInst->mIsCRepr) && (typeInst->IsSplattable())) + { + // We're splatting + } + else + { + mModule->mBfIRBuilder->Call_AddAttribute(callInst, argIdx + 1, BfIRAttribute_NoCapture); + addDeref = paramType->mSize; + } } } else if (paramType->IsPrimitiveType()) @@ -4822,9 +4831,15 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl& ir return; bool wantSplat = false; - if ((argVal.mType->IsSplattable()) && (!disableSplat)) + if (argVal.mType->IsSplattable()) { - if ((int)irArgs.size() + argVal.mType->GetSplatCount() <= mModule->mCompiler->mOptions.mMaxSplatRegs) + auto argTypeInstance = argVal.mType->ToTypeInstance(); + if ((argTypeInstance != NULL) && (argTypeInstance->mIsCRepr)) + { + // Always splat for crepr splattables + wantSplat = true; + } + else if ((!disableSplat) && (int)irArgs.size() + argVal.mType->GetSplatCount() <= mModule->mCompiler->mOptions.mMaxSplatRegs) wantSplat = true; } diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 0a536419..bbee433a 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -5495,7 +5495,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin BfIRType fieldDataPtrType = mBfIRBuilder->GetPointerTo(reflectFieldDataIRType); if (fieldTypes.size() == 0) { - if ((type->IsSplattable()) && (type->IsStruct()) && (!type->IsValuelessType())) + if ((type->IsSplattable()) && (type->IsStruct()) && (!type->IsValuelessType()) && (!typeInstance->mIsCRepr)) { BfTypeInstance* reflectFieldSplatDataType = ResolveTypeDef(mCompiler->mReflectFieldSplatDataDef)->ToTypeInstance(); @@ -14067,7 +14067,13 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func isSplattable = true; else if (resolvedTypeRef->IsSplattable()) { - if (resolvedTypeRef->GetSplatCount() + argIdx <= mCompiler->mOptions.mMaxSplatRegs) + auto resolvedTypeInst = resolvedTypeRef->ToTypeInstance(); + if ((resolvedTypeInst != NULL) && (resolvedTypeInst->mIsCRepr)) + { + // crepr splat is always splattable + isSplattable = true; + } + else if (resolvedTypeRef->GetSplatCount() + argIdx <= mCompiler->mOptions.mMaxSplatRegs) isSplattable = true; } } @@ -15148,9 +15154,18 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp } else if (resolvedType->IsComposite() && resolvedType->IsSplattable()) { - int splatCount = resolvedType->GetSplatCount(); - if (argIdx + splatCount <= mCompiler->mOptions.mMaxSplatRegs) + auto resolvedTypeInst = resolvedType->ToTypeInstance(); + if ((resolvedTypeInst != NULL) && (resolvedTypeInst->mIsCRepr)) + { + // crepr splat is always splat paramVar->mIsSplat = true; + } + else + { + int splatCount = resolvedType->GetSplatCount(); + if (argIdx + splatCount <= mCompiler->mOptions.mMaxSplatRegs) + paramVar->mIsSplat = true; + } } } else diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 710c0d59..c668c27e 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -2980,7 +2980,40 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy splatIterate(typeInstance); if (isCRepr) + { typeInstance->mIsSplattable = false; + + if ((mCompiler->mOptions.mPlatformType == BfPlatformType_Windows) && (mCompiler->mSystem->mPtrSize == 4)) + { + // Win32 splat rules + if ((typeInstance->mBaseType->mInstSize == 0) && (typeInstance->mInstSize <= 16)) + { + typeInstance->mIsSplattable = true; + + for (int fieldIdx = 0; fieldIdx < (int)typeInstance->mFieldInstances.size(); fieldIdx++) + { + auto fieldInstance = (BfFieldInstance*)&typeInstance->mFieldInstances[fieldIdx]; + if (fieldInstance->mDataIdx >= 0) + { + if (!fieldInstance->mResolvedType->IsPrimitiveType()) + typeInstance->mIsSplattable = false; + else + { + auto primType = (BfPrimitiveType*)fieldInstance->mResolvedType; + if ((primType->mTypeDef->mTypeCode != BfTypeCode_Int32) && + (primType->mTypeDef->mTypeCode != BfTypeCode_UInt32) && + (primType->mTypeDef->mTypeCode != BfTypeCode_IntPtr) && + (primType->mTypeDef->mTypeCode != BfTypeCode_UIntPtr) && + (primType->mTypeDef->mTypeCode != BfTypeCode_Pointer) && + (primType->mTypeDef->mTypeCode != BfTypeCode_Single) && + (primType->mTypeDef->mTypeCode != BfTypeCode_Double)) + typeInstance->mIsSplattable = false; + } + } + } + } + } + } else typeInstance->mIsSplattable = (dataCount <= 3) && (!hadNonSplattable); } diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 606a39d6..dc4032b0 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -949,7 +949,15 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, int splatCount = checkType->GetSplatCount(); doSplat = ((checkType->IsSplattable()) && ((paramIdx != -1) || (!mMethodDef->mIsMutating))); if ((int)paramTypes.size() + splatCount > module->mCompiler->mOptions.mMaxSplatRegs) - doSplat = false; + { + auto checkTypeInst = checkType->ToTypeInstance(); + if ((checkTypeInst != NULL) && (checkTypeInst->mIsCRepr)) + { + // CRepr splat means always splat + } + else + doSplat = false; + } } auto _AddType = [&](BfType* type)