1
0
Fork 0
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:
Brian Fiete 2020-12-28 10:50:04 -08:00
parent a8d4d085c2
commit 91b046b6d7
4 changed files with 152 additions and 61 deletions

View file

@ -5660,8 +5660,13 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
{ {
disableLowering = true; disableLowering = true;
auto argTypeInstance = argVal.mType->ToTypeInstance(); auto argTypeInstance = argVal.mType->ToTypeInstance();
if ((!disableSplat) && (int)irArgs.size() + argVal.mType->GetSplatCount() <= mModule->mCompiler->mOptions.mMaxSplatRegs) if (!disableSplat)
wantSplat = true; {
if ((argTypeInstance != NULL) && (argTypeInstance->mIsCRepr))
wantSplat = true;
else if ((int)irArgs.size() + argVal.mType->GetSplatCount() <= mModule->mCompiler->mOptions.mMaxSplatRegs)
wantSplat = true;
}
} }
if (wantSplat) if (wantSplat)

View file

@ -15539,9 +15539,14 @@ BfIRCallingConv BfModule::GetIRCallingConvention(BfMethodInstance* methodInstanc
return BfIRCallingConv_StdCall; return BfIRCallingConv_StdCall;
if (methodInstance->mCallingConvention == BfCallingConvention_Fastcall) if (methodInstance->mCallingConvention == BfCallingConvention_Fastcall)
return BfIRCallingConv_FastCall; return BfIRCallingConv_FastCall;
if ((!methodDef->mIsStatic) && (!owner->IsValuelessType()) && if (!methodDef->mIsStatic)
((!owner->IsSplattable()) || (methodDef->HasNoThisSplat()))) {
return BfIRCallingConv_ThisCall; if (owner->mIsCRepr)
return BfIRCallingConv_ThisCall;
if ((!owner->IsValuelessType()) &&
((!owner->IsSplattable()) || (methodDef->HasNoThisSplat())))
return BfIRCallingConv_ThisCall;
}
return BfIRCallingConv_CDecl; return BfIRCallingConv_CDecl;
//return GetIRCallingConvention(owner, methodInstance->mMethodDef); //return GetIRCallingConvention(owner, methodInstance->mMethodDef);
@ -15629,8 +15634,14 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
// crepr splat is always splattable // crepr splat is always splattable
isSplattable = true; isSplattable = true;
} }
else if (resolvedTypeRef->GetSplatCount() + argIdx <= mCompiler->mOptions.mMaxSplatRegs) else
isSplattable = true; {
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)) if (methodInstance->AllowsSplatting(paramIdx))
{ {
int splatCount = resolvedType->GetSplatCount(); auto resolveTypeInst = resolvedType->ToTypeInstance();
if (argIdx + splatCount <= mCompiler->mOptions.mMaxSplatRegs) if ((resolveTypeInst != NULL) && (resolveTypeInst->mIsCRepr))
paramVar->mIsSplat = true; 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); PopulateType(checkType, BfPopulateType_Data);
if (checkType->IsSplattable()) if (checkType->IsSplattable())
{ {
bool isSplat = false;
auto checkTypeInstance = checkType->ToTypeInstance();
if ((checkTypeInstance != NULL) && (checkTypeInstance->mIsCRepr))
isSplat = true;
int splatCount = checkType->GetSplatCount(); int splatCount = checkType->GetSplatCount();
if (checkArgIdx + splatCount <= mCompiler->mOptions.mMaxSplatRegs) if (checkArgIdx + splatCount <= mCompiler->mOptions.mMaxSplatRegs)
isSplat = true;
if (isSplat)
{ {
methodParam.mIsSplat = true; methodParam.mIsSplat = true;
argIdx += splatCount; argIdx += splatCount;

View file

@ -3700,8 +3700,13 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
splatIterate(typeInstance); splatIterate(typeInstance);
if (isCRepr) 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 else
typeInstance->mIsSplattable = (dataCount <= 3) && (!hadNonSplattable); typeInstance->mIsSplattable = (dataCount <= 3) && (!hadNonSplattable);

View file

@ -753,7 +753,29 @@ bool BfMethodInstance::HasSelf()
} }
bool BfMethodInstance::GetLoweredReturnType(BfTypeCode* loweredTypeCode, BfTypeCode* loweredTypeCode2) 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); 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; continue;
if ((doSplat) && (!checkType->IsMethodRef())) if ((doSplat) && (!checkType->IsMethodRef()))
{ {
int splatCount = checkType->GetSplatCount(); int splatCount = checkType->GetSplatCount();
if ((int)paramTypes.size() + splatCount > module->mCompiler->mOptions.mMaxSplatRegs) if ((int)paramTypes.size() + splatCount > module->mCompiler->mOptions.mMaxSplatRegs)
{ {
@ -1738,56 +1760,101 @@ bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCo
if (mHasUnderlyingArray) if (mHasUnderlyingArray)
return false; return false;
bool deepCheck = false;
if (mModule->mCompiler->mOptions.mPlatformType == BfPlatformType_Windows) if (mModule->mCompiler->mOptions.mPlatformType == BfPlatformType_Windows)
{ {
// Odd Windows rule: composite returns for non-static methods are always sret // Odd Windows rule: composite returns for non-static methods are always sret
if (typeUsage == BfTypeUsage_Return_NonStatic) if (typeUsage == BfTypeUsage_Return_NonStatic)
return false; return false;
} }
else else
{ {
// Non-Windows systems allow lowered splitting of composites over two int params // Non-Win64 systems allow lowered splitting of composites over multiple params
if (mModule->mSystem->mPtrSize == 8) if (mModule->mSystem->mPtrSize == 8)
{ deepCheck = true;
if ((mInstSize >= 4) && (mInstSize <= 16)) else
{
// We know this is correct for Linux x86 and Android armv7
if (mModule->mCompiler->mOptions.mPlatformType == BfPlatformType_Linux)
{ {
BfTypeCode types[4] = { BfTypeCode_None }; if ((typeUsage == BfTypeUsage_Return_NonStatic) || (typeUsage == BfTypeUsage_Return_Static))
return false;
std::function<void(BfType*, int)> _CheckType = [&](BfType* type, int offset) }
}
}
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) if (fieldInstance.mDataOffset >= 0)
_CheckType(typeInst->mBaseType, offset); _CheckType(fieldInstance.mResolvedType, offset + fieldInstance.mDataOffset);
for (auto& fieldInstance : typeInst->mFieldInstances)
{
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; if (outTypeCode != NULL)
types[offset / 4] = primType->mTypeDef->mTypeCode; *outTypeCode = BfTypeCode_Int32;
return true;
} }
else if (type->IsSizedArray())
if (mInstSize == 8)
{ {
auto sizedArray = (BfSizedArrayType*)type; if (outTypeCode != NULL)
for (int i = 0; i < sizedArray->mElementCount; i++) *outTypeCode = BfTypeCode_Int64;
_CheckType(sizedArray->mElementType, offset + i * sizedArray->mElementType->GetStride()); return true;
} }
}; }
}
_CheckType(this, 0); else
{
bool handled = false;
if (mInstSize >= 8) if (mInstSize >= 8)
{ {
if (outTypeCode != NULL) if (outTypeCode != NULL)
@ -1803,7 +1870,7 @@ bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCo
{ {
handled = true; handled = true;
if (outTypeCode2 != NULL) if (outTypeCode2 != NULL)
*outTypeCode2 = BfTypeCode_Int8; *outTypeCode2 = BfTypeCode_Int8;
} }
if (mInstSize == 10) if (mInstSize == 10)
{ {
@ -1812,16 +1879,16 @@ bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCo
*outTypeCode2 = BfTypeCode_Int16; *outTypeCode2 = BfTypeCode_Int16;
} }
if (mInstSize == 12) if (mInstSize == 12)
{ {
handled = true; handled = true;
if (outTypeCode2 != NULL) if (outTypeCode2 != NULL)
*outTypeCode2 = BfTypeCode_Int32; *outTypeCode2 = BfTypeCode_Int32;
} }
if (mInstSize == 16) if (mInstSize == 16)
{ {
handled = true; handled = true;
if (outTypeCode2 != NULL) if (outTypeCode2 != NULL)
*outTypeCode2 = BfTypeCode_Int64; *outTypeCode2 = BfTypeCode_Int64;
} }
if ((types[0] == BfTypeCode_Float) && (types[1] == BfTypeCode_None)) if ((types[0] == BfTypeCode_Float) && (types[1] == BfTypeCode_None))
@ -1831,7 +1898,7 @@ bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCo
*outTypeCode = BfTypeCode_Float; *outTypeCode = BfTypeCode_Float;
} }
if ((types[0] == BfTypeCode_Float) && (types[1] == BfTypeCode_Float)) if ((types[0] == BfTypeCode_Float) && (types[1] == BfTypeCode_Float))
{ {
if (outTypeCode != NULL) if (outTypeCode != NULL)
*outTypeCode = BfTypeCode_Float2; *outTypeCode = BfTypeCode_Float2;
} }
@ -1859,15 +1926,6 @@ bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCo
if (handled) if (handled)
return true; 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;
} }
} }
} }