mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 04:22:20 +02:00
Win32 lowering fixes
This commit is contained in:
parent
a8d4d085c2
commit
91b046b6d7
4 changed files with 152 additions and 61 deletions
|
@ -5660,8 +5660,13 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& 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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<void(BfType*, int)> _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<void(BfType*, int)> _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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue