internal sealed override void Compile(CompilationContext context) { var stack = context.Stack; if (stack.Count < 2) { throw new StackTooSmallException(this.OpCode, 2, stack.Count); } var type = stack.Pop(); if (type != this.Type) { throw new StackTypeInvalidException(this.OpCode, this.Type, type); } type = stack.Pop(); if (type != ValueType.Int32) { throw new StackTypeInvalidException(this.OpCode, ValueType.Int32, type); } Int32Constant.Emit(context, (int)this.Offset); context.EmitLoadThis(); context.Emit(OpCodes.Call, context[this.StoreHelper, this.CreateStoreMethod]); }
internal sealed override void Compile(CompilationContext context) { context.PopStack(this.OpCode, this.Type, WebAssemblyValueType.Int32); Int32Constant.Emit(context, (int)this.Offset); context.EmitLoadThis(); context.Emit(OpCodes.Call, context[this.StoreHelper, this.CreateStoreMethod]); }
internal sealed override void CompileIKVM(IKVMCompilationContext context, IKVM.Reflection.Universe universe) { var stack = context.Stack; if (stack.Count == 0) { throw new StackTooSmallException(this.OpCode, 1, 0); } var type = stack.Pop(); if (type != ValueType.Int32) { throw new StackTypeInvalidException(this.OpCode, ValueType.Int32, type); } if (this.Offset != 0) { Int32Constant.Emit(context, (int)this.Offset); context.Emit(IKVM.Reflection.Emit.OpCodes.Add_Ovf_Un); } this.IKVMEmitRangeCheck(context, universe); context.EmitLoadThis(); context.Emit(IKVM.Reflection.Emit.OpCodes.Ldfld, context.Memory); context.Emit(IKVM.Reflection.Emit.OpCodes.Call, Runtime.UnmanagedMemory.IKVMStartGetter(universe)); context.Emit(IKVM.Reflection.Emit.OpCodes.Add); byte alignment; switch (this.Flags & Options.Align8) { default: //Impossible to hit, but needed to avoid compiler error the about alignment variable. case Options.Align1: alignment = 1; break; case Options.Align2: alignment = 2; break; case Options.Align4: alignment = 4; break; case Options.Align8: alignment = 8; break; } if (alignment != 4) { context.Emit(IKVM.Reflection.Emit.OpCodes.Unaligned, alignment); } context.Emit(this.IKVMEmittedOpCode); var conversion = this.IKVMConversionOpCode; if (conversion != IKVM.Reflection.Emit.OpCodes.Nop) { context.Emit(conversion); } stack.Push(this.Type); }
internal sealed override void Compile(CompilationContext context) { var stack = context.Stack; context.PopStackNoReturn(this.OpCode, WebAssemblyValueType.Int32); if (this.Offset != 0) { Int32Constant.Emit(context, (int)this.Offset); context.Emit(OpCodes.Add_Ovf_Un); } this.EmitRangeCheck(context); context.EmitLoadThis(); context.Emit(OpCodes.Ldfld, context.CheckedMemory); context.Emit(OpCodes.Call, UnmanagedMemory.StartGetter); context.Emit(OpCodes.Add); byte alignment; switch (this.Flags & Options.Align8) { default: //Impossible to hit, but needed to avoid compiler error the about alignment variable. case Options.Align1: alignment = 1; break; case Options.Align2: alignment = 2; break; case Options.Align4: alignment = 4; break; case Options.Align8: alignment = 8; break; } //8-byte alignment is not available in IL. //See: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.unaligned?view=net-5.0 //However, because 8-byte alignment is subset of 4-byte alignment, //We don't have to consider it. if (alignment != 4 && alignment != 8) { context.Emit(OpCodes.Unaligned, alignment); } context.Emit(this.EmittedOpCode); var conversion = this.ConversionOpCode; if (conversion != OpCodes.Nop) { context.Emit(conversion); } stack.Push(this.Type); }
internal sealed override void Compile(CompilationContext context) { var stack = context.Stack; context.PopStack(this.OpCode, WebAssemblyValueType.Int32); if (this.Offset != 0) { Int32Constant.Emit(context, (int)this.Offset); context.Emit(OpCodes.Add_Ovf_Un); } this.EmitRangeCheck(context); context.EmitLoadThis(); context.Emit(OpCodes.Ldfld, context.CheckedMemory); context.Emit(OpCodes.Call, UnmanagedMemory.StartGetter); context.Emit(OpCodes.Add); byte alignment; switch (this.Flags & Options.Align8) { default: //Impossible to hit, but needed to avoid compiler error the about alignment variable. case Options.Align1: alignment = 1; break; case Options.Align2: alignment = 2; break; case Options.Align4: alignment = 4; break; case Options.Align8: alignment = 8; break; } if (alignment != 4) { context.Emit(OpCodes.Unaligned, alignment); } context.Emit(this.EmittedOpCode); var conversion = this.ConversionOpCode; if (conversion != OpCodes.Nop) { context.Emit(conversion); } stack.Push(this.Type); }
internal sealed override void Compile(CompilationContext context) { var signature = context.Types[this.Type]; var paramTypes = signature.RawParameterTypes; var returnTypes = signature.RawReturnTypes; var stack = context.Stack; if (stack.Count < paramTypes.Length) { throw new StackTooSmallException(OpCode.CallIndirect, paramTypes.Length, stack.Count); } var type = stack.Pop(); if (type != ValueType.Int32) { throw new StackTypeInvalidException(OpCode.CallIndirect, ValueType.Int32, type); } for (var i = paramTypes.Length - 1; i >= 0; i--) { type = stack.Pop(); if (type != paramTypes[i]) { throw new StackTypeInvalidException(OpCode.CallIndirect, paramTypes[i], type); } } for (var i = 0; i < returnTypes.Length; i++) { stack.Push(returnTypes[i]); } Int32Constant.Emit(context, checked ((int)this.Type)); context.Emit(OpCodes.Call, context[HelperMethod.GetFunctionPointer]); context.Emit(OpCodes.Stloc, context.IndirectPointerLocal.LocalIndex); context.EmitLoadThis(); context.Emit(OpCodes.Ldloc, context.IndirectPointerLocal.LocalIndex); context.EmitCalli( signature.ReturnTypes.Length == 0 ? typeof(void) : signature.ReturnTypes[0], signature.ParameterTypes.Concat(new[] { context.ExportsBuilder.AsType() }).ToArray( )); }