Skip to content

Commit

Permalink
Merge pull request #5 from kelnishi/stack-optimization
Browse files Browse the repository at this point in the history
Stack optimization WACS-v0.1.4
  • Loading branch information
kelnishi authored Nov 15, 2024
2 parents ca0fb5b + 6023b69 commit 8871c97
Show file tree
Hide file tree
Showing 35 changed files with 876 additions and 446 deletions.
110 changes: 110 additions & 0 deletions Spec.Test/BindingTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// /*
// * Copyright 2024 Kelvin Nishikawa
// *
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// */

using System;
using System.IO;
using Wacs.Core;
using Wacs.Core.Runtime;
using Xunit;

namespace Spec.Test
{
public class BindingTests
{
[Fact]
public void BindStackBinder()
{
var runtime = new WasmRuntime();
runtime.BindHostFunction<hostInOut>(("env","bound_host"), BoundHost);
using var fileStream = new FileStream("../../../engine/binding.wasm", FileMode.Open);
var module = BinaryModuleParser.ParseWasm(fileStream);
var moduleInst = runtime.InstantiateModule(module);
runtime.RegisterModule("binding", moduleInst);

var fa = runtime.GetExportedFunction(("binding", "4x4"));
var invoker = runtime.CreateStackInvoker(fa);

var result = invoker(new Value[]{1, 1, 1f, 1.0});

Assert.Equal(1 * 2, (int)result[0]);
Assert.Equal(1 * 3, (long)result[1]);
Assert.Equal(1f * 4f, (float)result[2]);
Assert.Equal(1.0 * 5.0, (double)result[3]);
}

[Fact]
public void BindParamAndResultI32()
{
var runtime = new WasmRuntime();
runtime.BindHostFunction<hostInOut>(("env","bound_host"), BoundHost);
using var fileStream = new FileStream("../../../engine/binding.wasm", FileMode.Open);
var module = BinaryModuleParser.ParseWasm(fileStream);
var moduleInst = runtime.InstantiateModule(module);
runtime.RegisterModule("binding", moduleInst);

var fa = runtime.GetExportedFunction(("binding", "i32"));
var invoker = runtime.CreateInvoker<Func<int, int>>(fa);

Assert.Equal(1 * 2, invoker(1));
Assert.Equal(2 * 2, invoker(2));
Assert.Equal(3 * 2, invoker(3));
}

[Fact]
public void BindParamAndResultF32()
{
var runtime = new WasmRuntime();
runtime.BindHostFunction<hostInOut>(("env","bound_host"), BoundHost);
using var fileStream = new FileStream("../../../engine/binding.wasm", FileMode.Open);
var module = BinaryModuleParser.ParseWasm(fileStream);
var moduleInst = runtime.InstantiateModule(module);
runtime.RegisterModule("binding", moduleInst);

var fa = runtime.GetExportedFunction(("binding", "f32"));
var invoker = runtime.CreateInvoker<Func<float, float>>(fa);

Assert.Equal(1f * 2f, invoker(1f));
Assert.Equal(2f * 2f, invoker(2f));
Assert.Equal(3f * 2f, invoker(3f));
}

static int BoundHost(int a, out int b)
{
b = a;
int c = a * 2;
return c;
}

[Fact]
public void BindHostFunction()
{
var runtime = new WasmRuntime();
runtime.BindHostFunction<hostInOut>(("env","bound_host"), BoundHost);

using var fileStream = new FileStream("../../../engine/binding.wasm", FileMode.Open);
var module = BinaryModuleParser.ParseWasm(fileStream);
var moduleInst = runtime.InstantiateModule(module);
runtime.RegisterModule("binding", moduleInst);

var fa = runtime.GetExportedFunction(("binding", "call_host"));
var invoker = runtime.CreateInvoker<Func<int, int>>(fa);

Assert.Equal(10 + 20, invoker(10));
}

delegate int hostInOut(int a, out int b);
}
}
2 changes: 1 addition & 1 deletion Spec.Test/Spec.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<Authors>Kelvin Nishikawa</Authors>
<Company>Kelvin Nishikawa</Company>
<Product>Spec.Test</Product>
<AssemblyVersion>1.0.0</AssemblyVersion>
<AssemblyVersion>1.0.1</AssemblyVersion>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
Expand Down
16 changes: 3 additions & 13 deletions Spec.Test/WastJson/Actions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,11 @@ namespace Spec.Test.WastJson
public class InvokeAction : IAction
{
[JsonPropertyName("module")] public string Module { get; set; } = "";

// [JsonPropertyName("expected")] public List<Argument> Expected { get; set; } = new();
[JsonPropertyName("args")] public List<Argument> Args { get; set; } = new();
public ActionType Type => ActionType.Invoke;

[JsonPropertyName("field")] public string Field { get; set; } = "";

[JsonPropertyName("args")] public List<Argument> Args { get; set; } = new();

public override string ToString() => $"{Field} - Args: {string.Join(", ", Args)}";
public override string ToString() => $"{Field} - Args: {string.Join(", ", Args ?? new List<Argument>())}";

public Value[] Invoke(ref WasmRuntime runtime, ref Module? module)
{
Expand Down Expand Up @@ -68,20 +64,14 @@ public Value[] Invoke(ref WasmRuntime runtime, ref Module? module)
public class GetAction : IAction
{
[JsonPropertyName("expected")]
public List<Argument> Expected {
public List<Argument>? Expected {
get => null;
set => throw new NotSupportedException("GetAction does not support results.");
}

public ActionType Type => ActionType.Get;

[JsonPropertyName("field")] public string Field { get; set; } = "";

public List<Argument> Args
{
get => null;
set => throw new NotSupportedException("GetAction does not support arguments.");
}
}

public class ActionJsonConverter : JsonConverter<IAction>
Expand Down
20 changes: 10 additions & 10 deletions Spec.Test/WastJson/Argument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,30 @@ namespace Spec.Test.WastJson
public class Argument
{
[JsonPropertyName("type")]
public string Type { get; set; }
public string? Type { get; set; }

[JsonPropertyName("lane_type")]
public string LaneType { get; set; }
public string? LaneType { get; set; }

[JsonPropertyName("value")]
public object Value { get; set; }
public object? Value { get; set; }


public Value AsValue =>
Type switch
{
"i32" => new Value(ValType.I32, Value.ToString()),
"i64" => new Value(ValType.I64, Value.ToString()),
"f32" => new Value(ValType.F32, Value.ToString()),
"f64" => new Value(ValType.F64, Value.ToString()),
"i32" => new Value(ValType.I32, Value?.ToString()??""),
"i64" => new Value(ValType.I64, Value?.ToString()??""),
"f32" => new Value(ValType.F32, Value?.ToString()??""),
"f64" => new Value(ValType.F64, Value?.ToString()??""),
"v128" => ParseV128(Value),
"funcref" => new Value(ValType.Funcref, Value.ToString()),
"externref" => new Value(ValType.Externref, Value.ToString()),
"funcref" => new Value(ValType.Funcref, Value?.ToString()??"null"),
"externref" => new Value(ValType.Externref, Value?.ToString()??"null"),
_ => throw new ArgumentException($"Cannot parse value {Value} of type {Type}")
};


private Value ParseV128(object value)
private Value ParseV128(object? value)
{
if (value is JsonElement jsonElement && jsonElement.ValueKind == JsonValueKind.Array)
{
Expand Down
Loading

0 comments on commit 8871c97

Please sign in to comment.