diff --git a/BeefLibs/corlib/src/WebAssembly.bf b/BeefLibs/corlib/src/WebAssembly.bf new file mode 100644 index 00000000..b0d87a3a --- /dev/null +++ b/BeefLibs/corlib/src/WebAssembly.bf @@ -0,0 +1,121 @@ +#if BF_PLATFORM_WASM + +namespace System; + +using System.Interop; + +class WebAssembly +{ + [CLink] + private static extern int32 emscripten_asm_const_int(char8* code, char8* arg_sigs, ...); + [CLink] + private static extern void emscripten_asm_const_ptr(char8* code, char8* arg_sigs, ...); + [CLink] + private static extern double emscripten_asm_const_double(char8* code, char8* arg_sigs, ...); + + [Intrinsic(":add_string_to_section")] + private static extern char8* add_string_to_section(uint8* string, uint8* section); + + private static Span GetStringData(String value) + { + return StringView(value).ToRawData(); + } + + /** + * Returns the string added to the specified data section. + */ + private static char8* AddStringToSection(T0 value, T1 section) where T0 : const String where T1 : const String + { + static uint8[?] data = GetStringData(value); + static uint8[?] sectionStr = GetStringData(section); + + #unwarn + return add_string_to_section(&data, §ionStr); + } + + private static void GetArgSigInternal(Type t, String s) + { + switch(t) + { + case typeof(float): + s.Append('f'); + case typeof(double): + s.Append('d'); + case typeof(c_ulong): fallthrough; + case typeof(c_ulonglong): + case typeof(c_longlong): + case typeof(c_long): + s.Append('j'); + default: +#if BF_32_BIT + s.Append('i'); +#else + s.Append('p'); +#endif + } + } + + [Comptime] + static void JSGetArgSig(Type t, String s) + { + if(t.IsTuple) + { + int count = t.FieldCount; + for(int i = 0; i < count; i++) + { + var type = t.GetField(i).Get().FieldType; + GetArgSigInternal(type, s); + } + }else + GetArgSigInternal(t, s); + } + + private static String JSGetResultName(Type t) + { + if(t.IsPointer) + return "ptr"; + else if (t.IsFloatingPoint) + return "double"; + else + return "int"; + } + + [Comptime] + private static void GetArgString(String s) + { + Type type = typeof(T); + int fieldCount = 0; + if (type.IsTuple) + { + fieldCount = type.FieldCount; + for(int i = 0; i< fieldCount; i++) + { + if(i == fieldCount-1) + s.AppendF("p0.{}", i); + else + s.AppendF("p0.{}, ", i); + } + } + else + s.Append("p0"); + } + + private static String JSGetCallString() where TCall : const String + { + if (TCall == null) + return ""; + var argSigs = JSGetArgSig(typeof(T0), .. scope .()); + var argString = GetArgString(.. scope .()); + return new $"result = emscripten_asm_const_{JSGetResultName(typeof(TResult))}(AddStringToSection({TCall.Quote(.. scope .())}, \"em_asm\"), \"{argSigs}\", {argString});"; + } + + public static TResult JSCall(TCall callString, T0 p0) where TCall : const String + { + TResult result = default; + Compiler.Mixin(JSGetCallString()); + return result; + } +} + + +#endif diff --git a/IDEHelper/Compiler/BfIRCodeGen.cpp b/IDEHelper/Compiler/BfIRCodeGen.cpp index 6a81da38..d7bb63bb 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.cpp +++ b/IDEHelper/Compiler/BfIRCodeGen.cpp @@ -3076,40 +3076,42 @@ void BfIRCodeGen::HandleNextCmd() { case BfIRIntrinsic__PLATFORM: { - if (intrinsicData->mName == "em_asm_internal") + if (intrinsicData->mName == "add_string_to_section") { - llvm::StringRef strContent; + llvm::StringRef strContent[2]; llvm::ConstantDataArray* dataArray; - if (const llvm::ConstantExpr* ce = llvm::dyn_cast(args[0])) + + for (int i = 0; i < 2; i++) { - llvm::Value* firstOperand = ce->getOperand(0); - if (llvm::GlobalVariable* gv = llvm::dyn_cast(firstOperand)) + if (const llvm::ConstantExpr* ce = llvm::dyn_cast(args[i])) { - if (gv->getType()->isPointerTy()) + llvm::Value* firstOperand = ce->getOperand(0); + if (llvm::GlobalVariable* gv = llvm::dyn_cast(firstOperand)) { - if (dataArray = llvm::dyn_cast(gv->getInitializer())) + if (gv->getType()->isPointerTy()) { - strContent = dataArray->getAsString(); + if (dataArray = llvm::dyn_cast(gv->getInitializer())) + strContent[i] = dataArray->getAsString(); } } } + else + FatalError("Value is not ConstantExpr"); } - else - FatalError("Value is not ConstantExpr"); auto charType = llvm::IntegerType::get(*mLLVMContext, 8); - std::vector chars(strContent.size()); - for (unsigned int i = 0; i < strContent.size(); i++) + std::vector chars(strContent[0].size()); + for (unsigned int i = 0; i < strContent[0].size(); i++) { - chars[i] = llvm::ConstantInt::get(charType, strContent[i]);; + chars[i] = llvm::ConstantInt::get(charType, strContent[0][i]);; } chars.push_back(llvm::ConstantInt::get(charType, 0)); auto stringType = llvm::ArrayType::get(charType, chars.size()); auto globalVar = (llvm::GlobalVariable*)mLLVMModule->getOrInsertGlobal("", stringType); - globalVar->setSection("em_asm"); + globalVar->setSection(strContent[1]); globalVar->setInitializer(llvm::ConstantArray::get(stringType, chars)); globalVar->setConstant(true); globalVar->setLinkage(llvm::GlobalValue::LinkageTypes::ExternalLinkage);