Explorar el Código

Add em_asm funtionality

hermansimensen hace 2 años
padre
commit
eeea06a22b
Se han modificado 2 ficheros con 137 adiciones y 14 borrados
  1. 121 0
      BeefLibs/corlib/src/WebAssembly.bf
  2. 16 14
      IDEHelper/Compiler/BfIRCodeGen.cpp

+ 121 - 0
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<uint8> GetStringData(String value)
+	{
+	    return StringView(value).ToRawData();
+	}
+
+	/**
+	* Returns the string added to the specified data section. 
+	*/
+	private static char8* AddStringToSection<T0, T1>(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, &sectionStr);
+	}
+
+	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<T>(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<TResult, TCall, T0>() where TCall : const String
+	{
+	    if (TCall == null)
+	        return "";
+	    var argSigs = JSGetArgSig(typeof(T0), .. scope .());
+		var argString = GetArgString<T0>(.. scope .());
+	    return new $"result = emscripten_asm_const_{JSGetResultName(typeof(TResult))}(AddStringToSection({TCall.Quote(.. scope .())}, \"em_asm\"), \"{argSigs}\", {argString});";
+	}
+
+	public static TResult JSCall<TResult, TCall, T0>(TCall callString, T0 p0) where TCall : const String
+	{
+	    TResult result = default;
+	    Compiler.Mixin(JSGetCallString<TResult, const TCall, T0>());
+	    return result;
+	}
+}
+
+
+#endif

+ 16 - 14
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<llvm::ConstantExpr>(args[0]))
+
+						for (int i = 0; i < 2; i++)
 						{
-							llvm::Value* firstOperand = ce->getOperand(0);
-							if (llvm::GlobalVariable* gv = llvm::dyn_cast<llvm::GlobalVariable>(firstOperand))
+							if (const llvm::ConstantExpr* ce = llvm::dyn_cast<llvm::ConstantExpr>(args[i]))
 							{
-								if (gv->getType()->isPointerTy())
+								llvm::Value* firstOperand = ce->getOperand(0);
+								if (llvm::GlobalVariable* gv = llvm::dyn_cast<llvm::GlobalVariable>(firstOperand))
 								{
-									if (dataArray = llvm::dyn_cast<llvm::ConstantDataArray>(gv->getInitializer()))
+									if (gv->getType()->isPointerTy())
 									{
-										strContent = dataArray->getAsString();
+										if (dataArray = llvm::dyn_cast<llvm::ConstantDataArray>(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<llvm::Constant*> chars(strContent.size());
-						for (unsigned int i = 0; i < strContent.size(); i++)
+						std::vector<llvm::Constant*> 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);