From b7b065855df95fd38eda929650ef60d64ddb62bc Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Thu, 6 Aug 2020 09:24:37 -0700 Subject: [PATCH] Start of wasm support --- BeefRT/rt/Internal.cpp | 12 ++ BeefRT/rt/ThreadLocalStorage.h | 4 +- BeefySysLib/Common.cpp | 4 +- BeefySysLib/platform/posix/PosixCommon.cpp | 8 +- BeefySysLib/platform/wasm/BFPlatform.cpp | 13 ++ BeefySysLib/platform/wasm/BFPlatform.h | 24 +++ BeefySysLib/platform/wasm/PlatformApp.h | 9 + BeefySysLib/platform/wasm/WasmCommon.cpp | 6 + BeefySysLib/platform/wasm/WasmCommon.h | 208 +++++++++++++++++++++ IDE/src/BuildContext.bf | 115 +++++++++++- IDE/src/IDEApp.bf | 15 +- IDE/src/Settings.bf | 5 + IDE/src/Workspace.bf | 17 +- IDEHelper/CMakeLists.txt | 7 + IDEHelper/Compiler/BfCompiler.cpp | 37 ++-- IDEHelper/Compiler/BfContext.cpp | 3 +- IDEHelper/Compiler/BfIRCodeGen.cpp | 7 + IDEHelper/Compiler/BfModule.cpp | 1 + IDEHelper/Compiler/BfSystem.h | 5 +- IDEHelper/IDEHelper.vcxproj | 4 +- IDEHelper/IDEHelper.vcxproj.user | 14 +- bin/build_wasm.bat | 4 + 22 files changed, 487 insertions(+), 35 deletions(-) create mode 100644 BeefySysLib/platform/wasm/BFPlatform.cpp create mode 100644 BeefySysLib/platform/wasm/BFPlatform.h create mode 100644 BeefySysLib/platform/wasm/PlatformApp.h create mode 100644 BeefySysLib/platform/wasm/WasmCommon.cpp create mode 100644 BeefySysLib/platform/wasm/WasmCommon.h create mode 100644 bin/build_wasm.bat diff --git a/BeefRT/rt/Internal.cpp b/BeefRT/rt/Internal.cpp index d2841b8c..3d269199 100644 --- a/BeefRT/rt/Internal.cpp +++ b/BeefRT/rt/Internal.cpp @@ -39,7 +39,9 @@ //#include "gc.h" #include "StompAlloc.h" #include "BeefySysLib/platform/PlatformHelper.h" +#ifndef BF_DISABLE_FFI #include "ffi.h" +#endif #include "Thread.h" #ifdef BF_PLATFORM_WINDOWS @@ -816,17 +818,27 @@ bool IO::Directory::Exists(char* fileName) void* bf::System::FFI::FFILIB::ClosureAlloc(intptr size, void** outFunc) { +#ifndef BF_DISABLE_FFI return ffi_closure_alloc(size, outFunc); +#else + return NULL; +#endif } bf::System::FFI::FFIResult bf::System::FFI::FFILIB::PrepCif(bf::System::FFI::FFILIB::FFICIF* cif, bf::System::FFI::FFIABI abi, int32 nargs, bf::System::FFI::FFIType* rtype, bf::System::FFI::FFIType** argTypes) { +#ifndef BF_DISABLE_FFI return (bf::System::FFI::FFIResult)ffi_prep_cif((ffi_cif*)cif, (ffi_abi)abi, nargs, (ffi_type*)rtype, (ffi_type**)argTypes); +#else + return (bf::System::FFI::FFIResult)0; +#endif } void bf::System::FFI::FFILIB::Call(bf::System::FFI::FFILIB::FFICIF* cif, void* funcPtr, void* rvalue, void** args) { +#ifndef BF_DISABLE_FFI ffi_call((ffi_cif*)cif, (void(*)())funcPtr, rvalue, args); +#endif } ////////////////////////////////////////////////////////////////////////// diff --git a/BeefRT/rt/ThreadLocalStorage.h b/BeefRT/rt/ThreadLocalStorage.h index 2caf6d6e..93c171d1 100644 --- a/BeefRT/rt/ThreadLocalStorage.h +++ b/BeefRT/rt/ThreadLocalStorage.h @@ -88,7 +88,7 @@ public: } }; -template > +/*template > class BfTLSStatic : public BfTLSStaticBase { public: @@ -147,4 +147,4 @@ public: return &mValueMap; } }; - +*/ \ No newline at end of file diff --git a/BeefySysLib/Common.cpp b/BeefySysLib/Common.cpp index 30474a5a..8bd5a04d 100644 --- a/BeefySysLib/Common.cpp +++ b/BeefySysLib/Common.cpp @@ -8,12 +8,12 @@ #ifndef BF_SMALL #define STB_SPRINTF_IMPLEMENTATION -#include "../third_party/stb/stb_sprintf.h" +#include "third_party/stb/stb_sprintf.h" #endif extern "C" { -#include "../third_party/utf8proc/utf8proc.h" +#include "third_party/utf8proc/utf8proc.h" } diff --git a/BeefySysLib/platform/posix/PosixCommon.cpp b/BeefySysLib/platform/posix/PosixCommon.cpp index 00ca2247..d6423ba6 100644 --- a/BeefySysLib/platform/posix/PosixCommon.cpp +++ b/BeefySysLib/platform/posix/PosixCommon.cpp @@ -19,9 +19,9 @@ #include #include "../PlatformInterface.h" #include "../PlatformHelper.h" -#include "../util/CritSect.h" -#include "../util/Dictionary.h" -#include "../util/Hash.h" +#include "../../util/CritSect.h" +#include "../../util/Dictionary.h" +#include "../../util/Hash.h" #ifdef BFP_HAS_EXECINFO #include #endif @@ -36,7 +36,7 @@ #endif #endif -#include "../third_party/stb/stb_sprintf.h" +#include "../../third_party/stb/stb_sprintf.h" #include #include diff --git a/BeefySysLib/platform/wasm/BFPlatform.cpp b/BeefySysLib/platform/wasm/BFPlatform.cpp new file mode 100644 index 00000000..8828d289 --- /dev/null +++ b/BeefySysLib/platform/wasm/BFPlatform.cpp @@ -0,0 +1,13 @@ +#include "Common.h" +#include "BFPlatform.h" +//#include +//#include +#include +#include +#include +#include +//#include +//#include +#include +#include + diff --git a/BeefySysLib/platform/wasm/BFPlatform.h b/BeefySysLib/platform/wasm/BFPlatform.h new file mode 100644 index 00000000..0c43c3ca --- /dev/null +++ b/BeefySysLib/platform/wasm/BFPlatform.h @@ -0,0 +1,24 @@ +#pragma once + +#define BFSTDCALL + +#include "WasmCommon.h" + +#define BF_PLATFORM_LINUX +#define BF_PLATFORM_POSIX +#define BF_PLATFORM_NAME "BF_PLATFORM_WASM" + +#define BF_IMPORT extern "C" + +#ifdef BFSYSLIB_DYNAMIC +#define BF_EXPORT extern "C" +#define BF_CALLTYPE +#else +#define BF_EXPORT extern "C" +#define BF_CALLTYPE +#define BF_RESOURCES_REL_DIR "../Resources" +#endif + +#define BF_DEBUG_BREAK() + +#include "../PlatformInterface.h" diff --git a/BeefySysLib/platform/wasm/PlatformApp.h b/BeefySysLib/platform/wasm/PlatformApp.h new file mode 100644 index 00000000..bc255f1a --- /dev/null +++ b/BeefySysLib/platform/wasm/PlatformApp.h @@ -0,0 +1,9 @@ +#pragma once + +#include "../../HeadlessApp.h" + +NS_BF_BEGIN; + +typedef HeadlessApp PlatformBFApp; + +NS_BF_END; \ No newline at end of file diff --git a/BeefySysLib/platform/wasm/WasmCommon.cpp b/BeefySysLib/platform/wasm/WasmCommon.cpp new file mode 100644 index 00000000..d901a121 --- /dev/null +++ b/BeefySysLib/platform/wasm/WasmCommon.cpp @@ -0,0 +1,6 @@ +#include "../posix/PosixCommon.cpp" + +extern "C" uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) +{ + return 0; +} diff --git a/BeefySysLib/platform/wasm/WasmCommon.h b/BeefySysLib/platform/wasm/WasmCommon.h new file mode 100644 index 00000000..2a973f6d --- /dev/null +++ b/BeefySysLib/platform/wasm/WasmCommon.h @@ -0,0 +1,208 @@ +#pragma once + +#ifdef __LP64__ +#define BF64 +#else +#define BF32 +#endif + +#define BOOST_DETAIL_NO_CONTAINER_FWD + +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define offsetof(type, member) __builtin_offsetof (type, member) + +extern "C" +{ +//#define FFI_BUILDING +//#include "third_party/libffi/x86_64-apple-darwin12.5.0/include/ffi.h" +} + +#define BF_ENDIAN_LITTLE + +#define _NOEXCEPT noexcept +#define NTAPI + +#define FFI_STDCALL FFI_DEFAULT_ABI +#define FFI_THISCALL FFI_DEFAULT_ABI +#define FFI_FASTCALL FFI_DEFAULT_ABI + +#define INVALID_SOCKET -1 + +typedef uint64_t uint64; +typedef uint32_t uint32; +typedef uint16_t uint16; +typedef uint8_t uint8; +typedef int64_t int64; +typedef int32_t int32; +typedef int16_t int16; +typedef int8_t int8; +typedef unsigned int uint; + +//#define BF_PLATFORM_SDL + +#define NOP +//#define BF_NOTHROW throw () +//#define BF_NOTHROW noexcept +#define BF_NOTHROW + +#ifdef BF64 +typedef int64 intptr; +typedef uint64 uintptr; +#else +typedef int32 intptr; +typedef uint32 uintptr; +#endif + +typedef wchar_t* BSTR; +typedef int HRESULT; +typedef uint8 BYTE; +typedef uint16 WORD; +typedef uint32 DWORD; +typedef int32 LONG; + +typedef pthread_key_t BFTlsKey; +typedef pthread_t BF_THREADID; +typedef pthread_t BF_THREADHANDLE; + +#define BF_HAS_TLS_DECLSPEC +#define BF_TLS_DECLSPEC thread_local + +//:int64 abs(int64 val); + +#define _stricmp stricmp +#define strnicmp strncasecmp + +struct IID +{ + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[ 8 ]; +}; + +typedef void* HANDLE; +typedef void* HMODULE; + +// We only need the stdcall attribute for x32? +//#define BFSTDCALL __attribute__((stdcall)) + +//#include "../notwin/NotWin.h" + +#ifdef DEBUG +#define _DEBUG +#endif + +#define NOT_IMPL throw "Unimplemented"; + +//ARM + +#if defined(__x86_64__) || defined(__i386__) +#define BF_FULL_MEMORY_FENCE() __asm__ __volatile__("mfence": : :"memory") +#define BF_SPINWAIT_NOP() __asm__ volatile ("pause\n" : : : "memory" ); +#else +#define BF_FULL_MEMORY_FENCE() __sync_synchronize() +#define BF_SPINWAIT_NOP() ((void) 0) +#endif + +#define BF_COMPILER_FENCE() __asm__ __volatile__("": : :"memory") +#define BF_THREAD_YIELD() sched_yield() + +#if defined _DEBUG || defined BF_DEBUG_ASSERTS +#define BF_ASSERT(_Expression) (void)( (!!(_Expression)) || (Beefy::BFFatalError(#_Expression, __FILE__, __LINE__), 0) ) +#else +#define BF_ASSERT(_Expression) (void)(0) +#endif + +#define BF_ASSERT_REL(_Expression) (void)( (!!(_Expression)) || (Beefy::BFFatalError(#_Expression, __FILE__, __LINE__), 0) ) +#define BF_FATAL(msg) (void) ((Beefy::BFFatalError(msg, __FILE__, __LINE__), 0) ) + +#if defined _DEBUG || defined BF_DEBUG_ASSERTS +#define BF_DBG_FATAL(msg) (void) ((Beefy::BFFatalError(msg, __FILE__, __LINE__), 0) ) +#else +#define BF_DBG_FATAL(msg) +#endif + +#define BF_NOINLINE __attribute__ ((noinline)) +#define BF_NAKED + +#define stricmp strcasecmp +#define _alloca alloca + +#define DIR_SEP_CHAR '/' +#define DIR_SEP_CHAR_ALT '\\' + +static char* itoa(int value, char* str, int base) +{ + if (base == 16) + sprintf(str, "%X", value); + else + sprintf(str, "%d", value); + return str; +} + +inline uint32 InterlockedCompareExchange(volatile uint32* dest, uint32 exch, uint32 comp) +{ + return __sync_val_compare_and_swap(dest, comp, exch); +} + +inline uint64 InterlockedCompareExchange64(volatile int64* dest, int64 exch, int64 comp) +{ + return __sync_val_compare_and_swap(dest, comp, exch); +} + +inline void* InterlockedCompareExchangePointer(void* volatile* dest, void* exch, void* comp) +{ + return __sync_val_compare_and_swap(dest, comp, exch); +} + +inline uint32 InterlockedExchange(volatile uint32* dest, uint32 val) +{ + return __sync_lock_test_and_set(dest, val); +} + +inline uint64 InterlockedExchange64(volatile int64* dest, int64 val) +{ + return __sync_lock_test_and_set(dest, val); +} + +inline uint32 InterlockedExchangeAdd(volatile uint32* dest, uint32 val) +{ + return __sync_add_and_fetch(dest, val); +} + +inline int32 InterlockedIncrement(volatile uint32* val) +{ + return __sync_add_and_fetch(val, 1); +} + +inline int64 InterlockedIncrement64(volatile int64* val) +{ + return __sync_add_and_fetch(val, 1); +} + +inline int32 InterlockedDecrement(volatile uint32* val) +{ + return __sync_add_and_fetch(val, -1); +} + +inline int64 InterlockedDecrement64(volatile int64* val) +{ + return __sync_add_and_fetch(val, -1); +} diff --git a/IDE/src/BuildContext.bf b/IDE/src/BuildContext.bf index 1ad37d42..8ab59b3a 100644 --- a/IDE/src/BuildContext.bf +++ b/IDE/src/BuildContext.bf @@ -527,6 +527,114 @@ namespace IDE return true; } + bool QueueProjectWasmLink(Project project, String targetPath, Workspace.Options workspaceOptions, Project.Options options, String objectsArg) + { + //bool isDebug = gApp.mConfigName.IndexOf("Debug", true) != -1; + + //bool isMinGW = false; + + //String error = scope String(); + + TestManager.ProjectInfo testProjectInfo = null; + if (gApp.mTestManager != null) + testProjectInfo = gApp.mTestManager.GetProjectInfo(project); + + bool isExe = (project.mGeneralOptions.mTargetType != Project.TargetType.BeefLib) || (testProjectInfo != null); + bool isDynLib = project.mGeneralOptions.mTargetType == Project.TargetType.BeefDynLib; + + if (isExe || isDynLib) + { + String linkLine = scope String(); + linkLine.Append("-o "); + IDEUtils.AppendWithOptionalQuotes(linkLine, targetPath); + linkLine.Append(" "); + + linkLine.Append(objectsArg); + + List libPaths = scope .(); + defer ClearAndDeleteItems(libPaths); + List depPaths = scope .(); + defer ClearAndDeleteItems(depPaths); + AddLinkDeps(project, options, workspaceOptions, linkLine, libPaths, depPaths); + + for (var libPath in libPaths) + { + IDEUtils.AppendWithOptionalQuotes(linkLine, libPath); + linkLine.Append(" "); + } + + if (project.mNeedsTargetRebuild) + { + if (File.Delete(targetPath) case .Err) + { + gApp.OutputLine("Failed to delete {0}", targetPath); + return false; + } + + if (options.mBuildOptions.mOtherLinkFlags.Length != 0) + { + var linkFlags = scope String(); + gApp.ResolveConfigString(gApp.mPlatformName, workspaceOptions, project, options, options.mBuildOptions.mOtherLinkFlags, "link flags", linkFlags); + linkLine.Append(linkFlags, " "); + } + + +#if BF_PLATFORM_WINDOWS + String compilerExePath = scope String(); + String llvmDir = scope String(IDEApp.sApp.mInstallDir); + IDEUtils.FixFilePath(llvmDir); + llvmDir.Append("llvm/"); + compilerExePath.Append(llvmDir, "bin/wasm-ld.exe"); +#else + String llvmDir = ""; + bool isWSL = false; + String compilerExePath = "wasm-ld"; +#endif + + + //compilerExePath.Set(@"C:\temp\emsdk\upstream\emscripten\emcc.bat"); + if (!gApp.mSettings.mEmscriptenPath.IsEmpty) + { + compilerExePath.Append(gApp.mSettings.mEmscriptenPath); + if ((!compilerExePath.EndsWith('\\')) && (!compilerExePath.EndsWith('/'))) + compilerExePath.Append("/"); + } + compilerExePath.Append(@"emcc.bat"); + //linkLine.Append(" c:\\Beef\\wasm\\BeefRT.a -s STRICT=1 -s USE_PTHREADS=1 -s ALIASING_FUNCTION_POINTERS=1 -s ASSERTIONS=0 -s DISABLE_EXCEPTION_CATCHING=0 -s DEMANGLE_SUPPORT=0 -s EVAL_CTORS=1 -s WASM=1 -s \"EXPORTED_FUNCTIONS=['_BeefMain','_BeefDone','_pthread_mutexattr_init','_pthread_mutex_init','_emscripten_futex_wake','_calloc','_sbrk']\""); + linkLine.Append(" c:\\Beef\\wasm\\BeefRT.a -s STRICT=1 -s USE_PTHREADS=1 -s ALIASING_FUNCTION_POINTERS=1 -s ASSERTIONS=0 -s DISABLE_EXCEPTION_CATCHING=0 -s DEMANGLE_SUPPORT=0 -s EVAL_CTORS=1 -s WASM=1"); + + String workingDir = scope String(); + if (!llvmDir.IsEmpty) + { + workingDir.Append(llvmDir, "bin"); + } + else + { + workingDir.Append(gApp.mInstallDir); + } + + //linkLine.Append(" --no-entry --export-all"); + + var runCmd = gApp.QueueRun(compilerExePath, linkLine, workingDir, .UTF8); + runCmd.mOnlyIfNotFailed = true; + var tagetCompletedCmd = new IDEApp.TargetCompletedCmd(project); + tagetCompletedCmd.mOnlyIfNotFailed = true; + gApp.mExecutionQueue.Add(tagetCompletedCmd); + + String logStr = scope String(); + logStr.AppendF("IDE Process {0}\r\n", Platform.BfpProcess_GetCurrentId()); + logStr.Append(linkLine); + String targetLogPath = scope String(targetPath, ".build.txt"); + if (Utils.WriteTextFile(targetLogPath, logStr) case .Err) + gApp.OutputErrorLine("Failed to write {}", targetLogPath); + + project.mLastDidBuild = true; + } + } + + return true; + } + public static void GetPdbPath(String targetPath, Workspace.Options workspaceOptions, Project.Options options, String outPdbPath) { int lastDotPos = targetPath.LastIndexOf('.'); @@ -1281,7 +1389,12 @@ namespace IDE objectsArg.Append(" "); } - if (workspaceOptions.mToolsetType == .GNU) + if (mPlatformType == .Wasm) + { + if (!QueueProjectWasmLink(project, targetPath, workspaceOptions, options, objectsArg)) + return false; + } + else if (workspaceOptions.mToolsetType == .GNU) { if ((options.mBuildOptions.mBuildKind == .StaticLib) || (options.mBuildOptions.mBuildKind == .DynamicLib)) { diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index f36d7691..12400e59 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -8422,7 +8422,7 @@ namespace IDE if (relocType == .NotSet) { - if (platform != .Windows) + if ((platform != .Windows) && (platform != .Wasm)) relocType = .PIC; } @@ -8931,6 +8931,9 @@ namespace IDE newString.Append(".dylib"); else newString.Append(".a"); + case .Wasm: + if (!newString.Contains('.')) + newString.Append(".html"); default: if (options.mBuildOptions.mBuildKind == .DynamicLib) newString.Append(".so"); @@ -8952,6 +8955,9 @@ namespace IDE case .macOS: if (project.mGeneralOptions.mTargetType == .BeefDynLib) newString.Append(".dylib"); + case .Wasm: + if (!newString.Contains('.')) + newString.Append(".html"); default: if (project.mGeneralOptions.mTargetType == .BeefDynLib) newString.Append(".so"); @@ -9005,6 +9011,11 @@ namespace IDE case .iOS: case .Linux: newString.AppendF("./{} -lpthread -ldl -Wl,-rpath -Wl,$ORIGIN", rtName); + case .Wasm: + newString.Append(mInstallDir); + newString.Append("Beef", IDEApp.sRTVersionStr, "RT"); + newString.Append((Workspace.PlatformType.GetPtrSizeByName(gApp.mPlatformName) == 4) ? "32" : "64"); + newString.Append("_wasm.lib"); default: } @@ -10062,6 +10073,8 @@ namespace IDE case .Linux: if (hostPlatform == .Windows) canCompile = true; // Use WSL + case .Wasm: + canCompile = true; default: } diff --git a/IDE/src/Settings.bf b/IDE/src/Settings.bf index d3eb70f6..771afcb7 100644 --- a/IDE/src/Settings.bf +++ b/IDE/src/Settings.bf @@ -902,6 +902,7 @@ namespace IDE public KeySettings mKeySettings = new .() ~ delete _; public RecentFiles mRecentFiles = new RecentFiles() ~ delete _; public String mWakaTimeKey = new .() ~ delete _; + public String mEmscriptenPath = new .() ~ delete _; public bool mEnableDevMode; public TutorialsFinished mTutorialsFinished = .(); @@ -946,6 +947,8 @@ namespace IDE mDebuggerSettings.Serialize(sd); using (sd.CreateObject("VisualStudio")) mVSSettings.Serialize(sd); + using (sd.CreateObject("Wasm")) + sd.Add("EmscriptenPath", mEmscriptenPath); using (sd.CreateObject("RecentFiles")) { @@ -1000,6 +1003,8 @@ namespace IDE mDebuggerSettings.Deserialize(sd); using (sd.Open("VisualStudio")) mVSSettings.Deserialize(sd); + using (sd.Open("Wasm")) + sd.Get("EmscriptenPath", mEmscriptenPath); using (sd.Open("RecentFiles")) { diff --git a/IDE/src/Workspace.bf b/IDE/src/Workspace.bf index 1d4fd821..a2ebf494 100644 --- a/IDE/src/Workspace.bf +++ b/IDE/src/Workspace.bf @@ -31,6 +31,7 @@ namespace IDE case macOS; case iOS; case Android; + case Wasm; public static PlatformType GetFromName(String name) { @@ -40,6 +41,7 @@ namespace IDE case "Linux32", "Linux64": return .Linux; case "macOS": return .macOS; case "iOS": return .iOS; + case "wasm32", "wasm64": return .Wasm; default: return TargetTriple.GetPlatformType(name); } @@ -90,6 +92,10 @@ namespace IDE outTriple.Append("x86_64-apple-macosx10.8.0"); case "iOS": outTriple.Append("arm64-apple-ios"); + case "wasm32": + outTriple.Append("wasm32-unknown-emscripten"); + case "wasm64": + outTriple.Append("wasm64-unknown-emscripten"); default: return false; } @@ -824,7 +830,14 @@ namespace IDE options.mEnableSideStack = false; options.mAllowHotSwapping = false; } - + + if (platformType == .Wasm) + { + options.mAllocType = .CRT; + options.mEnableObjectDebugFlags = false; + options.mEmitObjectAccessCheck = false; + } + options.mIncrementalBuild = !isRelease; options.mAllocStackTraceDepth = 1; @@ -1100,10 +1113,10 @@ namespace IDE configSelection.mConfig = new String(findConfig); configSelection.mPlatform = new String(findPlatform); options.mConfigSelections[project] = configSelection; + configSelection.mEnabled = true; } project.CreateConfig(findConfig, findPlatform); - configSelection.mEnabled = true; } } } diff --git a/IDEHelper/CMakeLists.txt b/IDEHelper/CMakeLists.txt index 49c64755..ba73ca3d 100644 --- a/IDEHelper/CMakeLists.txt +++ b/IDEHelper/CMakeLists.txt @@ -252,6 +252,13 @@ list(APPEND LLVM_LIBS ${LLVM_LIB}/libLLVMAArch64AsmParser.a ${LLVM_LIB}/libLLVMAArch64Disassembler.a + ${LLVM_LIB}/libLLVMWebAssemblyInfo.a + ${LLVM_LIB}/libLLVMWebAssemblyAsmPrinter.a + ${LLVM_LIB}/libLLVMWebAssemblyDesc.a + ${LLVM_LIB}/libLLVMWebAssemblyCodeGen.a + ${LLVM_LIB}/libLLVMWebAssemblyAsmParser.a + ${LLVM_LIB}/libLLVMWebAssemblyDisassembler.a + ${LLVM_LIB}/libLLVMSupport.a ${LLVM_LIB}/libLLVMDemangle.a) diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index c7eb7f75..182290bd 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -1374,7 +1374,8 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) CheckModuleStringRefs(module, bfModule, lastModuleRevision, foundStringIds, dllNameSet, dllMethods, stringValueEntries); if ((module->mHasForceLinkMarker) && - ((!isHotCompile) || (module->mHadHotObjectWrites))) + ((!isHotCompile) || (module->mHadHotObjectWrites)) && + (mOptions.mPlatformType != BfPlatformType_Wasm)) forceLinkValues.Add(bfModule->CreateForceLinkMarker(module, NULL)); } @@ -1593,7 +1594,8 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) { SmallVector paramTypes; auto dtorFuncType = bfModule->mBfIRBuilder->CreateFunctionType(voidType, paramTypes, false); - dtorFunc = bfModule->mBfIRBuilder->CreateFunction(dtorFuncType, BfIRLinkageType_External, "BfCallAllStaticDtors"); + String dtorName = (mOptions.mPlatformType == BfPlatformType_Wasm) ? "BeefDone" : "BfCallAllStaticDtors"; + dtorFunc = bfModule->mBfIRBuilder->CreateFunction(dtorFuncType, BfIRLinkageType_External, dtorName); bfModule->SetupIRMethod(NULL, dtorFunc, false); bfModule->mBfIRBuilder->SetActiveFunction(dtorFunc); auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true); @@ -1669,8 +1671,11 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) else { SmallVector paramTypes; - paramTypes.push_back(int32Type); - paramTypes.push_back(nullPtrType); + if (mOptions.mPlatformType != BfPlatformType_Wasm) + { + paramTypes.push_back(int32Type); + paramTypes.push_back(nullPtrType); + } mainFuncType = bfModule->mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, false); mainFunc = bfModule->mBfIRBuilder->CreateFunction(mainFuncType, BfIRLinkageType_External, "BeefMain"); bfModule->SetupIRMethod(NULL, mainFunc, false); @@ -1686,7 +1691,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) SmallVector paramTypes; paramTypes.push_back(int32Type); paramTypes.push_back(nullPtrType); - auto setCmdLineFuncType = bfModule->mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, false); + auto setCmdLineFuncType = bfModule->mBfIRBuilder->CreateFunctionType(voidType, paramTypes, false); auto setCmdLineFunc = bfModule->mBfIRBuilder->CreateFunction(setCmdLineFuncType, BfIRLinkageType_External, "BfpSystem_SetCommandLine"); bfModule->SetupIRMethod(NULL, setCmdLineFunc, false); @@ -1922,12 +1927,15 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) bfModule->mBfIRBuilder->SetInsertPoint(deinitBlock); } - bfModule->mBfIRBuilder->CreateCall(dtorFunc, SizedArray()); - - BfModuleMethodInstance shutdownMethod = bfModule->GetInternalMethod("Shutdown"); - if (shutdownMethod) + if (mOptions.mPlatformType != BfPlatformType_Wasm) { - bfModule->mBfIRBuilder->CreateCall(shutdownMethod.mFunc, SizedArray()); + bfModule->mBfIRBuilder->CreateCall(dtorFunc, SizedArray()); + + BfModuleMethodInstance shutdownMethod = bfModule->GetInternalMethod("Shutdown"); + if (shutdownMethod) + { + bfModule->mBfIRBuilder->CreateCall(shutdownMethod.mFunc, SizedArray()); + } } if (deinitSkipBlock) @@ -8726,7 +8734,7 @@ static BfPlatformType GetPlatform(StringView str) } bool hasLinux = false; - + for (auto elem : str.Split('-')) { if (elem == "linux") @@ -8739,6 +8747,8 @@ static BfPlatformType GetPlatform(StringView str) return BfPlatformType_iOS; else if ((elem == "android") || (elem == "androideabi")) return BfPlatformType_Android; + else if ((elem == "wasm32") || (elem == "wasm64")) + return BfPlatformType_Wasm; } if (hasLinux) @@ -8769,6 +8779,10 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_SetOptions(BfCompiler* bfCompiler, BfProje options->mMachineType = BfMachineType_AArch64; else if (options->mTargetTriple.StartsWith("armv")) options->mMachineType = BfMachineType_ARM; + else if (options->mTargetTriple.StartsWith("wasm32")) + options->mMachineType = BfMachineType_Wasm32; + else if (options->mTargetTriple.StartsWith("wasm64")) + options->mMachineType = BfMachineType_Wasm64; else options->mMachineType = BfMachineType_x64; // Default @@ -8870,4 +8884,3 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_ForceRebuild(BfCompiler* bfCompiler) bfCompiler->mOptions.mForceRebuildIdx++; } - diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index 9f147df5..e1f84c64 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -1688,7 +1688,8 @@ void BfContext::UpdateRevisedTypes() int wantPtrSize; if ((mCompiler->mOptions.mMachineType == BfMachineType_x86) | - (mCompiler->mOptions.mMachineType == BfMachineType_ARM)) + (mCompiler->mOptions.mMachineType == BfMachineType_ARM) || + (mCompiler->mOptions.mMachineType == BfMachineType_Wasm32)) wantPtrSize = 4; else wantPtrSize = 8; diff --git a/IDEHelper/Compiler/BfIRCodeGen.cpp b/IDEHelper/Compiler/BfIRCodeGen.cpp index a24c0eaf..16dd29cd 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.cpp +++ b/IDEHelper/Compiler/BfIRCodeGen.cpp @@ -4608,4 +4608,11 @@ void BfIRCodeGen::StaticInit() LLVMInitializeAArch64AsmPrinter(); //LLVMInitializeAArch64Parser(); //LLVMInitializeX86Disassembler(); + + LLVMInitializeWebAssemblyTargetInfo(); + LLVMInitializeWebAssemblyTarget(); + LLVMInitializeWebAssemblyTargetMC(); + LLVMInitializeWebAssemblyAsmPrinter(); + LLVMInitializeWebAssemblyAsmParser(); + LLVMInitializeWebAssemblyDisassembler(); } \ No newline at end of file diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index c9f3aea0..f8199653 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -6567,6 +6567,7 @@ BfIRFunction BfModule::GetBuiltInFunc(BfBuiltInFuncType funcTypeId) switch (funcTypeId) { case BfBuiltInFuncType_PrintF: + paramTypes.Add(nullPtrType); funcType = mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, true); func = mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_External, "PrintF"); break; diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index 128e08e3..ab075d0c 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -215,6 +215,7 @@ enum BfPlatformType BfPlatformType_macOS, BfPlatformType_iOS, BfPlatformType_Android, + BfPlatformType_Wasm }; enum BfMachineType @@ -223,7 +224,9 @@ enum BfMachineType BfMachineType_x86, BfMachineType_x64, BfMachineType_ARM, - BfMachineType_AArch64 + BfMachineType_AArch64, + BfMachineType_Wasm32, + BfMachineType_Wasm64, }; enum BfToolsetType diff --git a/IDEHelper/IDEHelper.vcxproj b/IDEHelper/IDEHelper.vcxproj index dad92d12..e0af052f 100644 --- a/IDEHelper/IDEHelper.vcxproj +++ b/IDEHelper/IDEHelper.vcxproj @@ -171,7 +171,7 @@ Windows DebugFull $(SolutionDir)\IDE\dist\$(TargetName).dll - rpcrt4.lib;cabinet.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;libcurl_a.lib;wininet.lib;LLVMMCDisassembler.lib;LLVMSupport.lib;LLVMMC.lib;LLVMObject.lib;LLVMCore.lib;LLVMBitReader.lib;LLVMAsmParser.lib;LLVMMCParser.lib;LLVMCodeGen.lib;LLVMTarget.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMSelectionDAG.lib;LLVMProfileData.lib;LLVMTransformUtils.lib;LLVMAnalysis.lib;LLVMAsmPrinter.lib;LLVMBitWriter.lib;LLVMVectorize.lib;LLVMipo.lib;LLVMInstrumentation.lib;LLVMDebugInfoDWARF.lib;LLVMDebugInfoPDB.lib;LLVMDebugInfoCodeView.lib;LLVMGlobalISel.lib;LLVMBinaryFormat.lib;LLVMLTO.lib;LLVMPasses.lib;LLVMLinker.lib;LLVMIRReader.lib;LLVMDemangle.lib;LLVMAggressiveInstCombine.lib;LLVMX86Info.lib;LLVMX86Utils.lib;LLVMX86AsmPrinter.lib;LLVMX86Desc.lib;LLVMX86CodeGen.lib;LLVMX86AsmParser.lib;LLVMX86Disassembler.lib;LLVMAArch64Info.lib;LLVMAArch64Utils.lib;LLVMAArch64AsmPrinter.lib;LLVMAArch64Desc.lib;LLVMAArch64CodeGen.lib;LLVMAArch64AsmParser.lib;LLVMAArch64Disassembler.lib;LLVMARMInfo.lib;LLVMARMUtils.lib;LLVMARMAsmPrinter.lib;LLVMARMDesc.lib;LLVMARMCodeGen.lib;LLVMARMAsmParser.lib;LLVMARMDisassembler.lib;%(AdditionalDependencies) + rpcrt4.lib;cabinet.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;libcurl_a.lib;wininet.lib;LLVMMCDisassembler.lib;LLVMSupport.lib;LLVMMC.lib;LLVMObject.lib;LLVMCore.lib;LLVMBitReader.lib;LLVMAsmParser.lib;LLVMMCParser.lib;LLVMCodeGen.lib;LLVMTarget.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMSelectionDAG.lib;LLVMProfileData.lib;LLVMTransformUtils.lib;LLVMAnalysis.lib;LLVMAsmPrinter.lib;LLVMBitWriter.lib;LLVMVectorize.lib;LLVMipo.lib;LLVMInstrumentation.lib;LLVMDebugInfoDWARF.lib;LLVMDebugInfoPDB.lib;LLVMDebugInfoCodeView.lib;LLVMGlobalISel.lib;LLVMBinaryFormat.lib;LLVMLTO.lib;LLVMPasses.lib;LLVMLinker.lib;LLVMIRReader.lib;LLVMDemangle.lib;LLVMAggressiveInstCombine.lib;LLVMX86Info.lib;LLVMX86Utils.lib;LLVMX86AsmPrinter.lib;LLVMX86Desc.lib;LLVMX86CodeGen.lib;LLVMX86AsmParser.lib;LLVMX86Disassembler.lib;LLVMAArch64Info.lib;LLVMAArch64Utils.lib;LLVMAArch64AsmPrinter.lib;LLVMAArch64Desc.lib;LLVMAArch64CodeGen.lib;LLVMAArch64AsmParser.lib;LLVMAArch64Disassembler.lib;LLVMARMInfo.lib;LLVMARMUtils.lib;LLVMARMAsmPrinter.lib;LLVMARMDesc.lib;LLVMARMCodeGen.lib;LLVMARMAsmParser.lib;LLVMARMDisassembler.lib;LLVMWebAssemblyInfo.lib;LLVMWebAssemblyAsmPrinter.lib;LLVMWebAssemblyDesc.lib;LLVMWebAssemblyCodeGen.lib;LLVMWebAssemblyAsmParser.lib;LLVMWebAssemblyDisassembler.lib;%(AdditionalDependencies) ..\extern\llvm_win64_8_0_1\Debug\lib; ..\extern\curl\builds\libcurl-vc15-x64-release-static-zlib-static-ipv6-sspi-winssl\lib;..\extern\curl\deps\lib;..\extern\jemalloc_win\x64\debug false $(SolutionDir)\IDE\dist\$(TargetName).lib @@ -230,7 +230,7 @@ true $(SolutionDir)\IDE\dist\$(TargetName).dll ..\extern\llvm_win64_8_0_1\Release\lib; ..\extern\curl\builds\libcurl-vc15-x64-release-static-zlib-static-ipv6-sspi-winssl\lib;..\extern\curl\deps\lib;..\extern\jemalloc_win\x64\release - rpcrt4.lib;cabinet.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;libcurl_a.lib;wininet.lib;LLVMMCDisassembler.lib;LLVMSupport.lib;LLVMMC.lib;LLVMObject.lib;LLVMCore.lib;LLVMBitReader.lib;LLVMAsmParser.lib;LLVMMCParser.lib;LLVMCodeGen.lib;LLVMTarget.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMSelectionDAG.lib;LLVMProfileData.lib;LLVMTransformUtils.lib;LLVMAnalysis.lib;LLVMAsmPrinter.lib;LLVMBitWriter.lib;LLVMVectorize.lib;LLVMipo.lib;LLVMInstrumentation.lib;LLVMDebugInfoDWARF.lib;LLVMDebugInfoPDB.lib;LLVMDebugInfoCodeView.lib;LLVMGlobalISel.lib;LLVMBinaryFormat.lib;LLVMLTO.lib;LLVMPasses.lib;LLVMLinker.lib;LLVMIRReader.lib;LLVMDemangle.lib;LLVMAggressiveInstCombine.lib;LLVMX86Info.lib;LLVMX86Utils.lib;LLVMX86AsmPrinter.lib;LLVMX86Desc.lib;LLVMX86CodeGen.lib;LLVMX86AsmParser.lib;LLVMX86Disassembler.lib;LLVMAArch64Info.lib;LLVMAArch64Utils.lib;LLVMAArch64AsmPrinter.lib;LLVMAArch64Desc.lib;LLVMAArch64CodeGen.lib;LLVMAArch64AsmParser.lib;LLVMAArch64Disassembler.lib;LLVMARMInfo.lib;LLVMARMUtils.lib;LLVMARMAsmPrinter.lib;LLVMARMDesc.lib;LLVMARMCodeGen.lib;LLVMARMAsmParser.lib;LLVMARMDisassembler.lib;%(AdditionalDependencies) + rpcrt4.lib;cabinet.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;libcurl_a.lib;wininet.lib;LLVMMCDisassembler.lib;LLVMSupport.lib;LLVMMC.lib;LLVMObject.lib;LLVMCore.lib;LLVMBitReader.lib;LLVMAsmParser.lib;LLVMMCParser.lib;LLVMCodeGen.lib;LLVMTarget.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMSelectionDAG.lib;LLVMProfileData.lib;LLVMTransformUtils.lib;LLVMAnalysis.lib;LLVMAsmPrinter.lib;LLVMBitWriter.lib;LLVMVectorize.lib;LLVMipo.lib;LLVMInstrumentation.lib;LLVMDebugInfoDWARF.lib;LLVMDebugInfoPDB.lib;LLVMDebugInfoCodeView.lib;LLVMGlobalISel.lib;LLVMBinaryFormat.lib;LLVMLTO.lib;LLVMPasses.lib;LLVMLinker.lib;LLVMIRReader.lib;LLVMDemangle.lib;LLVMAggressiveInstCombine.lib;LLVMX86Info.lib;LLVMX86Utils.lib;LLVMX86AsmPrinter.lib;LLVMX86Desc.lib;LLVMX86CodeGen.lib;LLVMX86AsmParser.lib;LLVMX86Disassembler.lib;LLVMAArch64Info.lib;LLVMAArch64Utils.lib;LLVMAArch64AsmPrinter.lib;LLVMAArch64Desc.lib;LLVMAArch64CodeGen.lib;LLVMAArch64AsmParser.lib;LLVMAArch64Disassembler.lib;LLVMARMInfo.lib;LLVMARMUtils.lib;LLVMARMAsmPrinter.lib;LLVMARMDesc.lib;LLVMARMCodeGen.lib;LLVMARMAsmParser.lib;LLVMARMDisassembler.lib;LLVMWebAssemblyInfo.lib;LLVMWebAssemblyAsmPrinter.lib;LLVMWebAssemblyDesc.lib;LLVMWebAssemblyCodeGen.lib;LLVMWebAssemblyAsmParser.lib;LLVMWebAssemblyDisassembler.lib;%(AdditionalDependencies) false true $(SolutionDir)\IDE\dist\$(TargetName).lib diff --git a/IDEHelper/IDEHelper.vcxproj.user b/IDEHelper/IDEHelper.vcxproj.user index c0a7a016..75967093 100644 --- a/IDEHelper/IDEHelper.vcxproj.user +++ b/IDEHelper/IDEHelper.vcxproj.user @@ -6,20 +6,20 @@ ..\IDE\dist\IDE.exe - -launch="C:\Beef\IDE\mintest\build\Debug_Win64\mintest\mintest.exe" -- These are the args + -proddir=c:\beef\ide\mintest WindowsLocalDebugger - $(SolutionDir)\dist\BeefIDE_d.exe - $(SolutionDir)\dist + $(SolutionDir)IDE\dist\BeefIDE_d.exe + $(SolutionDir)IDE\dist _NO_DEBUG_HEAP=1 - $(SolutionDir)\dist\IDE_bf.exe + $(SolutionDir)IDE\dist\BeefIDE.exe WindowsLocalDebugger - -proddir=c:\beef\IDE\Tests\Rando 2>StdErr.txt - $(SolutionDir)\dist + -proddir=c:\beef\IDE\mintest + $(SolutionDir)IDE\dist _NO_DEBUG_HEAP=1 - true + false \ No newline at end of file diff --git a/bin/build_wasm.bat b/bin/build_wasm.bat new file mode 100644 index 00000000..d3ffc43c --- /dev/null +++ b/bin/build_wasm.bat @@ -0,0 +1,4 @@ +mkdir ..\wasm +cd ..\wasm +call emcc ..\BeefRT\rt\Math.cpp ..\BeefRT\rt\Object.cpp ..\BeefRT\rt\Thread.cpp ..\BeefRT\rt\Internal.cpp ..\BeefySysLib\platform\wasm\WasmCommon.cpp ..\BeefySysLib\Common.cpp ..\BeefySysLib\util\String.cpp ..\BeefySysLib\util\UTF8.cpp ..\BeefySysLib\third_party\utf8proc\utf8proc.c -I..\ -I..\BeefySysLib -I..\BeefySysLib\platform\wasm -g -DBF_DISABLE_FFI -c -DBF_SMALL -s WASM=1 -s USE_PTHREADS=1 +emar r BeefRT.a Common.o Internal.o Math.o Object.o String.o Thread.o UTF8.o utf8proc.o WasmCommon.o \ No newline at end of file