From 31746c1f19e10d186808c9c6706f615e298a8e02 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Fri, 25 Oct 2024 11:20:01 -0400 Subject: [PATCH] Wasm calling convention fixes. IDEHelper/Tests runs on wasm now. --- BeefLibs/corlib/src/Console.bf | 5 ++-- BeefLibs/corlib/src/Internal.bf | 20 ++++++++++++---- IDE/src/IDEApp.bf | 3 +++ IDE/src/ui/PropertiesDialog.bf | 10 ++++++++ IDEHelper/Compiler/BfExprEvaluator.cpp | 9 ++++++- IDEHelper/Compiler/BfModule.cpp | 2 +- IDEHelper/Compiler/BfResolvedTypeUtils.cpp | 28 ++++++++++++++++++++-- IDEHelper/Compiler/BfResolvedTypeUtils.h | 6 ++--- IDEHelper/Tests/BeefProj.toml | 4 ++++ IDEHelper/Tests/BeefSpace.toml | 21 ++++++++++++++++ IDEHelper/Tests/src/Append.bf | 2 ++ IDEHelper/Tests/src/Reflection.bf | 2 ++ 12 files changed, 99 insertions(+), 13 deletions(-) diff --git a/BeefLibs/corlib/src/Console.bf b/BeefLibs/corlib/src/Console.bf index f835d5f0..e3399176 100644 --- a/BeefLibs/corlib/src/Console.bf +++ b/BeefLibs/corlib/src/Console.bf @@ -90,11 +90,12 @@ namespace System static function void(StringView str) OutString = => OutString_Simple; -#if !BF_RUNTIME_DISABLE +#if !BF_RUNTIME_DISABLE && !BF_PLATFORM_WASM private static extern void PutChars(char8* c, int32 len); #else [CLink] - private static extern void putchar(char8 c); + private static extern int32 putchar(char8 c); + [LinkName("Console_PutChars")] private static void PutChars(char8* c, int32 len) { for (int i < len) diff --git a/BeefLibs/corlib/src/Internal.bf b/BeefLibs/corlib/src/Internal.bf index 5b5518a5..44f0b8fb 100644 --- a/BeefLibs/corlib/src/Internal.bf +++ b/BeefLibs/corlib/src/Internal.bf @@ -32,7 +32,7 @@ namespace System [CRepr] struct VarArgs { -#if BF_PLATFORM_WINDOWS +#if BF_PLATFORM_WINDOWS || BF_PLATFORM_WASM void* mVAList; #else int[5] mVAList; // Conservative size for va_list @@ -67,7 +67,7 @@ namespace System public void* ToVAList() mut { -#if BF_PLATFORM_WINDOWS +#if BF_PLATFORM_WINDOWS || BF_PLATFORM_WASM return mVAList; #else return &mVAList; @@ -101,6 +101,8 @@ namespace System #if BF_PLATFORM_WASM static int32 sTestIdx; + static int32 sRanTestCount; + static int32 sErrorCount; class TestEntry { public String mName ~ delete _; @@ -155,6 +157,7 @@ namespace System [CallingConvention(.Cdecl), LinkName("Test_Error_Wasm")] static void Test_Error(char8* error) { + sErrorCount++; Debug.WriteLine(scope $"TEST ERROR: {StringView(error)}"); } @@ -179,14 +182,23 @@ namespace System Debug.WriteLine($"Test '{testEntry.mName}'"); break; } - + + sRanTestCount++; return sTestIdx++; } [CallingConvention(.Cdecl), LinkName("Test_Finish_Wasm")] static void Test_Finish() { - Debug.WriteLine("Tests done."); + sRanTestCount--; + + String completeStr = scope $"Completed {sRanTestCount} of {sTestEntries.Count} tests.'"; + Debug.WriteLine(completeStr); + if (sErrorCount > 0) + { + String failStr = scope $"ERROR: Failed {sErrorCount} test{((sErrorCount != 1) ? "s" : "")}"; + Debug.WriteLine(failStr); + } } #else [CallingConvention(.Cdecl)] diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index a2b91aff..ccdaa950 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -10881,6 +10881,9 @@ namespace IDE case "VSToolPath_x64": newString = gApp.mSettings.mVSSettings.mBin64Path; IDEUtils.FixFilePath(newString); + case "EmccPath": + newString = scope:ReplaceBlock String(); + newString.AppendF($"{gApp.mSettings.mEmscriptenPath}/upstream/emscripten/emcc.bat"); } } diff --git a/IDE/src/ui/PropertiesDialog.bf b/IDE/src/ui/PropertiesDialog.bf index b662c844..5f9d7638 100644 --- a/IDE/src/ui/PropertiesDialog.bf +++ b/IDE/src/ui/PropertiesDialog.bf @@ -1,3 +1,5 @@ +#pragma warning disable 168 + using System; using System.Collections; using System.Diagnostics; @@ -1601,6 +1603,14 @@ namespace IDE.ui floatVal.ToString(valStr); valueItem.Label = valStr; } + else if (curVariantType == typeof(Workspace.ConfigSelection)) + { + var platformItem = (DarkListViewItem)propEntry.mListViewItem.GetSubItem(2); + + var configSelection = propEntry.mCurValue.Get(); + valueItem.Label = configSelection.mConfig; + platformItem.Label = configSelection.mPlatform; + } else ThrowUnimplemented(); //valueItem.Label = ToStackString!(propEntry.mCurValue); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index d562c623..18920d72 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -14018,7 +14018,14 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr) else if ((closureTypeInst != NULL) && (captureThisByValue)) { // When we need to aggregrate a splat for a target, we just point out delegate's mTarget to inside ourselves where we aggregated the value - auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(mResult.mValue, 0, 1); + int dataIdx = 1; + if (!closureTypeInst->mFieldInstances.IsEmpty()) + { + auto& fieldInst = closureTypeInst->mFieldInstances[0]; + BF_ASSERT(fieldInst.GetFieldDef()->mName == "__this"); + dataIdx = fieldInst.mDataIdx; + } + auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(mResult.mValue, 0, dataIdx); target = mModule->LoadValue(target); mModule->mBfIRBuilder->CreateStore(target.mValue, fieldPtr); target = BfTypedValue(fieldPtr, target.mType, true); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 4f773120..ad8cb1fc 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -1259,7 +1259,7 @@ void BfModule::SetupIRBuilder(bool dbgVerifyCodeGen) //mBfIRBuilder->mDbgVerifyCodeGen = true; if ( (mModuleName == "-") - || (mModuleName == "") + //|| (mModuleName == "") //|| (mModuleName == "Tests_FuncRefs") ) mBfIRBuilder->mDbgVerifyCodeGen = true; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index ea4831b4..783f6958 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -1801,11 +1801,11 @@ void BfTypeInstance::Dispose() mTypeDef = NULL; } -int BfTypeInstance::GetSplatCount() +int BfTypeInstance::GetSplatCount(bool force) { if (IsValuelessType()) return 0; - if (!mIsSplattable) + if ((!mIsSplattable) && (!force)) return 1; int splatCount = 0; BfTypeUtils::SplatIterate([&](BfType* checkType) { splatCount++; }, this); @@ -2048,6 +2048,30 @@ bool BfTypeInstance::GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCo bool deepCheck = false; + if (mModule->mCompiler->mOptions.mMachineType == BfMachineType_Wasm32) + { + if (IsComposite()) + { + if (GetSplatCount(true) == 1) + { + BfType* componentType = NULL; + BfTypeUtils::SplatIterate([&](BfType* checkType) { componentType = checkType; }, this); + if (componentType != NULL) + { + if (componentType->IsPrimitiveType()) + { + auto primType = (BfPrimitiveType*)componentType; + if (outTypeCode != NULL) + *outTypeCode = primType->mTypeDef->mTypeCode; + return true; + } + } + } + else + return false; + } + } + if (mModule->mCompiler->mOptions.mPlatformType == BfPlatformType_Windows) { // Odd Windows rule: composite returns for non-static methods are always sret diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 523bcea8..48f109da 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -553,7 +553,7 @@ public: virtual bool IsSpecializedByAutoCompleteMethod() { return false; } virtual bool IsUnspecializedTypeVariation() { return false; } virtual bool IsSplattable() { return false; } - virtual int GetSplatCount() { return 1; } + virtual int GetSplatCount(bool force = false) { return 1; } virtual bool IsVoid() { return false; } virtual bool IsVoidPtr() { return false; } virtual bool CanBeValuelessType() { return false; } @@ -2134,7 +2134,7 @@ public: virtual bool IsFinishingType() override { return mIsFinishingType; } virtual bool IsIncomplete() override { return (mTypeIncomplete) || (mBaseTypeMayBeIncomplete); } virtual bool IsSplattable() override { BF_ASSERT((mInstSize >= 0) || (!IsComposite())); return mIsSplattable; } - virtual int GetSplatCount() override; + virtual int GetSplatCount(bool force = false) override; virtual bool IsTypeInstance() override { return true; } virtual BfTypeCode GetTypeCode() override { return mTypeDef->mTypeCode; } virtual bool IsInterface() override { return mTypeDef->mTypeCode == BfTypeCode_Interface; } @@ -2465,7 +2465,7 @@ public: virtual bool IsComposite() override { return true; } virtual bool IsMethodRef() override { return true; } virtual bool IsSplattable() override { return true; } - virtual int GetSplatCount() override { return (int)mDataToParamIdx.mSize; } + virtual int GetSplatCount(bool force) override { return (int)mDataToParamIdx.mSize; } virtual bool IsOnDemand() override { return true; } virtual bool IsTemporary() override { return true; } diff --git a/IDEHelper/Tests/BeefProj.toml b/IDEHelper/Tests/BeefProj.toml index 3f2f8467..9cf6ef25 100644 --- a/IDEHelper/Tests/BeefProj.toml +++ b/IDEHelper/Tests/BeefProj.toml @@ -19,3 +19,7 @@ PreBuildCmds = ["/usr/bin/c++ $(ProjectDir)/CLib/main.cpp -g -c -o $(ProjectDir) [Configs.Test.macOS] OtherLinkFlags = "$(LinkFlags) $(ProjectDir)/CLib/main.o" PreBuildCmds = ["/usr/bin/c++ $(ProjectDir)/CLib/main.cpp -g -c -o $(ProjectDir)/CLib/main.o"] + +[Configs.Test.wasm32] +OtherLinkFlags = "$(LinkFlags) $(ProjectDir)/CLib/main_wasm.o -sSTACK_SIZE=1048576" +PreBuildCmds = ["$(EmccPath) $(ProjectDir)/CLib/main.cpp -g -c -o $(ProjectDir)/CLib/main_wasm.o"] diff --git a/IDEHelper/Tests/BeefSpace.toml b/IDEHelper/Tests/BeefSpace.toml index 60735120..9b6ccca6 100644 --- a/IDEHelper/Tests/BeefSpace.toml +++ b/IDEHelper/Tests/BeefSpace.toml @@ -11,6 +11,11 @@ IntermediateType = "ObjectAndIRCode" [Configs.Debug.Win32] IntermediateType = "ObjectAndIRCode" +[Configs.Debug.wasm32] +AllocType = "CRT" +EnableObjectDebugFlags = false +EmitObjectAccessCheck = false + [Configs.Test.Win64] IntermediateType = "ObjectAndIRCode" COptimizationLevel = "O2" @@ -26,6 +31,12 @@ COptimizationLevel = "O2" ConfigSelections = {TestsB = {Config = "Test"}} [Configs.Test.Win32] +ConfigSelections = {TestsB = {Config = "Test"}} + +[Configs.Test.wasm32] +AllocType = "CRT" +EnableObjectDebugFlags = false +EmitObjectAccessCheck = false IntermediateType = "ObjectAndIRCode" ConfigSelections = {TestsB = {Config = "Test"}} @@ -50,3 +61,13 @@ EmitObjectAccessCheck = false EnableRealtimeLeakCheck = false AllocStackTraceDepth = 0 COptimizationLevel = "O2" + +[Configs.TestFail.wasm32] +AllocType = "CRT" +EnableObjectDebugFlags = false +EmitObjectAccessCheck = false + +[Configs.Paranoid.wasm32] +AllocType = "CRT" +EnableObjectDebugFlags = false +EmitObjectAccessCheck = false diff --git a/IDEHelper/Tests/src/Append.bf b/IDEHelper/Tests/src/Append.bf index ddeff8bc..4af4c07e 100644 --- a/IDEHelper/Tests/src/Append.bf +++ b/IDEHelper/Tests/src/Append.bf @@ -92,6 +92,7 @@ namespace Tests Test.Assert(ptr[i] == data[i]); } +#if BF_ENABLE_OBJECT_DEBUG_FLAGS [Test] public static void Test() { @@ -129,5 +130,6 @@ namespace Tests Test.Assert(cf.mC == 234); cf.mB.Append('!', 2048); } +#endif } } diff --git a/IDEHelper/Tests/src/Reflection.bf b/IDEHelper/Tests/src/Reflection.bf index a66fa50c..aa64c9e3 100644 --- a/IDEHelper/Tests/src/Reflection.bf +++ b/IDEHelper/Tests/src/Reflection.bf @@ -259,6 +259,7 @@ namespace Tests Test.Assert(t.InstanceSize == 8); } +#if !BF_PLATFORM_WASM [Test] static void TestA() { @@ -683,5 +684,6 @@ namespace Tests fieldIdx++; } } +#endif } }