diff --git a/Wacs.Core/Instructions/Control.cs b/Wacs.Core/Instructions/Control.cs index a8838a9..0716c25 100644 --- a/Wacs.Core/Instructions/Control.cs +++ b/Wacs.Core/Instructions/Control.cs @@ -86,10 +86,11 @@ public override void Validate(IWasmValidationContext context) try { var funcType = context.Types.ResolveBlockType(Block.Type); - context.Assert(funcType, $"Invalid BlockType: {Block.Type}"); + context.Assert(funcType, "Invalid BlockType: {0}",Block.Type); //Check the parameters [t1*] and discard - context.OpStack.PopValues(funcType.ParameterTypes); + context.OpStack.PopValues(funcType.ParameterTypes, ref _aside); + _aside.Clear(); //ControlStack will push the values back on (Control Frame is our Label) context.PushControlFrame(BlockOp, funcType); @@ -102,7 +103,7 @@ public override void Validate(IWasmValidationContext context) _ = exc; //Types didn't hit context.Assert(false, - $"Instruction block was invalid. BlockType {Block.Type} did not exist in the Context."); + "Instruction block was invalid. BlockType {0} did not exist in the Context.",Block.Type); } } @@ -162,10 +163,11 @@ public override void Validate(IWasmValidationContext context) try { var funcType = context.Types.ResolveBlockType(Block.Type); - context.Assert(funcType, $"Invalid BlockType: {Block.Type}"); + context.Assert(funcType, "Invalid BlockType: {0}",Block.Type); //Check the parameters [t1*] and discard - context.OpStack.PopValues(funcType.ParameterTypes); + context.OpStack.PopValues(funcType.ParameterTypes, ref _aside); + _aside.Clear(); //ControlStack will push the values back on (Control Frame is our Label) context.PushControlFrame(LoopOp, funcType); @@ -178,7 +180,7 @@ public override void Validate(IWasmValidationContext context) _ = exc; //Types didn't hit context.Assert(false, - $"Instruciton loop invalid. BlockType {Block.Type} did not exist in the Context."); + "Instruction loop invalid. BlockType {0} did not exist in the Context.",Block.Type); } } @@ -241,13 +243,14 @@ public override void Validate(IWasmValidationContext context) try { var ifType = context.Types.ResolveBlockType(IfBlock.Type); - context.Assert(ifType, $"Invalid BlockType: {IfBlock.Type}"); + context.Assert(ifType, "Invalid BlockType: {0}",IfBlock.Type); //Pop the predicate context.OpStack.PopI32(); //Check the parameters [t1*] and discard - context.OpStack.PopValues(ifType.ParameterTypes); + context.OpStack.PopValues(ifType.ParameterTypes, ref _aside); + _aside.Clear(); //ControlStack will push the values back on (Control Frame is our Label) context.PushControlFrame(IfOp, ifType); @@ -273,7 +276,7 @@ public override void Validate(IWasmValidationContext context) _ = exc; //Types didn't hit context.Assert(false, - $"Instruciton loop invalid. BlockType {IfBlock.Type} did not exist in the Context."); + "Instruction loop invalid. BlockType {0} did not exist in the Context.",IfBlock.Type); } } @@ -345,8 +348,7 @@ public class InstElse : InstEnd public override void Validate(IWasmValidationContext context) { var frame = context.PopControlFrame(); - context.Assert(frame.Opcode == OpCode.If, - "Else terminated a non-If block"); + context.Assert(frame.Opcode == OpCode.If, "Else terminated a non-If block"); context.PushControlFrame(ElseOp, frame.Types); } } @@ -435,17 +437,18 @@ public class InstBranch : InstructionBase, IBranchInstruction public override ByteCode Op => OpCode.Br; private LabelIdx L; - + // @Spec 3.3.8.6. br l public override void Validate(IWasmValidationContext context) { context.Assert(context.ContainsLabel(L.Value), - $"Instruction br invalid. Could not branch to label {L}"); + "Instruction br invalid. Could not branch to label {0}",L); var nthFrame = context.ControlStack.PeekAt((int)L.Value); //Validate results, but leave them on the stack - context.OpStack.PopValues(nthFrame.LabelTypes); + context.OpStack.PopValues(nthFrame.LabelTypes, ref _aside); + _aside.Clear(); // if (!context.Unreachable) // nthFrame.ConditionallyReachable = true; @@ -530,12 +533,12 @@ public class InstBranchIf : InstructionBase, IBranchInstruction public override ByteCode Op => OpCode.BrIf; public LabelIdx L; - + // @Spec 3.3.8.7. br_if public override void Validate(IWasmValidationContext context) { context.Assert(context.ContainsLabel(L.Value), - $"Instruction br_if invalid. Could not branch to label {L}"); + "Instruction br_if invalid. Could not branch to label {0}",L); //Pop the predicate context.OpStack.PopI32(); @@ -545,7 +548,7 @@ public override void Validate(IWasmValidationContext context) // nthFrame.ConditionallyReachable = true; //Pop values like we branch - context.OpStack.PopValues(nthFrame.LabelTypes); + context.OpStack.PopValues(nthFrame.LabelTypes, ref _aside); //But actually, we don't, so push them back on. context.OpStack.PushResult(nthFrame.LabelTypes); } @@ -598,7 +601,7 @@ public override void Validate(IWasmValidationContext context) //Pop the switch context.OpStack.PopI32(); context.Assert(context.ContainsLabel(Ln.Value), - $"Instruction br_table invalid. Context did not contain Label {Ln}"); + "Instruction br_table invalid. Context did not contain Label {0}", Ln); var mthFrame = context.ControlStack.PeekAt((int)Ln.Value); var arity = mthFrame.LabelTypes.Arity; @@ -609,20 +612,21 @@ public override void Validate(IWasmValidationContext context) foreach (var lidx in Ls) { context.Assert(context.ContainsLabel(lidx.Value), - $"Instruction br_table invalid. Context did not contain Label {lidx}"); + "Instruction br_table invalid. Context did not contain Label {0}", lidx); var nthFrame = context.ControlStack.PeekAt((int)lidx.Value); context.Assert(nthFrame.LabelTypes.Arity == arity, - $"Instruction br_table invalid. Label {lidx} had different arity {nthFrame.LabelTypes.Arity} =/= {arity}"); + "Instruction br_table invalid. Label {0} had different arity {1} =/= {2}", lidx, nthFrame.LabelTypes.Arity,arity); // if (!context.Unreachable) // nthFrame.ConditionallyReachable = true; - var vals = context.OpStack.PopValues(nthFrame.LabelTypes); - context.OpStack.PushValues(vals); + context.OpStack.PopValues(nthFrame.LabelTypes, ref _aside); + context.OpStack.PushValues(_aside); } - context.OpStack.PopValues(mthFrame.LabelTypes); + context.OpStack.PopValues(mthFrame.LabelTypes, ref _aside); + _aside.Clear(); context.SetUnreachable(); } @@ -705,13 +709,13 @@ public class InstReturn : InstructionBase { public static readonly InstReturn Inst = new(); public override ByteCode Op => OpCode.Return; - + // @Spec 3.3.8.9. return public override void Validate(IWasmValidationContext context) { //keep the results for the block or function to validate - var vals = context.OpStack.PopValues(context.ReturnType); - context.OpStack.PushValues(vals); + context.OpStack.PopValues(context.ReturnType, ref _aside); + context.OpStack.PushValues(_aside); context.SetUnreachable(); } @@ -750,10 +754,11 @@ public bool IsBound(ExecContext context) public override void Validate(IWasmValidationContext context) { context.Assert(context.Funcs.Contains(X), - $"Instruction call was invalid. Function {X} was not in the Context."); + "Instruction call was invalid. Function {0} was not in the Context.",X); var func = context.Funcs[X]; var type = context.Types[func.TypeIndex]; - context.OpStack.PopValues(type.ParameterTypes); + context.OpStack.PopValues(type.ParameterTypes, ref _aside); + _aside.Clear(); context.OpStack.PushResult(type.ResultType); } @@ -851,16 +856,17 @@ public bool IsBound(ExecContext context) public override void Validate(IWasmValidationContext context) { context.Assert(context.Tables.Contains(X), - $"Instruction call_indirect was invalid. Table {X} was not in the Context."); + "Instruction call_indirect was invalid. Table {0} was not in the Context.",X); var tableType = context.Tables[X]; context.Assert(tableType.ElementType == ReferenceType.Funcref, - $"Instruction call_indirect was invalid. Table type was not funcref"); + "Instruction call_indirect was invalid. Table type was not funcref"); context.Assert(context.Types.Contains(Y), - $"Instruction call_indirect was invalid. Function type {Y} was not in the Context."); + "Instruction call_indirect was invalid. Function type {0} was not in the Context.",Y); var funcType = context.Types[Y]; context.OpStack.PopI32(); - context.OpStack.PopValues(funcType.ParameterTypes); + context.OpStack.PopValues(funcType.ParameterTypes, ref _aside); + _aside.Clear(); context.OpStack.PushResult(funcType.ResultType); } diff --git a/Wacs.Core/Instructions/GlobalVariable.cs b/Wacs.Core/Instructions/GlobalVariable.cs index bb8fe9c..0abbd7b 100644 --- a/Wacs.Core/Instructions/GlobalVariable.cs +++ b/Wacs.Core/Instructions/GlobalVariable.cs @@ -61,7 +61,7 @@ public override string RenderText(ExecContext? context) public override void Validate(IWasmValidationContext context) { context.Assert(context.Globals.Contains(Index), - $"Instruction global.get was invalid. Context Globals did not contain {Index}"); + "Instruction global.get was invalid. Context Globals did not contain {0}",Index); var globalType = context.Globals[Index].Type; context.OpStack.PushType(globalType.ContentType); } @@ -132,11 +132,11 @@ public override string RenderText(ExecContext? context) public override void Validate(IWasmValidationContext context) { context.Assert(context.Globals.Contains(Index), - $"Instruction global.set was invalid. Context Globals did not contain {Index}"); + "Instruction global.set was invalid. Context Globals did not contain {0}",Index); var global = context.Globals[Index]; var mut = global.Type.Mutability; context.Assert(mut == Mutability.Mutable, - $"Instruction global.set was invalid. Trying to set immutable global {Index}"); + "Instruction global.set was invalid. Trying to set immutable global {0}",Index); context.OpStack.PopType(global.Type.ContentType); } diff --git a/Wacs.Core/Instructions/InstructionBase.cs b/Wacs.Core/Instructions/InstructionBase.cs index f7199f6..c569741 100644 --- a/Wacs.Core/Instructions/InstructionBase.cs +++ b/Wacs.Core/Instructions/InstructionBase.cs @@ -14,6 +14,7 @@ // * limitations under the License. // */ +using System.Collections.Generic; using System.IO; using Wacs.Core.OpCodes; using Wacs.Core.Runtime; @@ -50,5 +51,7 @@ public abstract class InstructionBase : IInstruction public virtual IInstruction Parse(BinaryReader reader) => this; public virtual string RenderText(ExecContext? context) => Op.GetMnemonic(); + + protected static Stack _aside = new(); } } \ No newline at end of file diff --git a/Wacs.Core/Instructions/LocalVariable.cs b/Wacs.Core/Instructions/LocalVariable.cs index 7c41f25..0bc457d 100644 --- a/Wacs.Core/Instructions/LocalVariable.cs +++ b/Wacs.Core/Instructions/LocalVariable.cs @@ -62,7 +62,7 @@ public override string RenderText(ExecContext? context) public override void Validate(IWasmValidationContext context) { context.Assert(context.Locals.Contains(Index), - $"Instruction local.get was invalid. Context Locals did not contain {Index}"); + "Instruction local.get was invalid. Context Locals did not contain {0}",Index); var value = context.Locals.Get(Index); context.OpStack.PushType(value.Type); } @@ -126,7 +126,7 @@ public override string RenderText(ExecContext? context) public override void Validate(IWasmValidationContext context) { context.Assert(context.Locals.Contains(Index), - $"Instruction local.set was invalid. Context Locals did not contain {Index}"); + "Instruction local.set was invalid. Context Locals did not contain {0}",Index); var value = context.Locals.Get(Index); context.OpStack.PopType(value.Type); } @@ -191,7 +191,7 @@ public override string RenderText(ExecContext? context) public override void Validate(IWasmValidationContext context) { context.Assert(context.Locals.Contains(Index), - $"Instruction local.tee was invalid. Context Locals did not contain {Index}"); + "Instruction local.tee was invalid. Context Locals did not contain {0}",Index); var value = context.Locals.Get(Index); context.OpStack.PopType(value.Type); context.OpStack.PushType(value.Type); diff --git a/Wacs.Core/Instructions/Memory.cs b/Wacs.Core/Instructions/Memory.cs index 1394331..597b459 100644 --- a/Wacs.Core/Instructions/Memory.cs +++ b/Wacs.Core/Instructions/Memory.cs @@ -82,9 +82,9 @@ public InstMemoryLoad(ValType type, BitWidth width) => public override void Validate(IWasmValidationContext context) { context.Assert(context.Mems.Contains(M.M), - $"Instruction {Op.GetMnemonic()} failed with invalid context memory 0."); + "Instruction {0} failed with invalid context memory 0.",Op.GetMnemonic()); context.Assert(M.Align.LinearSize() <= WidthT.ByteSize(), - $"Instruction {Op.GetMnemonic()} failed with invalid alignment {M.Align.LinearSize()} <= {WidthT}/8"); + "Instruction {0} failed with invalid alignment {1} <= {2}/8",Op.GetMnemonic(),M.Align.LinearSize(),WidthT); context.OpStack.PopI32(); context.OpStack.PushType(Type); @@ -249,10 +249,9 @@ public IInstruction Immediate(MemArg m) public override void Validate(IWasmValidationContext context) { context.Assert(context.Mems.Contains(M.M), - $"Instruction {Op.GetMnemonic()} failed with invalid context memory 0."); + "Instruction {0} failed with invalid context memory 0.",Op.GetMnemonic()); context.Assert(M.Align.LinearSize() <= TWidth.ByteSize(), - - $"Instruction {Op.GetMnemonic()} failed with invalid alignment {M.Align.LinearSize()} <= {TWidth}/8"); + "Instruction {0} failed with invalid alignment {1} <= {2}/8",Op.GetMnemonic(),M.Align.LinearSize(),TWidth); //Pop parameters from right to left context.OpStack.PopType(Type); diff --git a/Wacs.Core/Instructions/MemoryBulk.cs b/Wacs.Core/Instructions/MemoryBulk.cs index 18604cf..5bba447 100644 --- a/Wacs.Core/Instructions/MemoryBulk.cs +++ b/Wacs.Core/Instructions/MemoryBulk.cs @@ -38,7 +38,7 @@ public class InstMemorySize : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Mems.Contains(M), - $"Instruction {Op.GetMnemonic()} failed with invalid context memory {M}."); + "Instruction {0} failed with invalid context memory {1}.",Op.GetMnemonic(),M); context.OpStack.PushI32(); } @@ -81,7 +81,7 @@ public class InstMemoryGrow : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Mems.Contains(M), - $"Instruction {Op.GetMnemonic()} failed with invalid context memory {M}."); + "Instruction {0} failed with invalid context memory {1}.",Op.GetMnemonic(),M); context.OpStack.PopI32(); context.OpStack.PushI32(); } @@ -140,10 +140,10 @@ public class InstMemoryInit : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Mems.Contains(Y), - $"Instruction {Op.GetMnemonic()} failed with invalid context memory {Y}."); + "Instruction {0} failed with invalid context memory {1}.",Op.GetMnemonic(),Y); context.Assert(context.Datas.Contains(X), - $"Instruction {Op.GetMnemonic()} failed with invalid context data {X}."); + "Instruction {0} failed with invalid context data {1}.",Op.GetMnemonic(), X); context.OpStack.PopI32(); context.OpStack.PopI32(); @@ -256,7 +256,7 @@ public class InstDataDrop : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Datas.Contains(X), - $"Instruction {Op.GetMnemonic()} failed with invalid context data {X}."); + "Instruction {0} failed with invalid context data {1}.",Op.GetMnemonic(),X); } // @Spec 4.4.7.13 @@ -303,9 +303,9 @@ public class InstMemoryCopy : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Mems.Contains(SrcX), - $"Instruction {Op.GetMnemonic()} failed with invalid context memory {SrcX}."); + "Instruction {0} failed with invalid context memory {1}.",Op.GetMnemonic(),SrcX); context.Assert(context.Mems.Contains(DstY), - $"Instruction {Op.GetMnemonic()} failed with invalid context memory {DstY}."); + "Instruction {0} failed with invalid context memory {1}.",Op.GetMnemonic(), DstY); context.OpStack.PopI32(); context.OpStack.PopI32(); @@ -426,7 +426,7 @@ public class InstMemoryFill : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Mems.Contains(X), - $"Instruction {Op.GetMnemonic()} failed with invalid context memory {X}."); + "Instruction {0} failed with invalid context memory {1}.",Op.GetMnemonic(),X); context.OpStack.PopI32(); context.OpStack.PopI32(); diff --git a/Wacs.Core/Instructions/Parametric.cs b/Wacs.Core/Instructions/Parametric.cs index b4ebb9b..23b9a9a 100644 --- a/Wacs.Core/Instructions/Parametric.cs +++ b/Wacs.Core/Instructions/Parametric.cs @@ -70,8 +70,7 @@ public override void Validate(IWasmValidationContext context) { if (WithTypes) { - context.Assert(Types.Length == 1, - $"Select instruction type must be of length 1"); + context.Assert(Types.Length == 1, "Select instruction type must be of length 1"); var type = Types[0]; context.OpStack.PopI32(); context.OpStack.PopType(type); @@ -84,7 +83,7 @@ public override void Validate(IWasmValidationContext context) Value val2 = context.OpStack.PopAny(); Value val1 = context.OpStack.PopAny(); context.Assert(val1.Type.IsCompatible(val2.Type), - $"Select instruction expected matching types on the stack: {val1.Type} == {val2.Type}"); + "Select instruction expected matching types on the stack: {0} == {1}",val1.Type,val2.Type); if (!context.Attributes.Configure_RefTypes) { diff --git a/Wacs.Core/Instructions/Reference.cs b/Wacs.Core/Instructions/Reference.cs index 1f8ff18..3d92c47 100644 --- a/Wacs.Core/Instructions/Reference.cs +++ b/Wacs.Core/Instructions/Reference.cs @@ -76,12 +76,12 @@ public class InstRefFunc : InstructionBase, IConstInstruction public override void Validate(IWasmValidationContext context) { context.Assert(context.Funcs.Contains(FunctionIndex), - $"Instruction ref.func is invalid. Function {FunctionIndex} was not in the context."); + "Instruction ref.func is invalid. Function {0} was not in the context.",FunctionIndex); //Seems like C.Refs isn't strictly necessary since FunctionSpace collects all the references var func = context.Funcs[FunctionIndex]; context.Assert(func.IsFullyDeclared, - $"Instruction ref.func is invalid. Function {FunctionIndex} is not fully declared in the module."); + "Instruction ref.func is invalid. Function {0} is not fully declared in the module.",FunctionIndex); context.OpStack.PushFuncref(Value.NullFuncRef); } diff --git a/Wacs.Core/Instructions/SIMD/VLaneOp.cs b/Wacs.Core/Instructions/SIMD/VLaneOp.cs index 25eade8..c7cd6bf 100644 --- a/Wacs.Core/Instructions/SIMD/VLaneOp.cs +++ b/Wacs.Core/Instructions/SIMD/VLaneOp.cs @@ -176,22 +176,22 @@ private static ValidationDelegate ValidateFromLane(V128Shape shape) => switch (shape) { case V128Shape.I8x16: - context.Assert(l < 16, $"Instruction {op.GetMnemonic()} was invalid. Target Lane out of bounds."); + context.Assert(l < 16, "Instruction {0} was invalid. Target Lane out of bounds.", op.GetMnemonic()); break; case V128Shape.I16x8: - context.Assert(l < 8, $"Instruction {op.GetMnemonic()} was invalid. Target Lane out of bounds."); + context.Assert(l < 8, "Instruction {0} was invalid. Target Lane out of bounds.", op.GetMnemonic()); break; case V128Shape.I32x4: - context.Assert(l < 4, $"Instruction {op.GetMnemonic()} was invalid. Target Lane out of bounds."); + context.Assert(l < 4, "Instruction {0} was invalid. Target Lane out of bounds.", op.GetMnemonic()); break; case V128Shape.I64x2: - context.Assert(l < 2, $"Instruction {op.GetMnemonic()} was invalid. Target Lane out of bounds."); + context.Assert(l < 2, "Instruction {0} was invalid. Target Lane out of bounds.", op.GetMnemonic()); break; case V128Shape.F32x4: - context.Assert(l < 4, $"Instruction {op.GetMnemonic()} was invalid. Target Lane out of bounds."); + context.Assert(l < 4, "Instruction {0} was invalid. Target Lane out of bounds.", op.GetMnemonic()); break; case V128Shape.F64x2: - context.Assert(l < 2, $"Instruction {op.GetMnemonic()} was invalid. Target Lane out of bounds."); + context.Assert(l < 2, "Instruction {0} was invalid. Target Lane out of bounds.", op.GetMnemonic()); break; default: throw new InvalidOperationException("Unsupported lane shape"); } @@ -216,27 +216,27 @@ private static ValidationDelegate ValidateToLane(V128Shape shape) => switch (shape) { case V128Shape.I8x16: - context.Assert(l < 16, $"Instruction {op.GetMnemonic()} was invalid. Target Lane out of bounds."); + context.Assert(l < 16, "Instruction {0} was invalid. Target Lane out of bounds.", op.GetMnemonic()); context.OpStack.PopI32(); break; case V128Shape.I16x8: - context.Assert(l < 8, $"Instruction {op.GetMnemonic()} was invalid. Target Lane out of bounds."); + context.Assert(l < 8, "Instruction {0} was invalid. Target Lane out of bounds.", op.GetMnemonic()); context.OpStack.PopI32(); break; case V128Shape.I32x4: - context.Assert(l < 4, $"Instruction {op.GetMnemonic()} was invalid. Target Lane out of bounds."); + context.Assert(l < 4, "Instruction {0} was invalid. Target Lane out of bounds.", op.GetMnemonic()); context.OpStack.PopI32(); break; case V128Shape.I64x2: - context.Assert(l < 2, $"Instruction {op.GetMnemonic()} was invalid. Target Lane out of bounds."); + context.Assert(l < 2, "Instruction {0} was invalid. Target Lane out of bounds.", op.GetMnemonic()); context.OpStack.PopI64(); break; case V128Shape.F32x4: - context.Assert(l < 4, $"Instruction {op.GetMnemonic()} was invalid. Target Lane out of bounds."); + context.Assert(l < 4, "Instruction {0} was invalid. Target Lane out of bounds.", op.GetMnemonic()); context.OpStack.PopF32(); break; case V128Shape.F64x2: - context.Assert(l < 2, $"Instruction {op.GetMnemonic()} was invalid. Target Lane out of bounds."); + context.Assert(l < 2, "Instruction {0} was invalid. Target Lane out of bounds.", op.GetMnemonic()); context.OpStack.PopF64(); break; default: throw new InvalidOperationException("Unsupported lane shape"); diff --git a/Wacs.Core/Instructions/SIMD/VMemory.cs b/Wacs.Core/Instructions/SIMD/VMemory.cs index f9cde2b..f365044 100644 --- a/Wacs.Core/Instructions/SIMD/VMemory.cs +++ b/Wacs.Core/Instructions/SIMD/VMemory.cs @@ -63,9 +63,9 @@ public InstMemoryLoadMxN(BitWidth width, int count) => public override void Validate(IWasmValidationContext context) { context.Assert(context.Mems.Contains(M.M), - $"Instruction {Op.GetMnemonic()} failed with invalid context memory 0."); + "Instruction {0} failed with invalid context memory 0.",Op.GetMnemonic()); context.Assert(M.Align.LinearSize() <= WidthT.ByteSize() * CountN, - $"Instruction {Op.GetMnemonic()} failed with invalid alignment {M.Align.LinearSize()} <= {WidthT}/8"); + "Instruction {0} failed with invalid alignment {1} <= {2}/8",Op.GetMnemonic(),M.Align.LinearSize(),WidthT); context.OpStack.PopI32(); context.OpStack.PushV128(); @@ -169,9 +169,9 @@ public class InstMemoryLoadSplat : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Mems.Contains(M.M), - $"Instruction {Op.GetMnemonic()} failed with invalid context memory 0."); + "Instruction {0} failed with invalid context memory 0.",Op.GetMnemonic()); context.Assert(M.Align.LinearSize() <= WidthN.ByteSize(), - $"Instruction {Op.GetMnemonic()} failed with invalid alignment {M.Align} <= {BitWidth.V128}/8"); + "Instruction {0} failed with invalid alignment {1} <= {2}/8",Op.GetMnemonic(),M.Align,BitWidth.V128); context.OpStack.PopI32(); context.OpStack.PushV128(); @@ -275,9 +275,9 @@ public class InstMemoryLoadZero : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Mems.Contains(M.M), - $"Instruction {Op.GetMnemonic()} failed with invalid context memory 0."); + "Instruction {0} failed with invalid context memory 0.",Op.GetMnemonic()); context.Assert(M.Align.LinearSize() <= BitWidth.V128.ByteSize(), - $"Instruction {Op.GetMnemonic()} failed with invalid alignment {M.Align.LinearSize()} <= {BitWidth.V128}/8"); + "Instruction {0} failed with invalid alignment {1} <= {2}/8",Op.GetMnemonic(),M.Align.LinearSize(),BitWidth.V128); context.OpStack.PopI32(); context.OpStack.PushV128(); @@ -374,12 +374,12 @@ public class InstMemoryLoadLane : InstructionBase /// public override void Validate(IWasmValidationContext context) { - context.Assert(X < 128/WidthN.BitSize(), - $"Instruction {Op.GetMnemonic()} failed with invalid laneidx {X} <= {128/WidthN.BitSize()}"); + context.Assert(X < 128 / WidthN.BitSize(), + "Instruction {0} failed with invalid laneidx {1} <= {2}", Op.GetMnemonic(), X, 128 / WidthN.BitSize()); context.Assert(context.Mems.Contains(M.M), - $"Instruction {Op.GetMnemonic()} failed with invalid context memory 0."); + "Instruction {0} failed with invalid context memory 0.", Op.GetMnemonic()); context.Assert(M.Align.LinearSize() <= WidthN.ByteSize(), - $"Instruction {Op.GetMnemonic()} failed with invalid alignment {M.Align.LinearSize()} <= {WidthN}/8"); + "Instruction {0} failed with invalid alignment {1} <= {2}/8", Op.GetMnemonic(), M.Align.LinearSize(), WidthN); context.OpStack.PopV128(); context.OpStack.PopI32(); @@ -488,13 +488,12 @@ public IInstruction Immediate(MemArg m) /// public override void Validate(IWasmValidationContext context) { - context.Assert(X < 128/WidthN.BitSize(), - $"Instruction {Op.GetMnemonic()} failed with invalid laneidx {X} <= {128/WidthN.BitSize()}"); + context.Assert(X < 128 / WidthN.BitSize(), + "Instruction {0} failed with invalid laneidx {1} <= {2}", Op.GetMnemonic(), X, 128 / WidthN.BitSize()); context.Assert(context.Mems.Contains(M.M), - $"Instruction {Op.GetMnemonic()} failed with invalid context memory 0."); + "Instruction {0} failed with invalid context memory 0.", Op.GetMnemonic()); context.Assert(M.Align.LinearSize() <= WidthN.ByteSize(), - $"Instruction {Op.GetMnemonic()} failed with invalid alignment {M.Align.LinearSize()} <= {WidthN}/8"); - + "Instruction {0} failed with invalid alignment {1} <= {2}/8", Op.GetMnemonic(), M.Align.LinearSize(), WidthN); context.OpStack.PopV128(); context.OpStack.PopI32(); } diff --git a/Wacs.Core/Instructions/SIMD/ViShuffleOp.cs b/Wacs.Core/Instructions/SIMD/ViShuffleOp.cs index 8174a5a..a29dcdd 100644 --- a/Wacs.Core/Instructions/SIMD/ViShuffleOp.cs +++ b/Wacs.Core/Instructions/SIMD/ViShuffleOp.cs @@ -32,7 +32,7 @@ public override void Validate(IWasmValidationContext context) for (int i = 0; i < 16; ++i) { context.Assert(X[(byte)i] < 32, - $"Instruction {Op.GetMnemonic()} was invalid. Lane {i} ({X[(byte)i]}) was >= 32."); + "Instruction {0} was invalid. Lane {1} ({2}) was >= 32.",Op.GetMnemonic(),i,X[(byte)i]); } context.OpStack.PopV128(); diff --git a/Wacs.Core/Instructions/Table.cs b/Wacs.Core/Instructions/Table.cs index 3b2faf7..608feaf 100644 --- a/Wacs.Core/Instructions/Table.cs +++ b/Wacs.Core/Instructions/Table.cs @@ -36,7 +36,7 @@ public class InstTableGet : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Tables.Contains(X), - $"Instruction table.get failed to get table {X} from context"); + "Instruction table.get failed to get table {0} from context",X); var type = context.Tables[X]; context.OpStack.PopI32(); context.OpStack.PushType(type.ElementType.StackType()); @@ -96,7 +96,7 @@ public class InstTableSet : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Tables.Contains(X), - $"Instruction table.set failed to get table {X} from context"); + "Instruction table.set failed to get table {0} from context", X); var type = context.Tables[X]; context.OpStack.PopType(type.ElementType.StackType()); context.OpStack.PopI32(); @@ -160,13 +160,13 @@ public class InstTableInit : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Tables.Contains(X), - $"Instruction table.init is invalid. Table {X} not in the Context."); + "Instruction table.init is invalid. Table {0} not in the Context.", X); var t1 = context.Tables[X]; context.Assert(context.Elements.Contains(Y), - $"Instruction table.init is invalid. Element {Y} not in the Context."); + "Instruction table.init is invalid. Element {0} not in the Context.",Y); var t2 = context.Elements[Y]; context.Assert(t1.ElementType == t2.Type, - $"Instruction table.init is invalid. Type mismatch {t1.ElementType} != {t2.Type}"); + "Instruction table.init is invalid. Type mismatch {0} != {1}",t1.ElementType,t2.Type); context.OpStack.PopI32(); context.OpStack.PopI32(); context.OpStack.PopI32(); @@ -275,7 +275,7 @@ public class InstElemDrop : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Elements.Contains(X), - $"Instruction elem.drop is invalid. Element {X} was not in the Context"); + "Instruction elem.drop is invalid. Element {0} was not in the Context",X); } // @Spec 4.4.6.8. elem.drop x @@ -321,13 +321,13 @@ public class InstTableCopy : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Tables.Contains(DstX), - $"Instruction table.copy failed. Table index {DstX} does not exist in Context"); + "Instruction table.copy failed. Table index {0} does not exist in Context",DstX); var t1 = context.Tables[DstX]; context.Assert(context.Tables.Contains(SrcY), - $"Instruction table.copy failed. Table index {SrcY} does not exist in Context"); + "Instruction table.copy failed. Table index {0} does not exist in Context",SrcY); var t2 = context.Tables[SrcY]; context.Assert(t1.ElementType == t2.ElementType, - $"Instruction table.copy failed. Table type mismatch {t1.ElementType} != {t2.ElementType}"); + "Instruction table.copy failed. Table type mismatch {0} != {1}",t1.ElementType,t2.ElementType); context.OpStack.PopI32(); context.OpStack.PopI32(); context.OpStack.PopI32(); @@ -446,7 +446,7 @@ public class InstTableGrow : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Tables.Contains(X), - $"Instruction table.grow failed to get table {X} from context"); + "Instruction table.grow failed to get table {0} from context",X); var type = context.Tables[X]; context.OpStack.PopI32(); context.OpStack.PopType(type.ElementType.StackType()); @@ -513,7 +513,7 @@ public class InstTableSize : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Tables.Contains(X), - $"Instruction table.set failed to get table {X} from context"); + "Instruction table.set failed to get table {0} from context",X); context.OpStack.PushI32(); } @@ -558,7 +558,7 @@ public class InstTableFill : InstructionBase public override void Validate(IWasmValidationContext context) { context.Assert(context.Tables.Contains(X), - $"Instruction table.set failed to get table {X} from context"); + "Instruction table.set failed to get table {0} from context",X); var type = context.Tables[X]; context.OpStack.PopI32(); context.OpStack.PopType(type.ElementType.StackType()); diff --git a/Wacs.Core/Instructions/TailCall.cs b/Wacs.Core/Instructions/TailCall.cs index c34132e..f7308ad 100644 --- a/Wacs.Core/Instructions/TailCall.cs +++ b/Wacs.Core/Instructions/TailCall.cs @@ -46,16 +46,17 @@ public bool IsBound(ExecContext context) public override void Validate(IWasmValidationContext context) { //Return - var vals = context.OpStack.PopValues(context.ReturnType); - context.OpStack.PushValues(vals); + context.OpStack.PopValues(context.ReturnType, ref _aside); + context.OpStack.PushValues(_aside); context.SetUnreachable(); //Call context.Assert(context.Funcs.Contains(X), - $"Instruction call was invalid. Function {X} was not in the Context."); + "Instruction call was invalid. Function {0} was not in the Context.",X); var func = context.Funcs[X]; var type = context.Types[func.TypeIndex]; - context.OpStack.PopValues(type.ParameterTypes); + context.OpStack.PopValues(type.ParameterTypes, ref _aside); + _aside.Clear(); context.OpStack.PushResult(type.ResultType); } @@ -167,22 +168,23 @@ public bool IsBound(ExecContext context) public override void Validate(IWasmValidationContext context) { //Return - var vals = context.OpStack.PopValues(context.ReturnType); - context.OpStack.PushValues(vals); + context.OpStack.PopValues(context.ReturnType, ref _aside); + context.OpStack.PushValues(_aside); context.SetUnreachable(); //Call Indirect context.Assert(context.Tables.Contains(X), - $"Instruction call_indirect was invalid. Table {X} was not in the Context."); + "Instruction call_indirect was invalid. Table {0} was not in the Context.",X); var tableType = context.Tables[X]; context.Assert(tableType.ElementType == ReferenceType.Funcref, - $"Instruction call_indirect was invalid. Table type was not funcref"); + "Instruction call_indirect was invalid. Table type was not funcref"); context.Assert(context.Types.Contains(Y), - $"Instruction call_indirect was invalid. Function type {Y} was not in the Context."); + "Instruction call_indirect was invalid. Function type {0} was not in the Context.",Y); var funcType = context.Types[Y]; context.OpStack.PopI32(); - context.OpStack.PopValues(funcType.ParameterTypes); + context.OpStack.PopValues(funcType.ParameterTypes, ref _aside); + _aside.Clear(); context.OpStack.PushResult(funcType.ResultType); } diff --git a/Wacs.Core/Modules/Sections/StackCalculator.cs b/Wacs.Core/Modules/Sections/StackCalculator.cs index b0534b6..c521d35 100644 --- a/Wacs.Core/Modules/Sections/StackCalculator.cs +++ b/Wacs.Core/Modules/Sections/StackCalculator.cs @@ -16,6 +16,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using Wacs.Core.OpCodes; @@ -68,15 +69,13 @@ public void PushValues(Stack vals) { public Value PopType(ValType type) => _context.Pop(type); public Value PopAny() => _context.Pop(ValType.Nil); - public Stack PopValues(ResultType types) + public void PopValues(ResultType types, ref Stack aside) { - var aside = new Stack(); foreach (var type in types.Types.Reverse()) { var stackType = PopAny(); aside.Push(stackType); } - return aside; } public void ReturnResults(ResultType types) @@ -113,6 +112,8 @@ public void PopValues(ResultType types, bool keep = true) public class StackCalculator: IWasmValidationContext { + private static readonly object NonNull = new(); + public StackCalculator(ModuleInstance moduleInst, Module.Function func) { Types = new TypesSpace(moduleInst.Repr); @@ -194,13 +195,14 @@ public void PushControlFrame(ByteCode opCode, FunctionType types) OpStack.PushResult(types.ParameterTypes); } + private static Stack _aside = new(); public ValidationControlFrame PopControlFrame() { if (ControlStack.Count == 0) throw new InvalidDataException("Control Stack underflow"); - //Check to make sure we have the correct results - OpStack.PopValues(ControlFrame.EndTypes); + OpStack.PopValues(ControlFrame.EndTypes, ref _aside); + _aside.Clear(); //Reset the stack stackHeight = ControlFrame.Height; @@ -213,10 +215,9 @@ public void SetUnreachable() ControlFrame.Unreachable = true; } + public void Assert(bool factIsTrue, string formatString, params object[] args) { } + public void Assert([NotNull] object? objIsNotNull, string formatString, params object[] args) { objIsNotNull = NonNull; } - public void Assert(bool factIsTrue, string message) {} - - public void Assert(object objIsNotNull, string message) { } public void ValidateBlock(Block instructionBlock, int index = 0) {} } diff --git a/Wacs.Core/Modules/Sections/StackRenderer.cs b/Wacs.Core/Modules/Sections/StackRenderer.cs index 38bfdea..21042b8 100644 --- a/Wacs.Core/Modules/Sections/StackRenderer.cs +++ b/Wacs.Core/Modules/Sections/StackRenderer.cs @@ -70,16 +70,14 @@ public void PushValues(Stack vals) { public Value PopType(ValType type) => _context.Pop(type); public Value PopAny() => _context.Pop(ValType.Nil); - - public Stack PopValues(ResultType types) + + public void PopValues(ResultType types, ref Stack aside) { - var aside = new Stack(); foreach (var type in types.Types.Reverse()) { var stackType = PopAny(); aside.Push(stackType); } - return aside; } public void ReturnResults(ResultType types) @@ -158,8 +156,9 @@ public FakeContext(Module module, Module.Function func) public IValidationOpStack OpStack => _opStack; - public void Assert(bool factIsTrue, string message) {} - public void Assert([NotNull] object? objIsNotNull, string message) { objIsNotNull = NonNull; } + + public void Assert(bool factIsTrue, string formatString, params object[] args) { } + public void Assert([NotNull] object? objIsNotNull, string formatString, params object[] args) { objIsNotNull = NonNull; } public FuncIdx FunctionIndex => FuncIdx.Default; @@ -180,13 +179,15 @@ public void PushControlFrame(ByteCode opCode, FunctionType types) OpStack.PushResult(types.ParameterTypes); } + private static Stack _aside = new(); public ValidationControlFrame PopControlFrame() { if (ControlStack.Count == 0) throw new InvalidDataException("Control Stack underflow"); //Check to make sure we have the correct results - OpStack.PopValues(ControlFrame.EndTypes); + OpStack.PopValues(ControlFrame.EndTypes, ref _aside); + _aside.Clear(); //Reset the stack if (OpStack.Height != ControlFrame.Height) diff --git a/Wacs.Core/Runtime/ExecContext.cs b/Wacs.Core/Runtime/ExecContext.cs index 8c71764..25e5530 100644 --- a/Wacs.Core/Runtime/ExecContext.cs +++ b/Wacs.Core/Runtime/ExecContext.cs @@ -334,26 +334,26 @@ public void FunctionReturn() Stack<(string, int)> ascent = new(); int idx = _sequenceIndex; - // foreach (var label in Frame.Labels) - // { - // var pointer = (label.Instruction.GetMnemonic(), idx); - // ascent.Push(pointer); - // - // idx = label.ContinuationAddress.Index; - // - // switch ((OpCode)label.Instruction) - // { - // case OpCode.If: ascent.Push(("InstIf", 0)); - // break; - // case OpCode.Else: ascent.Push(("InstElse", 1)); - // break; - // case OpCode.Block: ascent.Push(("InstBlock", 0)); - // break; - // case OpCode.Loop: ascent.Push(("InstLoop", 0)); - // break; - // } - // - // } + foreach (var label in Frame.EnumerateLabels()) + { + var pointer = (label.Instruction.GetMnemonic(), idx); + ascent.Push(pointer); + + idx = label.ContinuationAddress.Index; + + switch ((OpCode)label.Instruction) + { + case OpCode.If: ascent.Push(("InstIf", 0)); + break; + case OpCode.Else: ascent.Push(("InstElse", 1)); + break; + case OpCode.Block: ascent.Push(("InstBlock", 0)); + break; + case OpCode.Loop: ascent.Push(("InstLoop", 0)); + break; + } + + } ascent.Push(("Function", (int)Frame.Index.Value)); diff --git a/Wacs.Core/Runtime/Frame.cs b/Wacs.Core/Runtime/Frame.cs index cca966f..46d0314 100644 --- a/Wacs.Core/Runtime/Frame.cs +++ b/Wacs.Core/Runtime/Frame.cs @@ -15,6 +15,8 @@ // */ using System.Buffers; +using System.Collections; +using System.Collections.Generic; using System.IO; using Wacs.Core.Instructions; using Wacs.Core.OpCodes; @@ -125,5 +127,17 @@ public InstructionPointer PopLabels(int idx) return oldLabel.Label.ContinuationAddress; } + + public IEnumerable