public JSExpression MaybeReplaceMethodCall(MethodReference caller, MethodReference method, MethodInfo methodInfo, JSExpression thisExpression, JSExpression[] arguments, TypeReference resultType, bool explicitThis) { var typeSystem = method.Module.TypeSystem; var fullName = method.FullName; switch (fullName) { case "System.Double System.Math::Sqrt(System.Double)": return(new AbstractSExpression( "f64.sqrt", typeSystem.Double, arguments, isConstantIfArgumentsAre: true )); case "System.Double System.Math::Floor(System.Double)": return(new AbstractSExpression( "f64.floor", typeSystem.Double, arguments, isConstantIfArgumentsAre: true )); case "System.Double System.Math::Ceiling(System.Double)": return(new AbstractSExpression( "f64.ceil", typeSystem.Double, arguments, isConstantIfArgumentsAre: true )); case "System.Void Wasm.Test::Printf(System.String,System.Object[])": // HACK: Ignored for now return(new JSNullExpression()); case "System.Void Wasm.Test::Invoke(System.String,System.Object[])": { var literalName = (JSStringLiteral)arguments[0]; var argumentValues = UnpackArgsArray(arguments[1]); return(new InvokeExport( literalName.Value, argumentValues )); } case "System.Void Wasm.Test::AssertReturn(System.Object,System.String,System.Object[])": { var expected = arguments[0]; string methodName; if (!ExtractLiteral(arguments[1], out methodName)) { throw new Exception("Expected export name as arg1 of assertreturn"); } var invokeArguments = UnpackArgsArray(arguments[2]); return(new AssertReturn(expected, methodName, invokeArguments)); } case "System.Void Wasm.Heap::SetHeapSize(System.Int32)": { var td = caller.DeclaringType.Resolve(); var hs = WasmUtil.HeapSizes; if (hs.ContainsKey(td)) { throw new Exception("Heap size for type " + td.FullName + " already set"); } long heapSize; if (!ExtractLiteral(arguments[0], out heapSize)) { throw new ArgumentException("SetHeapSize's argument must be an int literal"); } hs.Add(td, (int)heapSize); return(new JSNullExpression()); } case "System.Int32 Wasm.HeapI32::get_Item(System.Int32)": case "System.Int32 Wasm.HeapI32::get_Item(System.Int32,System.Int32)": { JSExpression actualAddress; if (arguments.Length == 2) { actualAddress = Add(typeSystem, arguments[0], arguments[1]); } else { actualAddress = arguments[0]; } // HACK: Indices are in elements, not bytes var actualAddressBytes = Mul(typeSystem, actualAddress, JSLiteral.New(4)); return(new GetMemory(typeSystem.Int32, false, actualAddressBytes)); } case "System.Byte Wasm.HeapU8::get_Item(System.Int32)": case "System.Byte Wasm.HeapU8::get_Item(System.Int32,System.Int32)": { JSExpression actualAddress; if (arguments.Length == 2) { actualAddress = Add(typeSystem, arguments[0], arguments[1]); } else { actualAddress = arguments[0]; } return(new GetMemory(typeSystem.Byte, false, actualAddress)); } case "System.Void Wasm.HeapI32::set_Item(System.Int32,System.Int32)": case "System.Void Wasm.HeapI32::set_Item(System.Int32,System.Int32,System.Int32)": { JSExpression actualAddress; if (arguments.Length == 3) { actualAddress = Add(typeSystem, arguments[0], arguments[1]); } else { actualAddress = arguments[0]; } // HACK: Indices are in elements, not bytes var actualAddressBytes = Mul(typeSystem, actualAddress, JSLiteral.New(4)); return(new SetMemory(typeSystem.Int32, false, actualAddressBytes, arguments[arguments.Length - 1])); } case "System.Void Wasm.HeapU8::set_Item(System.Int32,System.Byte)": case "System.Void Wasm.HeapU8::set_Item(System.Int32,System.Int32,System.Byte)": { JSExpression actualAddress; if (arguments.Length == 3) { actualAddress = Add(typeSystem, arguments[0], arguments[1]); } else { actualAddress = arguments[0]; } return(new SetMemory(typeSystem.Byte, false, actualAddress, arguments[arguments.Length - 1])); } case "System.Char System.String::get_Chars(System.Int32)": { var actualAddress = Add(typeSystem, thisExpression, arguments[0]); return(new GetMemory( typeSystem.Byte, false, actualAddress )); } case "System.Int32 System.String::get_Length()": { return(new GetStringLength(thisExpression)); } case "System.Int32* Wasm.HeapI32::get_Base()": case "System.Byte* Wasm.HeapU8::get_Base()": { return(JSLiteral.DefaultValue(method.ReturnType)); } case "System.Void Wasm.Heap::SetStdout(System.String)": { // FIXME: Store the filename somewhere return(new JSNullExpression()); } case "System.Void Wasm.Heap::Write(System.Int32,System.Int32)": { return(new StdoutWrite(arguments[0], arguments[1])); } } if (false) { Console.WriteLine("// Treating method '{0}' as runtime call", fullName); } return(null); }