From 69e814fc912cecf68dddc57cdf9e09feb116a5fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Tue, 12 Oct 2021 19:50:30 +0200 Subject: [PATCH 01/36] Fix double addition of the same DLL reference, in case the transpiled DLL is in fact the mscorlib itself --- IL2C.Core/Metadata/MetadataContext.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/IL2C.Core/Metadata/MetadataContext.cs b/IL2C.Core/Metadata/MetadataContext.cs index b9416e97..cc99f585 100644 --- a/IL2C.Core/Metadata/MetadataContext.cs +++ b/IL2C.Core/Metadata/MetadataContext.cs @@ -112,9 +112,12 @@ internal MetadataContext(string assemblyPath, bool readSymbols) this.MainAssembly = mainAssemblyInformation; assemblies.Add(mainAssembly, mainAssemblyInformation); - assemblies.Add(resolvedCoreAssembly, resolvedCoreAssemblyInformation); - modules.Add(resolvedCoreModule, resolvedCoreModuleInformation); - assemblyByModule.Add(resolvedCoreModule, resolvedCoreAssembly); + if (!assemblies.ContainsKey(resolvedCoreAssembly)) + { + assemblies.Add(resolvedCoreAssembly, resolvedCoreAssemblyInformation); + modules.Add(resolvedCoreModule, resolvedCoreModuleInformation); + assemblyByModule.Add(resolvedCoreModule, resolvedCoreAssembly); + } this.VoidType = this.GetOrAddType(resolvedCoreModule.TypeSystem.Void); this.ObjectType = this.GetOrAddType(resolvedCoreModule.TypeSystem.Object); From 663563cf810465eb49eef3127a6a75ed0c6d540d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Tue, 12 Oct 2021 19:52:02 +0200 Subject: [PATCH 02/36] Fix discovery of implemented method in case of explicit interface implementation --- IL2C.Core/Metadata/MetadataUtilities.cs | 41 ++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/IL2C.Core/Metadata/MetadataUtilities.cs b/IL2C.Core/Metadata/MetadataUtilities.cs index 611dea31..1f44a095 100644 --- a/IL2C.Core/Metadata/MetadataUtilities.cs +++ b/IL2C.Core/Metadata/MetadataUtilities.cs @@ -424,10 +424,27 @@ public MethodSignatureComparerImpl(bool isVirtual) public int Compare(IMethodInformation x, IMethodInformation y) { - var rn = x.Name.CompareTo(y.Name); + var xname = x.Name; + var yname = y.Name; + + var rn = xname.CompareTo(yname); if (rn != 0) { - return rn; + // If it is an explicit interface implementation, we need to compare with it's full name + if (x.DeclaringType.IsInterface) + { + xname = $"{x.DeclaringType.FriendlyName}.{xname}"; + } + if (y.DeclaringType.IsInterface) + { + yname = $"{y.DeclaringType.FriendlyName}.{yname}"; + } + + rn = xname.CompareTo(yname); + if (rn != 0) + { + return rn; + } } var xps = x.Parameters; @@ -449,9 +466,25 @@ public int Compare(IMethodInformation x, IMethodInformation y) public bool Equals(IMethodInformation x, IMethodInformation y) { - if (x.Name != y.Name) + var xname = x.Name; + var yname = y.Name; + + if (xname != yname) { - return false; + // If it is an explicit interface implementation, we need to compare with it's full name + if (x.DeclaringType.IsInterface) + { + xname = $"{x.DeclaringType.FriendlyName}.{xname}"; + } + if (y.DeclaringType.IsInterface) + { + yname = $"{y.DeclaringType.FriendlyName}.{yname}"; + } + + if (xname != yname) + { + return false; + } } var xps = x.Parameters; From 4234755f90553b2516b40a5a9f672df75605253a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Tue, 12 Oct 2021 20:10:43 +0200 Subject: [PATCH 03/36] Add bitwise NOT arithmetic operator --- .../ILConveters/ArithmeticalConverters.cs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/IL2C.Core/ILConveters/ArithmeticalConverters.cs b/IL2C.Core/ILConveters/ArithmeticalConverters.cs index 6010bd4e..71601d73 100644 --- a/IL2C.Core/ILConveters/ArithmeticalConverters.cs +++ b/IL2C.Core/ILConveters/ArithmeticalConverters.cs @@ -234,4 +234,37 @@ public override ExpressionEmitter Prepare(DecodeContext decodeContext) ArithmeticalConverterUtilities.BinaryOperators.Rem, decodeContext); } } + + internal sealed class NotConverter : InlineNoneConverter + { + public override OpCode OpCode => OpCodes.Not; + + public override ExpressionEmitter Prepare(DecodeContext decodeContext) + { + var si0 = decodeContext.PopStack(); + + if (si0.TargetType.IsFloatStackFriendlyType || si0.TargetType.IsByReference) + throw new InvalidProgramSequenceException( + "Invalid arithmetical NOT operation: Location={0}, Type0={1}", + decodeContext.CurrentCode.RawLocation, + si0.TargetType.FriendlyName); + + if (si0.TargetType.IsInt32StackFriendlyType) + { + var result = decodeContext.PushStack(decodeContext.PrepareContext.MetadataContext.Int32Type); + return (extractContext, _) => new[] { string.Format( + "{0} = ~{1}", + extractContext.GetSymbolName(result), + extractContext.GetSymbolName(si0)) }; + } + else + { // Int64 = ~(Int64) + var result = decodeContext.PushStack(decodeContext.PrepareContext.MetadataContext.Int64Type); + return (extractContext, _) => new[] { string.Format( + "{0} = ~{1}", + extractContext.GetSymbolName(result), + extractContext.GetSymbolName(si0)) }; + } + } + } } From 19c92d9127c6a6a4e4a53464aac972f7ca11768c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Tue, 12 Oct 2021 20:55:39 +0200 Subject: [PATCH 04/36] Implement shr, shl IL codes --- .../ILConveters/ArithmeticalConverters.cs | 59 ++++++++++++++++--- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/IL2C.Core/ILConveters/ArithmeticalConverters.cs b/IL2C.Core/ILConveters/ArithmeticalConverters.cs index 71601d73..fc5bfdd5 100644 --- a/IL2C.Core/ILConveters/ArithmeticalConverters.cs +++ b/IL2C.Core/ILConveters/ArithmeticalConverters.cs @@ -242,6 +242,7 @@ internal sealed class NotConverter : InlineNoneConverter public override ExpressionEmitter Prepare(DecodeContext decodeContext) { var si0 = decodeContext.PopStack(); + Metadata.ILocalVariableInformation result; if (si0.TargetType.IsFloatStackFriendlyType || si0.TargetType.IsByReference) throw new InvalidProgramSequenceException( @@ -251,20 +252,62 @@ public override ExpressionEmitter Prepare(DecodeContext decodeContext) if (si0.TargetType.IsInt32StackFriendlyType) { - var result = decodeContext.PushStack(decodeContext.PrepareContext.MetadataContext.Int32Type); - return (extractContext, _) => new[] { string.Format( - "{0} = ~{1}", - extractContext.GetSymbolName(result), - extractContext.GetSymbolName(si0)) }; + result = decodeContext.PushStack(decodeContext.PrepareContext.MetadataContext.Int32Type); } else { // Int64 = ~(Int64) - var result = decodeContext.PushStack(decodeContext.PrepareContext.MetadataContext.Int64Type); - return (extractContext, _) => new[] { string.Format( + result = decodeContext.PushStack(decodeContext.PrepareContext.MetadataContext.Int64Type); + } + + return (extractContext, _) => new[] { string.Format( "{0} = ~{1}", extractContext.GetSymbolName(result), extractContext.GetSymbolName(si0)) }; - } } } + + internal enum ShiftDirection + { + Left, Right + } + + internal abstract class ShiftConverter : InlineNoneConverter + { + public abstract ShiftDirection Direction { get; } + + public override ExpressionEmitter Prepare(DecodeContext decodeContext) + { + var si1 = decodeContext.PopStack(); + var si0 = decodeContext.PopStack(); + + if (si0.TargetType.IsFloatStackFriendlyType || si0.TargetType.IsByReference || !si1.TargetType.IsInt32Type) + throw new InvalidProgramSequenceException( + "Invalid arithmetical NOT operation: Location={0}, Type0={1}", + decodeContext.CurrentCode.RawLocation, + si0.TargetType.FriendlyName); + + var result = decodeContext.PushStack(si0.TargetType); + + return (extractContext, _) => new[] { string.Format( + "{0} = {1} {2} {3}", + extractContext.GetSymbolName(result), + extractContext.GetSymbolName(si0), + Direction == ShiftDirection.Left ? "<<" : ">>", + extractContext.GetSymbolName(si1)) }; + } + } + + internal sealed class ShiftRightConverter : ShiftConverter + { + public override OpCode OpCode => OpCodes.Shr; + + public override ShiftDirection Direction => ShiftDirection.Right; + } + + internal sealed class ShiftLeftConverter : ShiftConverter + { + public override OpCode OpCode => OpCodes.Shl; + + public override ShiftDirection Direction => ShiftDirection.Left; + } } From f6bb40661d8712976a52cdeeb79cb98f954b07c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Tue, 12 Oct 2021 21:15:34 +0200 Subject: [PATCH 05/36] Add starg and star.s IL codes --- IL2C.Core/ILConveters/StargConverters .cs | 67 +++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 IL2C.Core/ILConveters/StargConverters .cs diff --git a/IL2C.Core/ILConveters/StargConverters .cs b/IL2C.Core/ILConveters/StargConverters .cs new file mode 100644 index 00000000..6c089e60 --- /dev/null +++ b/IL2C.Core/ILConveters/StargConverters .cs @@ -0,0 +1,67 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// IL2C - A translator for ECMA-335 CIL/MSIL to C language. +// Copyright (c) 2016-2019 Kouji Matsui (@kozy_kekyo, @kekyo2) +// +// 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 Mono.Cecil.Cil; + +using IL2C.Translators; +using IL2C.Metadata; + +namespace IL2C.ILConverters +{ + internal static class StargConverterUtilities + { + public static ExpressionEmitter Prepare( + int parameterIndex, DecodeContext decodeContext, bool isReference) + { + var parameter = decodeContext.Method.Parameters[parameterIndex]; + var targetType = isReference ? parameter.TargetType.MakeByReference() : parameter.TargetType; + var symbol = decodeContext.PushStack(targetType); + + return (extractContext, _) => new[] { string.Format( + "{0} = {1}{2}", + parameter.ParameterName, + // NOTE: Don't check "targetType.IsByReference" instead "isReference." + // Because it's maybe double encoded byref type. + isReference ? "&" : string.Empty, + extractContext.GetSymbolName(symbol)) }; + } + } + + internal sealed class StargSConverter : ShortInlineParamConverter + { + public override OpCode OpCode => OpCodes.Starg_S; + + public override ExpressionEmitter Prepare(VariableInformation operand, DecodeContext decodeContext) + { + return StargConverterUtilities.Prepare(operand.Index, decodeContext, false); + } + } + + internal sealed class StargConverter : InlineParamConverter + { + public override OpCode OpCode => OpCodes.Starg; + + public override ExpressionEmitter Prepare(VariableInformation operand, DecodeContext decodeContext) + { + return StargConverterUtilities.Prepare(operand.Index, decodeContext, false); + } + } +} From 9091c5b323d8bc034156c8cbd2e325ce0a704714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Wed, 13 Oct 2021 11:56:26 +0200 Subject: [PATCH 06/36] Fix for #105, stop endless loop, fix static constructor handling #97, #98 --- IL2C.Core/AssemblyPreparer.cs | 2 +- IL2C.Core/Metadata/TypeInformation.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/IL2C.Core/AssemblyPreparer.cs b/IL2C.Core/AssemblyPreparer.cs index 12389a6e..49d824fb 100644 --- a/IL2C.Core/AssemblyPreparer.cs +++ b/IL2C.Core/AssemblyPreparer.cs @@ -322,7 +322,7 @@ public static PreparedInformations Prepare(TranslateContext translateContext) // All types type => true, // The methods except type initializer. - method => !(method.IsConstructor && method.IsStatic)); + method => true); } } } diff --git a/IL2C.Core/Metadata/TypeInformation.cs b/IL2C.Core/Metadata/TypeInformation.cs index 53ec4e1e..b90c8d77 100644 --- a/IL2C.Core/Metadata/TypeInformation.cs +++ b/IL2C.Core/Metadata/TypeInformation.cs @@ -363,7 +363,7 @@ public bool IsReferenceType public bool IsRequiredTraverse => (this.Member.IsValueType && !this.Member.IsPrimitive && !this.Member.IsPointer && !this.IsByReference && !this.IsEnum && - this.Fields.Any(f => f.FieldType.IsRequiredTraverse)) || + this.Fields.Where(f => f.FieldType.FriendlyName != this.Member.FullName).Any(f => f.FieldType.IsRequiredTraverse)) || this.IsReferenceType; private static int InternalGetStaticSizeOfValue(ITypeInformation type) => From bab32a09599cc87d349f0696d325d0b16f872e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Wed, 13 Oct 2021 11:57:56 +0200 Subject: [PATCH 07/36] Implement Shr.un and Neg IL codes --- .../ILConveters/ArithmeticalConverters.cs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/IL2C.Core/ILConveters/ArithmeticalConverters.cs b/IL2C.Core/ILConveters/ArithmeticalConverters.cs index fc5bfdd5..114ff003 100644 --- a/IL2C.Core/ILConveters/ArithmeticalConverters.cs +++ b/IL2C.Core/ILConveters/ArithmeticalConverters.cs @@ -310,4 +310,46 @@ internal sealed class ShiftLeftConverter : ShiftConverter public override ShiftDirection Direction => ShiftDirection.Left; } + + internal sealed class ShiftRightUnConverter : ShiftConverter + { + public override OpCode OpCode => OpCodes.Shr_Un; + + public override ShiftDirection Direction => ShiftDirection.Right; + } + + internal sealed class NegConverter : InlineNoneConverter + { + public override OpCode OpCode => OpCodes.Neg; + + public override ExpressionEmitter Prepare(DecodeContext decodeContext) + { + var si0 = decodeContext.PopStack(); + Metadata.ILocalVariableInformation result; + + if (si0.TargetType.IsByReference) + throw new InvalidProgramSequenceException( + "Invalid arithmetical NEG operation: Location={0}, Type0={1}", + decodeContext.CurrentCode.RawLocation, + si0.TargetType.FriendlyName); + + if (si0.TargetType.IsInt32StackFriendlyType) + { + result = decodeContext.PushStack(decodeContext.PrepareContext.MetadataContext.Int32Type); + } + else if (si0.TargetType.IsInt64StackFriendlyType) + { // Int64 = -(Int64) + result = decodeContext.PushStack(decodeContext.PrepareContext.MetadataContext.Int64Type); + } + else + { // double = -(double) + result = decodeContext.PushStack(decodeContext.PrepareContext.MetadataContext.DoubleType); + } + + return (extractContext, _) => new[] { string.Format( + "{0} = -{1}", + extractContext.GetSymbolName(result), + extractContext.GetSymbolName(si0)) }; + } + } } From 80e54b573f577818f5d213df32fd92630ddd6909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Wed, 13 Oct 2021 11:59:05 +0200 Subject: [PATCH 08/36] Implement Bgt.un and Bgt.un.s IL codes --- IL2C.Core/ILConveters/BranchConverters.cs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/IL2C.Core/ILConveters/BranchConverters.cs b/IL2C.Core/ILConveters/BranchConverters.cs index cb36384b..a57170cb 100644 --- a/IL2C.Core/ILConveters/BranchConverters.cs +++ b/IL2C.Core/ILConveters/BranchConverters.cs @@ -241,6 +241,28 @@ public override ExpressionEmitter Prepare( } } + internal sealed class Bgt_UnConverter : ShortInlineBrTargetConverter + { + public override OpCode OpCode => OpCodes.Bgt_Un; + + public override ExpressionEmitter Prepare( + ICodeInformation operand, DecodeContext decodeContext) + { + return BranchExpressionUtilities.ApplyBinary(operand, ">", decodeContext); + } + } + + internal sealed class Bgt_Un_sConverter : ShortInlineBrTargetConverter + { + public override OpCode OpCode => OpCodes.Bgt_Un_S; + + public override ExpressionEmitter Prepare( + ICodeInformation operand, DecodeContext decodeContext) + { + return BranchExpressionUtilities.ApplyBinary(operand, ">", decodeContext); + } + } + internal sealed class BleConverter : ShortInlineBrTargetConverter { public override OpCode OpCode => OpCodes.Ble; From c5ac12415a974f5af0b74dd0ea75466b5276850f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Wed, 13 Oct 2021 12:00:26 +0200 Subject: [PATCH 09/36] Extend ConditionalConverters to handle float type parameters --- IL2C.Core/ILConveters/ConditionalConverters.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/IL2C.Core/ILConveters/ConditionalConverters.cs b/IL2C.Core/ILConveters/ConditionalConverters.cs index bdbe2abe..3fc81f83 100644 --- a/IL2C.Core/ILConveters/ConditionalConverters.cs +++ b/IL2C.Core/ILConveters/ConditionalConverters.cs @@ -77,6 +77,18 @@ public static ExpressionEmitter Prepare( extractContext.GetSymbolName(si1)) }; } + if (si0.TargetType.IsFloatStackFriendlyType && + si1.TargetType.IsFloatStackFriendlyType) + { + var result = decodeContext.PushStack(decodeContext.PrepareContext.MetadataContext.Int32Type); + return (extractContext, _) => new[] { string.Format( + "{0} = (double){1} {2} (double){3}", + extractContext.GetSymbolName(result), + extractContext.GetSymbolName(si0), + oper, + extractContext.GetSymbolName(si1)) }; + } + if ((si0.TargetType.IsIntPtrStackFriendlyType || !si0.TargetType.IsValueType || si0.TargetType.IsByReference || si0.TargetType.IsUntypedReferenceType) && (si1.TargetType.IsIntPtrStackFriendlyType || !si1.TargetType.IsValueType || si1.TargetType.IsByReference || si0.TargetType.IsUntypedReferenceType)) { From e01dc9a5c524c64f9fef59a61ce26b3b4b432ed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Wed, 13 Oct 2021 12:01:07 +0200 Subject: [PATCH 10/36] Fix typo --- IL2C.Core/ILConveters/LdtokenConverters.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IL2C.Core/ILConveters/LdtokenConverters.cs b/IL2C.Core/ILConveters/LdtokenConverters.cs index 03e2fbe4..d1761749 100644 --- a/IL2C.Core/ILConveters/LdtokenConverters.cs +++ b/IL2C.Core/ILConveters/LdtokenConverters.cs @@ -33,7 +33,7 @@ internal sealed class LdtokenConverters : InlineMemberConverter public override ExpressionEmitter Prepare( IMemberInformation member, DecodeContext decodeContext) { - // ECMA-335 III.4.17 ldtoken - load the runt ime representat ion of a metadata + // ECMA-335 III.4.17 ldtoken - load the runtime representation of a metadata var field = member as IFieldInformation; if (field != null) From 4833ba2df3e62f94c7eaafc9d9573fa81cc5593f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Wed, 13 Oct 2021 12:02:27 +0200 Subject: [PATCH 11/36] Implement Stind.i1-i8, Stind.r4-r8 IL codes --- IL2C.Core/ILConveters/StindConverters.cs | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/IL2C.Core/ILConveters/StindConverters.cs b/IL2C.Core/ILConveters/StindConverters.cs index 6ebba82e..3401b889 100644 --- a/IL2C.Core/ILConveters/StindConverters.cs +++ b/IL2C.Core/ILConveters/StindConverters.cs @@ -81,6 +81,28 @@ public static ExpressionEmitter Prepare( } } + internal sealed class Stind_i1Converter : InlineNoneConverter + { + public override OpCode OpCode => OpCodes.Stind_I1; + + public override ExpressionEmitter Prepare( + DecodeContext decodeContext) + { + return StindConverter_Utilities.Prepare(decodeContext); + } + } + + internal sealed class Stind_i2Converter : InlineNoneConverter + { + public override OpCode OpCode => OpCodes.Stind_I2; + + public override ExpressionEmitter Prepare( + DecodeContext decodeContext) + { + return StindConverter_Utilities.Prepare(decodeContext); + } + } + internal sealed class Stind_i4Converter : InlineNoneConverter { public override OpCode OpCode => OpCodes.Stind_I4; @@ -92,6 +114,39 @@ public override ExpressionEmitter Prepare( } } + internal sealed class Stind_i8Converter : InlineNoneConverter + { + public override OpCode OpCode => OpCodes.Stind_I8; + + public override ExpressionEmitter Prepare( + DecodeContext decodeContext) + { + return StindConverter_Utilities.Prepare(decodeContext); + } + } + + internal sealed class Stind_r4Converter : InlineNoneConverter + { + public override OpCode OpCode => OpCodes.Stind_R4; + + public override ExpressionEmitter Prepare( + DecodeContext decodeContext) + { + return StindConverter_Utilities.Prepare(decodeContext); + } + } + + internal sealed class Stind_r8Converter : InlineNoneConverter + { + public override OpCode OpCode => OpCodes.Stind_R8; + + public override ExpressionEmitter Prepare( + DecodeContext decodeContext) + { + return StindConverter_Utilities.Prepare(decodeContext); + } + } + internal sealed class Stind_RefConverter : InlineNoneConverter { public override OpCode OpCode => OpCodes.Stind_Ref; From 90bd0a3c9d63347d74252e12febafdf4bf032c3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Wed, 13 Oct 2021 20:05:53 +0200 Subject: [PATCH 12/36] Fix StargConverter --- IL2C.Core/ILConveters/StargConverters .cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/IL2C.Core/ILConveters/StargConverters .cs b/IL2C.Core/ILConveters/StargConverters .cs index 6c089e60..ecdfb216 100644 --- a/IL2C.Core/ILConveters/StargConverters .cs +++ b/IL2C.Core/ILConveters/StargConverters .cs @@ -31,9 +31,11 @@ internal static class StargConverterUtilities public static ExpressionEmitter Prepare( int parameterIndex, DecodeContext decodeContext, bool isReference) { + var si = decodeContext.PopStack(); var parameter = decodeContext.Method.Parameters[parameterIndex]; var targetType = isReference ? parameter.TargetType.MakeByReference() : parameter.TargetType; - var symbol = decodeContext.PushStack(targetType); + + // TODO: check target and source type return (extractContext, _) => new[] { string.Format( "{0} = {1}{2}", @@ -41,7 +43,7 @@ public static ExpressionEmitter Prepare( // NOTE: Don't check "targetType.IsByReference" instead "isReference." // Because it's maybe double encoded byref type. isReference ? "&" : string.Empty, - extractContext.GetSymbolName(symbol)) }; + extractContext.GetSymbolName(si)) }; } } From 05ececc0099d990e57a3292e55f36608678c3751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Wed, 13 Oct 2021 20:07:26 +0200 Subject: [PATCH 13/36] Add Enum to int conversion handling to GetRightExpression() --- IL2C.Core/TranslateContext.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/IL2C.Core/TranslateContext.cs b/IL2C.Core/TranslateContext.cs index 46579c27..aa16aa0e 100644 --- a/IL2C.Core/TranslateContext.cs +++ b/IL2C.Core/TranslateContext.cs @@ -282,6 +282,17 @@ private string GetRightExpression( rhsExpression); } } + else if (rhsType.IsEnum) + { + // intValue = (int)enumValue + if (lhsType.IsNumericPrimitive) + { + return string.Format( + "({0}){1}", + lhsType.CLanguageTypeName, + rhsExpression); + } + } else if (rhsType.IsBooleanType) { // intValue = boolValue (implicitly conversion) From f98e142cc69bf8de73ade2d9d47f17a217033f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Wed, 13 Oct 2021 20:08:45 +0200 Subject: [PATCH 14/36] Fix NullReferenceException occurring in MethodSignatureTypeComparerImpl.Compare() --- IL2C.Core/Metadata/MetadataUtilities.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/IL2C.Core/Metadata/MetadataUtilities.cs b/IL2C.Core/Metadata/MetadataUtilities.cs index 1f44a095..014ac45c 100644 --- a/IL2C.Core/Metadata/MetadataUtilities.cs +++ b/IL2C.Core/Metadata/MetadataUtilities.cs @@ -270,6 +270,16 @@ public MethodSignatureTypeComparerImpl() public int Compare(ITypeInformation x, ITypeInformation y) { + if (x == null) + { + if (y == null) return 0; + else return 1; + } + else + { + if (y == null) return -1; + } + if (x.Equals(y)) { return 0; @@ -385,9 +395,6 @@ public int Compare(IParameterInformation x, IParameterInformation y) var xt = x.TargetType; var yt = y.TargetType; - var xr = xt.IsAssignableFrom(yt); - var yr = yt.IsAssignableFrom(xt); - return MethodSignatureTypeComparer.Compare(xt, yt); } From df35a871b59ea1eb29b222643b163f76d1d8fc68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Wed, 13 Oct 2021 20:10:59 +0200 Subject: [PATCH 15/36] Fix InternalWriteVTableTypePreDefinitions() to correctly handle empty interface definitions --- IL2C.Core/Writers/HeaderWriter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IL2C.Core/Writers/HeaderWriter.cs b/IL2C.Core/Writers/HeaderWriter.cs index 3d06d29b..cca7ca60 100644 --- a/IL2C.Core/Writers/HeaderWriter.cs +++ b/IL2C.Core/Writers/HeaderWriter.cs @@ -118,7 +118,7 @@ private static void InternalWriteVTableTypePreDefinitions( } // If virtual method collection doesn't contain newslot method at this declared type: - if (!type.DeclaredNewslotMethods.Any(method => method.DeclaringType.Equals(type))) + if (!type.DeclaredNewslotMethods.Any(method => method.DeclaringType.Equals(type)) && type.BaseType != null) { twHeader.WriteLine( "typedef {0}_VTABLE_DECL__ {1}_VTABLE_DECL__;", From 1a9cfe8397ed0c4f1ab43483cdfe39e5f4d79a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Wed, 13 Oct 2021 20:12:49 +0200 Subject: [PATCH 16/36] Enable IL2C_RUNTIME_TYPE_BEGIN writer, to handle compilation of System.Object, where there is no BaseType --- IL2C.Core/Writers/TypeHelperWriter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IL2C.Core/Writers/TypeHelperWriter.cs b/IL2C.Core/Writers/TypeHelperWriter.cs index f9a407b5..b20d818e 100644 --- a/IL2C.Core/Writers/TypeHelperWriter.cs +++ b/IL2C.Core/Writers/TypeHelperWriter.cs @@ -342,7 +342,7 @@ public static void InternalConvertTypeHelper( declaredType.IsReferenceType ? "IL2C_TYPE_REFERENCE" : "IL2C_TYPE_VALUE", declaredType.CLanguageStaticSizeOfExpression, - declaredType.BaseType.MangledUniqueName, + declaredType.BaseType == null ? "NULL" : declaredType.BaseType.MangledUniqueName, declaredType.IsDelegate ? "System_Delegate_MarkHandler__" : markTargetFields.Length.ToString(), interfaceTypes.Length); } From 2a73440babcf1c633dea895c559d78144ae0efd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Wed, 13 Oct 2021 20:14:19 +0200 Subject: [PATCH 17/36] Enable handling without error such cases, where BaseType == null --- IL2C.Core/Writers/TypeWriter.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/IL2C.Core/Writers/TypeWriter.cs b/IL2C.Core/Writers/TypeWriter.cs index 74e5f8cd..89c7428a 100644 --- a/IL2C.Core/Writers/TypeWriter.cs +++ b/IL2C.Core/Writers/TypeWriter.cs @@ -98,7 +98,7 @@ public static void WriteTypeDefinitions( tw.WriteLine( "// [1-2-3] {0} VTable layout (Derived from {1})", declaredType.MemberTypeName, - declaredType.BaseType.FriendlyName); + declaredType.BaseType?.FriendlyName); } tw.WriteLine( @@ -276,7 +276,7 @@ public static void WriteTypeDefinitions( { tw.WriteLine( "// [1-5-1] VTable (Same as {0})", - declaredType.BaseType.FriendlyName); + declaredType.BaseType?.FriendlyName); tw.WriteLine( "#define {0}_VTABLE__ {1}_VTABLE__", declaredType.MangledUniqueName, @@ -287,7 +287,7 @@ public static void WriteTypeDefinitions( { tw.WriteLine( "// [1-5-2] VTable (Derived from {0})", - declaredType.BaseType.FriendlyName); + declaredType.BaseType?.FriendlyName); tw.WriteLine( "extern {0}_VTABLE_DECL__ {0}_VTABLE__;", declaredType.MangledUniqueName); From e8029c15923b394c980edf8f50b46581222c86a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Wed, 13 Oct 2021 20:16:10 +0200 Subject: [PATCH 18/36] Implement Switch IL code, for #93 and #91 v0.1 --- IL2C.Core/ILConveters/SwitchConverter.cs | 48 ++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 IL2C.Core/ILConveters/SwitchConverter.cs diff --git a/IL2C.Core/ILConveters/SwitchConverter.cs b/IL2C.Core/ILConveters/SwitchConverter.cs new file mode 100644 index 00000000..f35bcb4e --- /dev/null +++ b/IL2C.Core/ILConveters/SwitchConverter.cs @@ -0,0 +1,48 @@ +using IL2C.ILConverters; +using IL2C.Metadata; +using IL2C.Translators; +using Mono.Cecil.Cil; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IL2C.ILConveters +{ + internal sealed class SwitchConverter : ILConverter + { + public override OpCode OpCode => OpCodes.Switch; + + public override ExpressionEmitter Prepare(Instruction[] operands, DecodeContext decodeContext) + { + var si = decodeContext.PopStack(); + if (!si.TargetType.IsInt32Type) + throw new InvalidProgramSequenceException( + "Invalid type at stack for switch: Location={0}, StackType={1}", + decodeContext.CurrentCode.RawLocation, + si.TargetType.FriendlyName); + + var labels = new string[operands.Length]; + int i; + + for (i = 0; i < operands.Length; i++) + { + labels[i] = decodeContext.EnqueueNewPath(operands[i].Offset); + } + + return (extractContext, _) => + { + var result = new string[labels.Length + 1]; + result[0] = $"switch ({extractContext.GetSymbolName(si)}) {{\n "; + for (int q = 0; q < labels.Length; q++) + { + var caseStr = $"case {q}: goto {labels[q]}"; + if (q == 0) result[q] += caseStr; else result[q] = caseStr; + } + result[result.Length - 1] = "default: }"; + return result; + }; + } + } +} From e1b6cc4314419f76f5ea327c256328af96cd8c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Thu, 14 Oct 2021 09:57:40 +0200 Subject: [PATCH 19/36] Implement Ldobj and Stobj IL codes --- IL2C.Core/ILConveters/LdindConverters.cs | 14 +++++++++++++- IL2C.Core/ILConveters/StindConverters.cs | 12 ++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/IL2C.Core/ILConveters/LdindConverters.cs b/IL2C.Core/ILConveters/LdindConverters.cs index 3a9a5d59..6b3f63de 100644 --- a/IL2C.Core/ILConveters/LdindConverters.cs +++ b/IL2C.Core/ILConveters/LdindConverters.cs @@ -31,7 +31,7 @@ public static ExpressionEmitter Prepare(DecodeContext decodeContext) { var siFrom = decodeContext.PopStack(); - // Requre only managed refs + // Require only managed refs if (!siFrom.TargetType.IsByReference) { throw new InvalidProgramSequenceException( @@ -159,4 +159,16 @@ public override ExpressionEmitter Prepare(DecodeContext decodeContext) return LdindConverterUtilities.Prepare(decodeContext); } } + + // It is just a generalized Ldind. C compiler handles struct copy + internal sealed class LdobjConverter : InlineTypeConverter + { + public override OpCode OpCode => OpCodes.Ldobj; + + public override ExpressionEmitter Prepare(Metadata.ITypeInformation operand, DecodeContext decodeContext) + { + // Note: note really need the operand in this case, since IL2C knows the type already + return LdindConverterUtilities.Prepare(decodeContext); + } + } } diff --git a/IL2C.Core/ILConveters/StindConverters.cs b/IL2C.Core/ILConveters/StindConverters.cs index 3401b889..491f5673 100644 --- a/IL2C.Core/ILConveters/StindConverters.cs +++ b/IL2C.Core/ILConveters/StindConverters.cs @@ -157,4 +157,16 @@ public override ExpressionEmitter Prepare( return StindConverter_Utilities.Prepare(decodeContext); } } + + // It is just a generalized Stind. C compiler handles struct copy + internal sealed class StobjConverter : InlineTypeConverter + { + public override OpCode OpCode => OpCodes.Stobj; + + public override ExpressionEmitter Prepare(Metadata.ITypeInformation operand, DecodeContext decodeContext) + { + // Note: note really need the operand in this case, since IL2C knows the type already + return StindConverter_Utilities.Prepare(decodeContext); + } + } } From 30c0889232ec578bf4ded285fc2491e7c9a3f2a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Thu, 14 Oct 2021 10:29:20 +0200 Subject: [PATCH 20/36] Updated supported-opcodes.md by Unit tests, no regression so far --- docs/supported-opcodes.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/supported-opcodes.md b/docs/supported-opcodes.md index a042e520..2fbd6aab 100644 --- a/docs/supported-opcodes.md +++ b/docs/supported-opcodes.md @@ -1,6 +1,6 @@ # Supported IL opcodes -* Number of opcode implementations: 140 / 219 +* Number of opcode implementations: 157 / 219 * Number of opcode tests: 928 [81 / 219] OpCode | Binary | Implement | Test | ILConverter @@ -18,8 +18,8 @@ OpCode | Binary | Implement | Test | ILConverter | [bge.un.s](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.bge_un_s) | 0x34 | | | | | [bgt](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.bgt) | 0x3d | Implemented | | IL2C.ILConverters.BgtConverter | | [bgt.s](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.bgt_s) | 0x30 | Implemented | | IL2C.ILConverters.Bgt_sConverter | -| [bgt.un](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.bgt_un) | 0x42 | | | | -| [bgt.un.s](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.bgt_un_s) | 0x35 | | | | +| [bgt.un](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.bgt_un) | 0x42 | Implemented | | IL2C.ILConverters.Bgt_UnConverter | +| [bgt.un.s](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.bgt_un_s) | 0x35 | Implemented | | IL2C.ILConverters.Bgt_Un_sConverter | | [ble](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ble) | 0x3e | Implemented | | IL2C.ILConverters.BleConverter | | [ble.s](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ble_s) | 0x31 | Implemented | | IL2C.ILConverters.Ble_sConverter | | [ble.un](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ble_un) | 0x43 | | | | @@ -153,7 +153,7 @@ OpCode | Binary | Implement | Test | ILConverter | [ldloca](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldloca) | 0xfe0d | | | | | [ldloca.s](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldloca_s) | 0x12 | Implemented | [Test [17]](../tests/IL2C.Core.Test.ILConverters/Ldloca_s) | IL2C.ILConverters.Ldloca_sConverter | | [ldnull](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldnull) | 0x14 | Implemented | [Test [3]](../tests/IL2C.Core.Test.ILConverters/Ldnull) | IL2C.ILConverters.LdnullConverter | -| [ldobj](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldobj) | 0x71 | | | | +| [ldobj](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldobj) | 0x71 | Implemented | | IL2C.ILConverters.LdobjConverter | | [ldsfld](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldsfld) | 0x7e | Implemented | [Test [16]](../tests/IL2C.Core.Test.ILConverters/Ldsfld) | IL2C.ILConverters.LdsfldConverter | | [ldsflda](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldsflda) | 0x7f | Implemented | [Test [16]](../tests/IL2C.Core.Test.ILConverters/Ldsflda) | IL2C.ILConverters.LdsfldaConverter | | [ldstr](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldstr) | 0x72 | Implemented | [Test [1]](../tests/IL2C.Core.Test.ILConverters/Ldstr) | IL2C.ILConverters.LdstrConverter | @@ -166,12 +166,12 @@ OpCode | Binary | Implement | Test | ILConverter | [mul](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.mul) | 0x5a | Implemented | [Test [9]](../tests/IL2C.Core.Test.ILConverters/Mul) | IL2C.ILConverters.MulConverter | | [mul.ovf](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.mul_ovf) | 0xd8 | | | | | [mul.ovf.un](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.mul_ovf_un) | 0xd9 | | | | -| [neg](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.neg) | 0x65 | | | | +| [neg](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.neg) | 0x65 | Implemented | | IL2C.ILConverters.NegConverter | | [newarr](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.newarr) | 0x8d | Implemented | | IL2C.ILConverters.NewarrConverter | | [newobj](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.newobj) | 0x73 | Implemented | | IL2C.ILConverters.NewobjConverter | | no | 0xfe19 | | | | | [nop](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.nop) | 0x0 | Implemented | [Test [1]](../tests/IL2C.Core.Test.ILConverters/Nop) | IL2C.ILConverters.NopConverter | -| [not](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.not) | 0x66 | | | | +| [not](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.not) | 0x66 | Implemented | | IL2C.ILConverters.NotConverter | | [or](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.or) | 0x60 | Implemented | [Test [5]](../tests/IL2C.Core.Test.ILConverters/Or) | IL2C.ILConverters.OrConverter | | [pop](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.pop) | 0x26 | Implemented | | IL2C.ILConverters.PopConverter | | [readonly](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.readonly) | 0xfe1e | | | | @@ -181,12 +181,12 @@ OpCode | Binary | Implement | Test | ILConverter | [rem.un](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.rem_un) | 0x5e | | | | | [ret](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ret) | 0x2a | Implemented | [Test [6]](../tests/IL2C.Core.Test.ILConverters/Ret) | IL2C.ILConverters.RetConverter | | [rethrow](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.rethrow) | 0xfe1a | Implemented | | IL2C.ILConverters.RethrowConverter | -| [shl](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.shl) | 0x62 | | | | -| [shr](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.shr) | 0x63 | | | | -| [shr.un](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.shr_un) | 0x64 | | | | +| [shl](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.shl) | 0x62 | Implemented | | IL2C.ILConverters.ShiftLeftConverter | +| [shr](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.shr) | 0x63 | Implemented | | IL2C.ILConverters.ShiftRightConverter | +| [shr.un](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.shr_un) | 0x64 | Implemented | | IL2C.ILConverters.ShiftRightUnConverter | | [sizeof](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.sizeof) | 0xfe1c | Implemented | | IL2C.ILConverters.SizeofConverter | -| [starg](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.starg) | 0xfe0b | | | | -| [starg.s](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.starg_s) | 0x10 | | | | +| [starg](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.starg) | 0xfe0b | Implemented | | IL2C.ILConverters.StargConverter | +| [starg.s](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.starg_s) | 0x10 | Implemented | | IL2C.ILConverters.StargSConverter | | [stelem.any](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stelem) | 0xa4 | Implemented | [Test [42]](../tests/IL2C.Core.Test.ILConverters/Stelem) | IL2C.ILConverters.Stelem_anyConvertersConverter | | [stelem.i](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stelem_i) | 0x9b | | | | | [stelem.i1](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stelem_i1) | 0x9c | Implemented | [Test [6]](../tests/IL2C.Core.Test.ILConverters/Stelem_i1) | IL2C.ILConverters.Stelem_i1ConvertersConverter | @@ -198,12 +198,12 @@ OpCode | Binary | Implement | Test | ILConverter | [stelem.ref](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stelem_ref) | 0xa2 | Implemented | [Test [6]](../tests/IL2C.Core.Test.ILConverters/Stelem_ref) | IL2C.ILConverters.Stelem_refConvertersConverter | | [stfld](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stfld) | 0x7d | Implemented | | IL2C.ILConverters.StfldConverter | | [stind.i](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_i) | 0xdf | | | | -| [stind.i1](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_i1) | 0x52 | | | | -| [stind.i2](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_i2) | 0x53 | | | | +| [stind.i1](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_i1) | 0x52 | Implemented | | IL2C.ILConverters.Stind_i1Converter | +| [stind.i2](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_i2) | 0x53 | Implemented | | IL2C.ILConverters.Stind_i2Converter | | [stind.i4](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_i4) | 0x54 | Implemented | | IL2C.ILConverters.Stind_i4Converter | -| [stind.i8](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_i8) | 0x55 | | | | -| [stind.r4](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_r4) | 0x56 | | | | -| [stind.r8](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_r8) | 0x57 | | | | +| [stind.i8](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_i8) | 0x55 | Implemented | | IL2C.ILConverters.Stind_i8Converter | +| [stind.r4](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_r4) | 0x56 | Implemented | | IL2C.ILConverters.Stind_r4Converter | +| [stind.r8](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_r8) | 0x57 | Implemented | | IL2C.ILConverters.Stind_r8Converter | | [stind.ref](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stind_ref) | 0x51 | Implemented | | IL2C.ILConverters.Stind_RefConverter | | [stloc](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stloc) | 0xfe0e | | | | | [stloc.0](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stloc_0) | 0xa | Implemented | [Test [16]](../tests/IL2C.Core.Test.ILConverters/Stloc_0) | IL2C.ILConverters.Stloc_0Converter | @@ -211,12 +211,12 @@ OpCode | Binary | Implement | Test | ILConverter | [stloc.2](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stloc_2) | 0xc | Implemented | [Test [16]](../tests/IL2C.Core.Test.ILConverters/Stloc_2) | IL2C.ILConverters.Stloc_2Converter | | [stloc.3](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stloc_3) | 0xd | Implemented | [Test [16]](../tests/IL2C.Core.Test.ILConverters/Stloc_3) | IL2C.ILConverters.Stloc_3Converter | | [stloc.s](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stloc_s) | 0x13 | Implemented | [Test [17]](../tests/IL2C.Core.Test.ILConverters/Stloc_s) | IL2C.ILConverters.Stloc_SConverter | -| [stobj](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stobj) | 0x81 | | | | +| [stobj](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stobj) | 0x81 | Implemented | | IL2C.ILConverters.StobjConverter | | [stsfld](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stsfld) | 0x80 | Implemented | [Test [14]](../tests/IL2C.Core.Test.ILConverters/Stsfld) | IL2C.ILConverters.StsfldConverter | | [sub](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.sub) | 0x59 | Implemented | [Test [11]](../tests/IL2C.Core.Test.ILConverters/Sub) | IL2C.ILConverters.SubConverter | | [sub.ovf](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.sub_ovf) | 0xda | | | | | [sub.ovf.un](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.sub_ovf_un) | 0xdb | | | | -| [switch](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.switch) | 0x45 | | | | +| [switch](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.switch) | 0x45 | Implemented | | IL2C.ILConveters.SwitchConverter | | [tail](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.tailcall) | 0xfe14 | | | | | [throw](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.throw) | 0x7a | Implemented | | IL2C.ILConverters.ThrowConverter | | [unaligned](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.unaligned) | 0xfe12 | | | | From 08ea06ad682017ca63cc3256cb180715a27e2410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Thu, 14 Oct 2021 12:56:27 +0200 Subject: [PATCH 21/36] Add switch IL code tests --- .../Switch/Switch.cs | 38 +++++++++++++++++++ .../Switch/Switch.il | 23 +++++++++++ 2 files changed, 61 insertions(+) create mode 100644 tests/IL2C.Core.Test.ILConverters/Switch/Switch.cs create mode 100644 tests/IL2C.Core.Test.ILConverters/Switch/Switch.il diff --git a/tests/IL2C.Core.Test.ILConverters/Switch/Switch.cs b/tests/IL2C.Core.Test.ILConverters/Switch/Switch.cs new file mode 100644 index 00000000..5deb4c7e --- /dev/null +++ b/tests/IL2C.Core.Test.ILConverters/Switch/Switch.cs @@ -0,0 +1,38 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// IL2C - A translator for ECMA-335 CIL/MSIL to C language. +// Copyright (c) 2016-2019 Kouji Matsui (@kozy_kekyo, @kekyo2) +// +// 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.Runtime.CompilerServices; + +namespace IL2C.ILConverters +{ + [TestCase((string)"0", "TestSwitch", (int)0)] + [TestCase((string)"1", "TestSwitch", (int)1)] + [TestCase((string)"2", "TestSwitch", (int)2)] + [TestCase((string)"3", "TestSwitch", (int)3)] + [TestCase((string)"Out of range", "TestSwitch", (int)-1)] + [TestCase((string)"Out of range", "TestSwitch", (int)4)] + [TestCase((string)"Out of range", "TestSwitch", (int)int.MinValue)] + [TestCase((string)"Out of range", "TestSwitch", (int)int.MaxValue)] + public sealed class Switch + { + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern string TestSwitch(int value); + } +} diff --git a/tests/IL2C.Core.Test.ILConverters/Switch/Switch.il b/tests/IL2C.Core.Test.ILConverters/Switch/Switch.il new file mode 100644 index 00000000..801fcaf1 --- /dev/null +++ b/tests/IL2C.Core.Test.ILConverters/Switch/Switch.il @@ -0,0 +1,23 @@ +.class public IL2C.ILConverters.Switch +{ + .method public static string TestSwitch(int value) cil managed + { + .maxstack 1 + ldarg.0 + switch (label0, label1, label2, label3) + ldstr "Out of range" + ret +label0: + ldstr "0" + ret +label1: + ldstr "1" + ret +label2: + ldstr "2" + ret +label3: + ldstr "3" + ret + } +} From ff75c55dfec217d727974732ab9215f425d549cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Thu, 14 Oct 2021 15:31:37 +0200 Subject: [PATCH 22/36] Fix switch test + generator --- IL2C.Core/ILConveters/SwitchConverter.cs | 2 +- tests/IL2C.Core.Test.ILConverters/Switch/Switch.cs | 2 +- tests/IL2C.Core.Test.ILConverters/Switch/Switch.il | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/IL2C.Core/ILConveters/SwitchConverter.cs b/IL2C.Core/ILConveters/SwitchConverter.cs index f35bcb4e..a26bf598 100644 --- a/IL2C.Core/ILConveters/SwitchConverter.cs +++ b/IL2C.Core/ILConveters/SwitchConverter.cs @@ -40,7 +40,7 @@ public override ExpressionEmitter Prepare(Instruction[] operands, DecodeContext var caseStr = $"case {q}: goto {labels[q]}"; if (q == 0) result[q] += caseStr; else result[q] = caseStr; } - result[result.Length - 1] = "default: }"; + result[result.Length - 1] = "default: ;}"; return result; }; } diff --git a/tests/IL2C.Core.Test.ILConverters/Switch/Switch.cs b/tests/IL2C.Core.Test.ILConverters/Switch/Switch.cs index 5deb4c7e..98fdccfa 100644 --- a/tests/IL2C.Core.Test.ILConverters/Switch/Switch.cs +++ b/tests/IL2C.Core.Test.ILConverters/Switch/Switch.cs @@ -33,6 +33,6 @@ namespace IL2C.ILConverters public sealed class Switch { [MethodImpl(MethodImplOptions.ForwardRef)] - public static extern string TestSwitch(int value); + public static extern string TestSwitch(int v); } } diff --git a/tests/IL2C.Core.Test.ILConverters/Switch/Switch.il b/tests/IL2C.Core.Test.ILConverters/Switch/Switch.il index 801fcaf1..88fb042e 100644 --- a/tests/IL2C.Core.Test.ILConverters/Switch/Switch.il +++ b/tests/IL2C.Core.Test.ILConverters/Switch/Switch.il @@ -1,6 +1,6 @@ .class public IL2C.ILConverters.Switch { - .method public static string TestSwitch(int value) cil managed + .method public static string TestSwitch(int32 v) cil managed { .maxstack 1 ldarg.0 From 5453d3932af7cb3269f76d98f12e2e5815b3922c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Thu, 14 Oct 2021 21:47:07 +0200 Subject: [PATCH 23/36] Ldobj IL code test + related fixes in converters --- .../ILConveters/ArithmeticalConverters.cs | 8 ++-- IL2C.Core/ILConveters/LdindConverters.cs | 22 +++++++-- tests/IL2C.Core.Test.Fixture/TestFramework.cs | 4 +- .../Ldobj/Ldobj.cs | 46 +++++++++++++++++++ .../Ldobj/Ldobj.il | 19 ++++++++ 5 files changed, 88 insertions(+), 11 deletions(-) create mode 100644 tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs create mode 100644 tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il diff --git a/IL2C.Core/ILConveters/ArithmeticalConverters.cs b/IL2C.Core/ILConveters/ArithmeticalConverters.cs index 114ff003..53beb4b1 100644 --- a/IL2C.Core/ILConveters/ArithmeticalConverters.cs +++ b/IL2C.Core/ILConveters/ArithmeticalConverters.cs @@ -78,7 +78,7 @@ public static ExpressionEmitter Prepare(BinaryOperators binaryOperator, DecodeCo extractContext.GetSymbolName(si1)) }; } - // Double = (Float) % (Float) + // Double = (Float) op (Float) if (si0.TargetType.IsFloatStackFriendlyType && si1.TargetType.IsFloatStackFriendlyType && (binaryOperator == BinaryOperators.Rem)) { @@ -105,7 +105,7 @@ public static ExpressionEmitter Prepare(BinaryOperators binaryOperator, DecodeCo } // ByRef = (Int32) + (ByRef) - if (si0.TargetType.IsInt32StackFriendlyType && si1.TargetType.IsByReference && + if (si0.TargetType.IsInt32StackFriendlyType && (si1.TargetType.IsByReference || si1.TargetType.IsArray) && (binaryOperator == BinaryOperators.Add)) { var result = decodeContext.PushStack(si1.TargetType); @@ -118,7 +118,7 @@ public static ExpressionEmitter Prepare(BinaryOperators binaryOperator, DecodeCo } // ByRef = (IntPtr) + (ByRef) - if (si0.TargetType.IsIntPtrStackFriendlyType && si1.TargetType.IsByReference && + if (si0.TargetType.IsIntPtrStackFriendlyType && (si1.TargetType.IsByReference || si1.TargetType.IsArray) && (binaryOperator == BinaryOperators.Add)) { var result = decodeContext.PushStack(si1.TargetType); @@ -131,7 +131,7 @@ public static ExpressionEmitter Prepare(BinaryOperators binaryOperator, DecodeCo } // ByRef = (ByRef) +/- (Int32|IntPtr) - if (si0.TargetType.IsByReference && + if ((si0.TargetType.IsByReference || si0.TargetType.IsArray) && (si1.TargetType.IsInt32StackFriendlyType || si1.TargetType.IsIntPtrStackFriendlyType) && ((binaryOperator == BinaryOperators.Add) || (binaryOperator == BinaryOperators.Sub))) { diff --git a/IL2C.Core/ILConveters/LdindConverters.cs b/IL2C.Core/ILConveters/LdindConverters.cs index 6b3f63de..f00684ba 100644 --- a/IL2C.Core/ILConveters/LdindConverters.cs +++ b/IL2C.Core/ILConveters/LdindConverters.cs @@ -32,7 +32,7 @@ public static ExpressionEmitter Prepare(DecodeContext decodeContext) var siFrom = decodeContext.PopStack(); // Require only managed refs - if (!siFrom.TargetType.IsByReference) + if (!(siFrom.TargetType.IsByReference || siFrom.TargetType.IsArray)) { throw new InvalidProgramSequenceException( "Invalid managed reference: Location={0}, StackType={1}", @@ -43,10 +43,22 @@ public static ExpressionEmitter Prepare(DecodeContext decodeContext) var targetType = siFrom.TargetType.ElementType; var symbol = decodeContext.PushStack(targetType); - return (extractContext, _) => new[] { string.Format( - "{0} = *{1}", - extractContext.GetSymbolName(symbol), - extractContext.GetSymbolName(siFrom)) }; + if (siFrom.TargetType.IsArray) + { + return (extractContext, _) => new[] { string.Format( + "{0} = *(({2}*){1})", + extractContext.GetSymbolName(symbol), + extractContext.GetSymbolName(siFrom), + targetType.CLanguageTypeName + ) }; + } + else + { + return (extractContext, _) => new[] { string.Format( + "{0} = *{1}", + extractContext.GetSymbolName(symbol), + extractContext.GetSymbolName(siFrom)) }; + } } } diff --git a/tests/IL2C.Core.Test.Fixture/TestFramework.cs b/tests/IL2C.Core.Test.Fixture/TestFramework.cs index c9ab3451..05b1f34b 100644 --- a/tests/IL2C.Core.Test.Fixture/TestFramework.cs +++ b/tests/IL2C.Core.Test.Fixture/TestFramework.cs @@ -403,7 +403,7 @@ await TestUtilities.CopyResourceToStreamAsync( CultureInfo.CurrentCulture = CultureInfo.InvariantCulture; CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture; rawResult = caseInfo.Method.Invoke(null, caseInfo.Arguments); - Assert.AreEqual(caseInfo.Expected, rawResult); + Assert.AreEqual(caseInfo.Expected, rawResult, "Bad MSIL, or test case!"); break; } @@ -435,7 +435,7 @@ await TestUtilities.CopyResourceToStreamAsync( /////////////////////////////////////////////// // Step 4: Verify result. - Assert.AreEqual("Success", sanitized); + Assert.AreEqual("Success", sanitized, "Compiled C code failed!"); } } } diff --git a/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs new file mode 100644 index 00000000..831e1e9b --- /dev/null +++ b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs @@ -0,0 +1,46 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// IL2C - A translator for ECMA-335 CIL/MSIL to C language. +// Copyright (c) 2016-2019 Kouji Matsui (@kozy_kekyo, @kekyo2) +// +// 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.Runtime.CompilerServices; + +namespace IL2C.ILConverters +{ + [TestCase(4, "Ldobj_test_int32", 0 * 4)] + [TestCase(3, "Ldobj_test_int32", 1 * 4)] + [TestCase(2, "Ldobj_test_int32", 2 * 4)] + [TestCase(1, "Ldobj_test_int32", 3 * 4)] + [TestCase(0, "Ldobj_test_int32", 4 * 4)] + public sealed class Ldobj + { + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern int Ldobj_test_int32i(int v, int[] vs); + + public static int Ldobj_test_int32(int v) + { + var TestInt32Values = new int[5]; + TestInt32Values[0] = 4; + TestInt32Values[1] = 3; + TestInt32Values[2] = 2; + TestInt32Values[3] = 1; + TestInt32Values[4] = 0; + return Ldobj_test_int32i(v, TestInt32Values); + } + } +} diff --git a/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il new file mode 100644 index 00000000..5bbc5de9 --- /dev/null +++ b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il @@ -0,0 +1,19 @@ +.class public IL2C.ILConverters.Ldobj +{ + .method public static int32 Ldobj_test_int32i(int32 v, int32[] vs) cil managed + { + .maxstack 2 + .locals init ( + int32[] pinned int32Values + ) + ldarg.1 + stloc.0 + ldloc.0 + ldarg.0 + add + ldc.i4.8 + add + ldobj [mscorlib]System.Int32 + ret + } +} From 8e3bac85c0147357c5d92529238a56b76066db53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Fri, 15 Oct 2021 00:37:28 +0200 Subject: [PATCH 24/36] Fix ldobj unit test --- .../ILConveters/ArithmeticalConverters.cs | 4 +- docs/supported-opcodes.md | 6 +- .../Ldobj/Ldobj.cs | 59 +++++++++++++------ .../Ldobj/Ldobj.il | 25 ++++---- 4 files changed, 60 insertions(+), 34 deletions(-) diff --git a/IL2C.Core/ILConveters/ArithmeticalConverters.cs b/IL2C.Core/ILConveters/ArithmeticalConverters.cs index 53beb4b1..deda17cd 100644 --- a/IL2C.Core/ILConveters/ArithmeticalConverters.cs +++ b/IL2C.Core/ILConveters/ArithmeticalConverters.cs @@ -105,7 +105,7 @@ public static ExpressionEmitter Prepare(BinaryOperators binaryOperator, DecodeCo } // ByRef = (Int32) + (ByRef) - if (si0.TargetType.IsInt32StackFriendlyType && (si1.TargetType.IsByReference || si1.TargetType.IsArray) && + if (si0.TargetType.IsInt32StackFriendlyType && (si1.TargetType.IsByReference) && (binaryOperator == BinaryOperators.Add)) { var result = decodeContext.PushStack(si1.TargetType); @@ -118,7 +118,7 @@ public static ExpressionEmitter Prepare(BinaryOperators binaryOperator, DecodeCo } // ByRef = (IntPtr) + (ByRef) - if (si0.TargetType.IsIntPtrStackFriendlyType && (si1.TargetType.IsByReference || si1.TargetType.IsArray) && + if (si0.TargetType.IsIntPtrStackFriendlyType && (si1.TargetType.IsByReference) && (binaryOperator == BinaryOperators.Add)) { var result = decodeContext.PushStack(si1.TargetType); diff --git a/docs/supported-opcodes.md b/docs/supported-opcodes.md index 2fbd6aab..7d82fa09 100644 --- a/docs/supported-opcodes.md +++ b/docs/supported-opcodes.md @@ -1,7 +1,7 @@ # Supported IL opcodes * Number of opcode implementations: 157 / 219 -* Number of opcode tests: 928 [81 / 219] +* Number of opcode tests: 941 [83 / 219] OpCode | Binary | Implement | Test | ILConverter |:---|:---|:---|:---|:---| @@ -153,7 +153,7 @@ OpCode | Binary | Implement | Test | ILConverter | [ldloca](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldloca) | 0xfe0d | | | | | [ldloca.s](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldloca_s) | 0x12 | Implemented | [Test [17]](../tests/IL2C.Core.Test.ILConverters/Ldloca_s) | IL2C.ILConverters.Ldloca_sConverter | | [ldnull](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldnull) | 0x14 | Implemented | [Test [3]](../tests/IL2C.Core.Test.ILConverters/Ldnull) | IL2C.ILConverters.LdnullConverter | -| [ldobj](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldobj) | 0x71 | Implemented | | IL2C.ILConverters.LdobjConverter | +| [ldobj](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldobj) | 0x71 | Implemented | [Test [5]](../tests/IL2C.Core.Test.ILConverters/Ldobj) | IL2C.ILConverters.LdobjConverter | | [ldsfld](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldsfld) | 0x7e | Implemented | [Test [16]](../tests/IL2C.Core.Test.ILConverters/Ldsfld) | IL2C.ILConverters.LdsfldConverter | | [ldsflda](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldsflda) | 0x7f | Implemented | [Test [16]](../tests/IL2C.Core.Test.ILConverters/Ldsflda) | IL2C.ILConverters.LdsfldaConverter | | [ldstr](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldstr) | 0x72 | Implemented | [Test [1]](../tests/IL2C.Core.Test.ILConverters/Ldstr) | IL2C.ILConverters.LdstrConverter | @@ -216,7 +216,7 @@ OpCode | Binary | Implement | Test | ILConverter | [sub](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.sub) | 0x59 | Implemented | [Test [11]](../tests/IL2C.Core.Test.ILConverters/Sub) | IL2C.ILConverters.SubConverter | | [sub.ovf](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.sub_ovf) | 0xda | | | | | [sub.ovf.un](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.sub_ovf_un) | 0xdb | | | | -| [switch](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.switch) | 0x45 | Implemented | | IL2C.ILConveters.SwitchConverter | +| [switch](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.switch) | 0x45 | Implemented | [Test [8]](../tests/IL2C.Core.Test.ILConverters/Switch) | IL2C.ILConveters.SwitchConverter | | [tail](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.tailcall) | 0xfe14 | | | | | [throw](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.throw) | 0x7a | Implemented | | IL2C.ILConverters.ThrowConverter | | [unaligned](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.unaligned) | 0xfe12 | | | | diff --git a/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs index 831e1e9b..27da995f 100644 --- a/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs +++ b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs @@ -22,25 +22,50 @@ namespace IL2C.ILConverters { - [TestCase(4, "Ldobj_test_int32", 0 * 4)] - [TestCase(3, "Ldobj_test_int32", 1 * 4)] - [TestCase(2, "Ldobj_test_int32", 2 * 4)] - [TestCase(1, "Ldobj_test_int32", 3 * 4)] - [TestCase(0, "Ldobj_test_int32", 4 * 4)] + [TestCase(4, "Ldobj_test_int32", 4)] + [TestCase(1, "Ldobj_test_int32", 1)] + [TestCase(0, "Ldobj_test_int32", 0)] + [TestCase(int.MinValue, "Ldobj_test_int32", int.MinValue)] + [TestCase(int.MaxValue, "Ldobj_test_int32", int.MaxValue)] + + //[TestCase("1:2 C(3,4,5)", "Ldobj_test_PointSer", "1:2 C(3,4,5)", IncludeTypes = new[] { typeof(Point) })] + //[TestCase("20:20 C(255,255,255)", "Ldobj_test_PointSer", "20:20 C(255,255,255)", IncludeTypes = new[] { typeof(Point) })] public sealed class Ldobj { + //public struct Point + //{ + // public int X, Y; + // public int R, G, B; + + // public override string ToString() + // { + // return $"{X}:{Y} C({R},{G},{B})"; + // } + + // public static Point Parse(string v) + // { + // var result = new Point(); + // var coo = v.Split(' ')[0]; + // result.X = Int32.Parse(coo.Split(':')[0]); + // result.Y = Int32.Parse(coo.Split(':')[1]); + // var col = v.Split(' ')[1].Trim(new char[] { 'C', '(', ')' }); + // result.R = Int32.Parse(col.Split(',')[0]); + // result.G = Int32.Parse(col.Split(',')[1]); + // result.B = Int32.Parse(col.Split(',')[2]); + // return result; + // } + //} + [MethodImpl(MethodImplOptions.ForwardRef)] - public static extern int Ldobj_test_int32i(int v, int[] vs); - - public static int Ldobj_test_int32(int v) - { - var TestInt32Values = new int[5]; - TestInt32Values[0] = 4; - TestInt32Values[1] = 3; - TestInt32Values[2] = 2; - TestInt32Values[3] = 1; - TestInt32Values[4] = 0; - return Ldobj_test_int32i(v, TestInt32Values); - } + public static extern int Ldobj_test_int32(int v); + + //[MethodImpl(MethodImplOptions.ForwardRef)] + //public static extern Point Ldobj_test_Point(Point v); + + //public static string Ldobj_test_PointSer(string val) + //{ + // var v = Point.Parse(val); + // return Ldobj_test_Point(v).ToString(); + //} } } diff --git a/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il index 5bbc5de9..3f69a3b8 100644 --- a/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il +++ b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il @@ -1,19 +1,20 @@ .class public IL2C.ILConverters.Ldobj { - .method public static int32 Ldobj_test_int32i(int32 v, int32[] vs) cil managed + .method public static int32 Ldobj_test_int32(int32 v) cil managed { - .maxstack 2 - .locals init ( - int32[] pinned int32Values - ) - ldarg.1 - stloc.0 - ldloc.0 - ldarg.0 - add - ldc.i4.8 - add + .maxstack 1 + ldarga.s 0 ldobj [mscorlib]System.Int32 ret } + + /* + .method public static valuetype Point Ldobj_test_Point(valuetype Point v) cil managed + { + .maxstack 1 + ldarga.s 0 + ldobj valuetype Point + ret + } + */ } From e0d75e0543c0ba654bb6dcbe1c536047f39e8cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Fri, 15 Oct 2021 09:33:16 +0200 Subject: [PATCH 25/36] More ldobj tests --- .../Ldobj/Ldobj.cs | 75 +++++++++++-------- .../Ldobj/Ldobj.il | 38 +++++++++- 2 files changed, 78 insertions(+), 35 deletions(-) diff --git a/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs index 27da995f..72f30a1d 100644 --- a/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs +++ b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs @@ -22,50 +22,63 @@ namespace IL2C.ILConverters { + public struct Point + { + public int X, Y; + public int R, G, B; + + public override string ToString() + { + return $"{X}:{Y} C({R},{G},{B})"; + } + } + [TestCase(byte.MinValue, "Ldobj_test_uint8", byte.MinValue)] + [TestCase(byte.MaxValue, "Ldobj_test_uint8", byte.MaxValue)] + + [TestCase(ushort.MinValue, "Ldobj_test_uint16", ushort.MinValue)] + [TestCase(ushort.MaxValue, "Ldobj_test_uint16", ushort.MaxValue)] + [TestCase(4, "Ldobj_test_int32", 4)] [TestCase(1, "Ldobj_test_int32", 1)] [TestCase(0, "Ldobj_test_int32", 0)] [TestCase(int.MinValue, "Ldobj_test_int32", int.MinValue)] [TestCase(int.MaxValue, "Ldobj_test_int32", int.MaxValue)] - //[TestCase("1:2 C(3,4,5)", "Ldobj_test_PointSer", "1:2 C(3,4,5)", IncludeTypes = new[] { typeof(Point) })] - //[TestCase("20:20 C(255,255,255)", "Ldobj_test_PointSer", "20:20 C(255,255,255)", IncludeTypes = new[] { typeof(Point) })] + [TestCase(4L, "Ldobj_test_int64", 4L)] + [TestCase(1L, "Ldobj_test_int64", 1L)] + [TestCase(0L, "Ldobj_test_int64", 0L)] + [TestCase(long.MinValue, "Ldobj_test_int64", long.MinValue)] + [TestCase(long.MaxValue, "Ldobj_test_int64", long.MaxValue)] + + [TestCase(ulong.MinValue, "Ldobj_test_uint64", ulong.MinValue)] + [TestCase(ulong.MaxValue, "Ldobj_test_uint64", ulong.MaxValue)] + + [TestCase("1:2 C(3,4,5)", "Ldobj_test_PointSer", 1, 2, 3, 4, 5, IncludeTypes = new[] { typeof(Ldobj), typeof(Point), typeof(Int32), typeof(Char), typeof(String) })] + [TestCase("20:20 C(255,255,255)", "Ldobj_test_PointSer", 20, 20, 255, 255, 255, IncludeTypes = new[] { typeof(Ldobj), typeof(Point), typeof(Int32), typeof(Char), typeof(String) })] public sealed class Ldobj { - //public struct Point - //{ - // public int X, Y; - // public int R, G, B; + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern byte Ldobj_test_uint8(byte v); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern ushort Ldobj_test_uint16(ushort v); - // public override string ToString() - // { - // return $"{X}:{Y} C({R},{G},{B})"; - // } + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern int Ldobj_test_int32(int v); - // public static Point Parse(string v) - // { - // var result = new Point(); - // var coo = v.Split(' ')[0]; - // result.X = Int32.Parse(coo.Split(':')[0]); - // result.Y = Int32.Parse(coo.Split(':')[1]); - // var col = v.Split(' ')[1].Trim(new char[] { 'C', '(', ')' }); - // result.R = Int32.Parse(col.Split(',')[0]); - // result.G = Int32.Parse(col.Split(',')[1]); - // result.B = Int32.Parse(col.Split(',')[2]); - // return result; - // } - //} + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern long Ldobj_test_int64(long v); [MethodImpl(MethodImplOptions.ForwardRef)] - public static extern int Ldobj_test_int32(int v); + public static extern ulong Ldobj_test_uint64(ulong v); - //[MethodImpl(MethodImplOptions.ForwardRef)] - //public static extern Point Ldobj_test_Point(Point v); + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern Point Ldobj_test_Point(Point v); - //public static string Ldobj_test_PointSer(string val) - //{ - // var v = Point.Parse(val); - // return Ldobj_test_Point(v).ToString(); - //} + public static string Ldobj_test_PointSer(int x, int y, int r, int g, int b) + { + var v = new Point() { X = x, Y = y, R = r, G = g, B = b }; + return Ldobj_test_Point(v).ToString(); + } } } diff --git a/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il index 3f69a3b8..4f21513d 100644 --- a/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il +++ b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il @@ -1,5 +1,20 @@ .class public IL2C.ILConverters.Ldobj { + .method public static uint8 Ldobj_test_uint8(uint8 v) cil managed + { + .maxstack 1 + ldarga.s 0 + ldobj [mscorlib]System.Byte + ret + } + .method public static uint16 Ldobj_test_uint16(uint16 v) cil managed + { + .maxstack 1 + ldarga.s 0 + ldobj [mscorlib]System.UInt16 + ret + } + .method public static int32 Ldobj_test_int32(int32 v) cil managed { .maxstack 1 @@ -8,13 +23,28 @@ ret } - /* - .method public static valuetype Point Ldobj_test_Point(valuetype Point v) cil managed + .method public static int64 Ldobj_test_int64(int64 v) cil managed + { + .maxstack 1 + ldarga.s 0 + ldobj [mscorlib]System.Int64 + ret + } + + .method public static uint64 Ldobj_test_uint64(uint64 v) cil managed + { + .maxstack 1 + ldarga.s 0 + ldobj [mscorlib]System.UInt64 + ret + } + + .method public static valuetype IL2C.ILConverters.Point Ldobj_test_Point(valuetype IL2C.ILConverters.Point v) cil managed { .maxstack 1 ldarga.s 0 - ldobj valuetype Point + ldobj valuetype IL2C.ILConverters.Point ret } - */ + } From 1153f48b726979839b5c1f4d55a7a1ea1e626eea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Fri, 15 Oct 2021 10:38:08 +0200 Subject: [PATCH 26/36] More Ldobj tests --- tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs | 16 ++++++++++++++++ tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs index 72f30a1d..1c17baf5 100644 --- a/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs +++ b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.cs @@ -53,6 +53,16 @@ public override string ToString() [TestCase(ulong.MinValue, "Ldobj_test_uint64", ulong.MinValue)] [TestCase(ulong.MaxValue, "Ldobj_test_uint64", ulong.MaxValue)] + [TestCase(0.0F, "Ldobj_test_float", 0.0F)] + [TestCase(-0.001F, "Ldobj_test_float", -0.001F)] + [TestCase(float.MinValue, "Ldobj_test_float", float.MinValue)] + [TestCase(float.MaxValue, "Ldobj_test_float", float.MaxValue)] + + [TestCase(0.0, "Ldobj_test_double", 0.0)] + [TestCase(-0.001, "Ldobj_test_double", -0.001)] + [TestCase(double.MinValue, "Ldobj_test_double", double.MinValue)] + [TestCase(double.MaxValue, "Ldobj_test_double", double.MaxValue)] + [TestCase("1:2 C(3,4,5)", "Ldobj_test_PointSer", 1, 2, 3, 4, 5, IncludeTypes = new[] { typeof(Ldobj), typeof(Point), typeof(Int32), typeof(Char), typeof(String) })] [TestCase("20:20 C(255,255,255)", "Ldobj_test_PointSer", 20, 20, 255, 255, 255, IncludeTypes = new[] { typeof(Ldobj), typeof(Point), typeof(Int32), typeof(Char), typeof(String) })] public sealed class Ldobj @@ -72,6 +82,12 @@ public sealed class Ldobj [MethodImpl(MethodImplOptions.ForwardRef)] public static extern ulong Ldobj_test_uint64(ulong v); + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern float Ldobj_test_float(float v); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern double Ldobj_test_double(double v); + [MethodImpl(MethodImplOptions.ForwardRef)] public static extern Point Ldobj_test_Point(Point v); diff --git a/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il index 4f21513d..a2c7f7c5 100644 --- a/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il +++ b/tests/IL2C.Core.Test.ILConverters/Ldobj/Ldobj.il @@ -39,6 +39,22 @@ ret } + .method public static float32 Ldobj_test_float(float32 v) cil managed + { + .maxstack 1 + ldarga.s 0 + ldobj [mscorlib]System.Single + ret + } + + .method public static float64 Ldobj_test_double(float64 v) cil managed + { + .maxstack 1 + ldarga.s 0 + ldobj [mscorlib]System.Double + ret + } + .method public static valuetype IL2C.ILConverters.Point Ldobj_test_Point(valuetype IL2C.ILConverters.Point v) cil managed { .maxstack 1 From 796f113dd2345f98d0d0689a5422f7ff142c0067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Sun, 17 Oct 2021 20:25:49 +0200 Subject: [PATCH 27/36] Add Stobj IL Code unit tests --- .../Stobj/Stobj.cs | 134 ++++++++++++++++++ .../Stobj/Stobj.il | 74 ++++++++++ 2 files changed, 208 insertions(+) create mode 100644 tests/IL2C.Core.Test.ILConverters/Stobj/Stobj.cs create mode 100644 tests/IL2C.Core.Test.ILConverters/Stobj/Stobj.il diff --git a/tests/IL2C.Core.Test.ILConverters/Stobj/Stobj.cs b/tests/IL2C.Core.Test.ILConverters/Stobj/Stobj.cs new file mode 100644 index 00000000..f528c86d --- /dev/null +++ b/tests/IL2C.Core.Test.ILConverters/Stobj/Stobj.cs @@ -0,0 +1,134 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// IL2C - A translator for ECMA-335 CIL/MSIL to C language. +// Copyright (c) 2016-2019 Kouji Matsui (@kozy_kekyo, @kekyo2) +// +// 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.Runtime.CompilerServices; + +namespace IL2C.ILConverters +{ + [TestCase(byte.MinValue, "Stobj_test_uint8Tst", byte.MinValue, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(byte.MaxValue, "Stobj_test_uint8Tst", byte.MaxValue, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + + [TestCase(ushort.MinValue, "Stobj_test_uint16Tst", ushort.MinValue, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(ushort.MaxValue, "Stobj_test_uint16Tst", ushort.MaxValue, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + + [TestCase(4, "Stobj_test_int32Tst", 4, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(1, "Stobj_test_int32Tst", 1, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(0, "Stobj_test_int32Tst", 0, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(int.MinValue, "Stobj_test_int32Tst", int.MinValue, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(int.MaxValue, "Stobj_test_int32Tst", int.MaxValue, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + + [TestCase(4L, "Stobj_test_int64Tst", 4L, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(1L, "Stobj_test_int64Tst", 1L, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(0L, "Stobj_test_int64Tst", 0L, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(long.MinValue, "Stobj_test_int64Tst", long.MinValue, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(long.MaxValue, "Stobj_test_int64Tst", long.MaxValue, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + + [TestCase(ulong.MinValue, "Stobj_test_uint64Tst", ulong.MinValue, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(ulong.MaxValue, "Stobj_test_uint64Tst", ulong.MaxValue, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + + [TestCase(0.0F, "Stobj_test_floatTst", 0.0F, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(-0.001F, "Stobj_test_floatTst", -0.001F, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(float.MinValue, "Stobj_test_floatTst", float.MinValue, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(float.MaxValue, "Stobj_test_floatTst", float.MaxValue, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + + [TestCase(0.0, "Stobj_test_doubleTst", 0.0, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(-0.001, "Stobj_test_doubleTst", -0.001, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(double.MinValue, "Stobj_test_doubleTst", double.MinValue, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + [TestCase(double.MaxValue, "Stobj_test_doubleTst", double.MaxValue, IncludeTypes = new[] { typeof(Stobj), typeof(Point) })] + + [TestCase("1:2 C(3,4,5)", "Stobj_test_PointSer", 1, 2, 3, 4, 5, IncludeTypes = new[] { typeof(Stobj), typeof(Point), typeof(Int32), typeof(Char), typeof(String) })] + [TestCase("20:20 C(255,255,255)", "Stobj_test_PointSer", 20, 20, 255, 255, 255, IncludeTypes = new[] { typeof(Stobj), typeof(Point), typeof(Int32), typeof(Char), typeof(String) })] + public sealed class Stobj + { + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern void Stobj_test_uint8(byte v, out byte result); + + public static byte Stobj_test_uint8Tst(byte v) + { + Stobj_test_uint8(v, out byte result); + return result; + } + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern void Stobj_test_uint16(ushort v, out ushort result); + + public static ushort Stobj_test_uint16Tst(ushort v) + { + Stobj_test_uint16(v, out ushort result); + return result; + } + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern void Stobj_test_int32(int v, out int result); + + public static int Stobj_test_int32Tst(int v) + { + Stobj_test_int32(v, out int result); + return result; + } + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern void Stobj_test_int64(long v, out long result); + + public static long Stobj_test_int64Tst(long v) + { + Stobj_test_int64(v, out long result); + return result; + } + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern void Stobj_test_uint64(ulong v, out ulong result); + + public static ulong Stobj_test_uint64Tst(ulong v) + { + Stobj_test_uint64(v, out ulong result); + return result; + } + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern void Stobj_test_float(float v, out float result); + + public static float Stobj_test_floatTst(float v) + { + Stobj_test_float(v, out float result); + return result; + } + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern void Stobj_test_double(double v, out double result); + + public static double Stobj_test_doubleTst(double v) + { + Stobj_test_double(v, out double result); + return result; + } + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern void Stobj_test_Point(Point v, out Point result); + + public static string Stobj_test_PointSer(int x, int y, int r, int g, int b) + { + var v = new Point() { X = x, Y = y, R = r, G = g, B = b }; + Stobj_test_Point(v, out Point result); + return result.ToString(); + } + + } +} diff --git a/tests/IL2C.Core.Test.ILConverters/Stobj/Stobj.il b/tests/IL2C.Core.Test.ILConverters/Stobj/Stobj.il new file mode 100644 index 00000000..f4facd70 --- /dev/null +++ b/tests/IL2C.Core.Test.ILConverters/Stobj/Stobj.il @@ -0,0 +1,74 @@ +.class public IL2C.ILConverters.Stobj +{ + .method public static void Stobj_test_uint8(uint8 v, [out] uint8& result) cil managed + { + .maxstack 2 + ldarg.s 1 + ldarg.s 0 + stobj [mscorlib]System.Byte + ret + } + + .method public static void Stobj_test_uint16(uint16 v, [out] uint16& result) cil managed + { + .maxstack 2 + ldarg.s 1 + ldarg.s 0 + stobj [mscorlib]System.UInt16 + ret + } + + .method public static void Stobj_test_int32(int32 v, [out] int32& result) cil managed + { + .maxstack 2 + ldarg.s 1 + ldarg.s 0 + stobj [mscorlib]System.Int32 + ret + } + + .method public static void Stobj_test_int64(int64 v, [out] int64& result) cil managed + { + .maxstack 2 + ldarg.s 1 + ldarg.s 0 + stobj [mscorlib]System.Int64 + ret + } + + .method public static void Stobj_test_uint64(uint64 v, [out] uint64& result) cil managed + { + .maxstack 2 + ldarg.s 1 + ldarg.s 0 + stobj [mscorlib]System.UInt64 + ret + } + + .method public static void Stobj_test_float(float32 v, [out] float32& result) cil managed + { + .maxstack 2 + ldarg.s 1 + ldarg.s 0 + stobj [mscorlib]System.Single + ret + } + + .method public static void Stobj_test_double(float64 v, [out] float64& result) cil managed + { + .maxstack 2 + ldarg.s 1 + ldarg.s 0 + stobj [mscorlib]System.Double + ret + } + + .method public static void Stobj_test_Point(valuetype IL2C.ILConverters.Point v, [out] valuetype IL2C.ILConverters.Point& result) cil managed + { + .maxstack 2 + ldarg.s 1 + ldarg.s 0 + stobj IL2C.ILConverters.Point + ret + } +} From dd832364c0d30cb28d3703d9302e2c5c8ec45e53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Sun, 17 Oct 2021 21:55:13 +0200 Subject: [PATCH 28/36] Add more TypeInitializer unit tests --- .../TypeInitializer_DefaultValues.cs | 136 +++++++++++++++ .../TypeInitializer_NonStaticClass.cs | 149 ++++++++++++++++ .../TypeInitializer_Singleton.cs | 49 ++++++ .../TypeInitializer/TypeInitializer_Struct.cs | 164 ++++++++++++++++++ 4 files changed, 498 insertions(+) create mode 100644 tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_DefaultValues.cs create mode 100644 tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_NonStaticClass.cs create mode 100644 tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_Singleton.cs create mode 100644 tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_Struct.cs diff --git a/tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_DefaultValues.cs b/tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_DefaultValues.cs new file mode 100644 index 00000000..fd1150f4 --- /dev/null +++ b/tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_DefaultValues.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IL2C.RuntimeSystems +{ + public static class TypeInitializer_DefaultValues_Field + { + public static bool BooleanValue = true; + public static readonly byte ByteValue = 10; + public static short Int16Value = 10; + public static readonly int Int32Value = 10; + public static readonly long Int64Value = 10; + public static readonly sbyte SByteValue = 10; + public static readonly ushort UInt16Value = 10; + public static uint UInt32Value = 10; + public static readonly ulong UInt64Value = 10; + public static readonly IntPtr IntPtrValue = (IntPtr)10; + public static UIntPtr UIntPtrValue = (UIntPtr)10; + public static readonly float SingleValue = 10.0f; + public static readonly double DoubleValue = 10.0; + public static readonly char CharValue = 'X'; + public static string StringValue = "StringValue"; + public static int[] Array = new[] { 1, 2, 3 }; + } + + [TestId("TypeInitializer_Defaults")] + [Description("These tests are verified the IL2C can handle the type initializer special translation cases.")] + [TestCase(true, "Bool", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase((byte)10, "Byte", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase((short)10, "Int16", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase((int)10, "Int32", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase((long)10, "Int64", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase((sbyte)10, "SByte", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase((ushort)10, "UInt16", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase((uint)10, "UInt32", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase((ulong)10, "UInt64", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase((int)10, "IntPtr", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase((uint)10, "UIntPtr", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase((float)10f, "Single", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase((double)10f, "Double", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase((char)'X', "Char", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase("StringValue", "String", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + [TestCase(true, "Array", IncludeTypes = new[] { typeof(TypeInitializer_DefaultValues_Field) })] + public sealed class TypeInitializer_DefaultValues + { + public static bool Bool() + { + return TypeInitializer_DefaultValues_Field.BooleanValue; + } + + public static byte Byte() + { + return TypeInitializer_DefaultValues_Field.ByteValue; + } + + public static short Int16() + { + return TypeInitializer_DefaultValues_Field.Int16Value; + } + + public static int Int32() + { + return TypeInitializer_DefaultValues_Field.Int32Value; + } + + public static long Int64() + { + return TypeInitializer_DefaultValues_Field.Int64Value; + } + + public static sbyte SByte() + { + return TypeInitializer_DefaultValues_Field.SByteValue; + } + + public static ushort UInt16() + { + return TypeInitializer_DefaultValues_Field.UInt16Value; + } + + public static uint UInt32() + { + return TypeInitializer_DefaultValues_Field.UInt32Value; + } + + public static ulong UInt64() + { + return TypeInitializer_DefaultValues_Field.UInt64Value; + } + + public static IntPtr IntPtr() + { + return TypeInitializer_DefaultValues_Field.IntPtrValue; + } + + public static UIntPtr UIntPtr() + { + return TypeInitializer_DefaultValues_Field.UIntPtrValue; + } + + public static float Single() + { + return TypeInitializer_DefaultValues_Field.SingleValue; + } + + public static double Double() + { + return TypeInitializer_DefaultValues_Field.DoubleValue; + } + + public static char Char() + { + return TypeInitializer_DefaultValues_Field.CharValue; + } + + public static string String() + { + return TypeInitializer_DefaultValues_Field.StringValue; + } + + public static bool Array() + { + var array = TypeInitializer_DefaultValues_Field.Array; + if (array == null) return false; + if (array.Length != 3) return false; + if (array[0] != 1) return false; + if (array[1] != 2) return false; + if (array[2] != 3) return false; + return true; + } + } +} diff --git a/tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_NonStaticClass.cs b/tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_NonStaticClass.cs new file mode 100644 index 00000000..f246a2b5 --- /dev/null +++ b/tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_NonStaticClass.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IL2C.RuntimeSystems +{ + public class TypeInitializer_NonStaticClass_Fields + { + public static bool BooleanValue; + public static readonly byte ByteValue; + public static readonly short Int16Value; + public static readonly int Int32Value; + public static readonly long Int64Value; + public static readonly sbyte SByteValue; + public static ushort UInt16Value; + public static readonly uint UInt32Value; + public static readonly ulong UInt64Value; + public static readonly IntPtr IntPtrValue; + public static readonly UIntPtr UIntPtrValue; + public static float SingleValue; + public static readonly double DoubleValue; + public static readonly char CharValue; + public static readonly string StringValue; + + static TypeInitializer_NonStaticClass_Fields() + { + BooleanValue = !BooleanValue; + ByteValue = (byte)(ByteValue + 1); + Int16Value = (short)(Int16Value + 1); + Int32Value = (int)(Int32Value + 1); + Int64Value = (long)(Int64Value + 1); + SByteValue = (sbyte)(SByteValue + 1); + UInt16Value = (ushort)(UInt16Value + 1); + UInt32Value = (uint)(UInt32Value + 1); + UInt64Value = (ulong)(UInt64Value + 1); + IntPtrValue = (IntPtr)(IntPtrValue + 1); + UIntPtrValue = (UIntPtr)(UIntPtrValue + 1); + SingleValue = (float)(SingleValue + 1); + DoubleValue = (double)(DoubleValue + 1); + CharValue = (char)(CharValue + 1); + StringValue = StringValue + "ABC"; + + DoRefInt32(ref Int32Value); + } + + private static void DoRefInt32(ref int value) + { + value += 2; + } + } + + [TestId("TypeInitializer_Non_Static_Class")] + [Description("These tests are verified the IL2C can handle the type initializer special translation cases.")] + [TestCase(true, "Bool", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + [TestCase((byte)1, "Byte", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + [TestCase((short)1, "Int16", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + [TestCase((int)3, "Int32", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + [TestCase((long)1, "Int64", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + [TestCase((sbyte)1, "SByte", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + [TestCase((ushort)1, "UInt16", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + [TestCase((uint)1, "UInt32", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + [TestCase((ulong)1, "UInt64", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + [TestCase((int)1, "IntPtr", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + [TestCase((uint)1, "UIntPtr", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + [TestCase((float)1, "Single", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + [TestCase((double)1, "Double", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + [TestCase((char)1, "Char", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + [TestCase("ABC", "String", IncludeTypes = new[] { typeof(TypeInitializer_NonStaticClass_Fields) })] + public sealed class TypeInitializer_NonStaticClass + { + public static bool Bool() + { + return TypeInitializer_NonStaticClass_Fields.BooleanValue; + } + + public static byte Byte() + { + return TypeInitializer_NonStaticClass_Fields.ByteValue; + } + + public static short Int16() + { + return TypeInitializer_NonStaticClass_Fields.Int16Value; + } + + public static int Int32() + { + return TypeInitializer_NonStaticClass_Fields.Int32Value; + } + + public static long Int64() + { + return TypeInitializer_NonStaticClass_Fields.Int64Value; + } + + public static sbyte SByte() + { + return TypeInitializer_NonStaticClass_Fields.SByteValue; + } + + public static ushort UInt16() + { + return TypeInitializer_NonStaticClass_Fields.UInt16Value; + } + + public static uint UInt32() + { + return TypeInitializer_NonStaticClass_Fields.UInt32Value; + } + + public static ulong UInt64() + { + return TypeInitializer_NonStaticClass_Fields.UInt64Value; + } + + public static IntPtr IntPtr() + { + return TypeInitializer_NonStaticClass_Fields.IntPtrValue; + } + + public static UIntPtr UIntPtr() + { + return TypeInitializer_NonStaticClass_Fields.UIntPtrValue; + } + + public static float Single() + { + return TypeInitializer_NonStaticClass_Fields.SingleValue; + } + + public static double Double() + { + return TypeInitializer_NonStaticClass_Fields.DoubleValue; + } + + public static char Char() + { + return TypeInitializer_NonStaticClass_Fields.CharValue; + } + + public static string String() + { + return TypeInitializer_NonStaticClass_Fields.StringValue; + } + } +} diff --git a/tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_Singleton.cs b/tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_Singleton.cs new file mode 100644 index 00000000..225d694b --- /dev/null +++ b/tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_Singleton.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IL2C.RuntimeSystems +{ + public class TypeInitializer_Singleton_Class + { + public int Value; + + public static TypeInitializer_Singleton_Class Default; + + static TypeInitializer_Singleton_Class() + { + Default = new TypeInitializer_Singleton_Class(); + Default.Value = 20; + } + } + + public struct TypeInitializer_Singleton_Struct + { + public int Value; + + public static TypeInitializer_Singleton_Struct Default; + + static TypeInitializer_Singleton_Struct() + { + Default = new TypeInitializer_Singleton_Struct(); + Default.Value = 10; + } + } + + [TestCase((int)20, "Default_Class_Value", IncludeTypes = new[] { typeof(TypeInitializer_Singleton_Class) })] + [TestCase((int)10, "Default_Struct_Value", IncludeTypes = new[] { typeof(TypeInitializer_Singleton_Struct) })] + public sealed class TypeInitializer_Singleton + { + public static int Default_Class_Value() + { + return TypeInitializer_Singleton_Class.Default.Value; + } + + public static int Default_Struct_Value() + { + return TypeInitializer_Singleton_Struct.Default.Value; + } + } +} diff --git a/tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_Struct.cs b/tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_Struct.cs new file mode 100644 index 00000000..2f6119b9 --- /dev/null +++ b/tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer/TypeInitializer_Struct.cs @@ -0,0 +1,164 @@ +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// IL2C - A translator for ECMA-335 CIL/MSIL to C language. +// Copyright (c) 2016-2019 Kouji Matsui (@kozy_kekyo, @kekyo2) +// +// 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.ComponentModel; + +namespace IL2C.RuntimeSystems +{ + public struct TypeInitializer_Struct_Field + { + public static readonly bool BooleanValue; + public static readonly byte ByteValue; + public static readonly short Int16Value; + public static readonly int Int32Value; + public static readonly long Int64Value; + public static readonly sbyte SByteValue; + public static ushort UInt16Value; + public static readonly uint UInt32Value; + public static readonly ulong UInt64Value; + public static IntPtr IntPtrValue; + public static readonly UIntPtr UIntPtrValue; + public static readonly float SingleValue; + public static double DoubleValue; + public static readonly char CharValue; + public static readonly string StringValue; + + static TypeInitializer_Struct_Field() + { + BooleanValue = !BooleanValue; + ByteValue = (byte)(ByteValue + 1); + Int16Value = (short)(Int16Value + 1); + Int32Value = (int)(Int32Value + 1); + Int64Value = (long)(Int64Value + 1); + SByteValue = (sbyte)(SByteValue + 1); + UInt16Value = (ushort)(UInt16Value + 1); + UInt32Value = (uint)(UInt32Value + 1); + UInt64Value = (ulong)(UInt64Value + 1); + IntPtrValue = (IntPtr)(IntPtrValue + 1); + UIntPtrValue = (UIntPtr)(UIntPtrValue + 1); + SingleValue = (float)(SingleValue + 1); + DoubleValue = (double)(DoubleValue + 1); + CharValue = (char)(CharValue + 1); + StringValue = StringValue + "ABC"; + + DoRefInt32(ref Int32Value); + } + + private static void DoRefInt32(ref int value) + { + value += 2; + } + } + + [TestId("TypeInitializer_Struct")] + [Description("These tests are verified the IL2C can handle the type initializer special translation cases.")] + [TestCase(true, "Bool", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + [TestCase((byte)1, "Byte", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + [TestCase((short)1, "Int16", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + [TestCase((int)3, "Int32", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + [TestCase((long)1, "Int64", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + [TestCase((sbyte)1, "SByte", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + [TestCase((ushort)1, "UInt16", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + [TestCase((uint)1, "UInt32", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + [TestCase((ulong)1, "UInt64", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + [TestCase((int)1, "IntPtr", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + [TestCase((uint)1, "UIntPtr", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + [TestCase((float)1, "Single", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + [TestCase((double)1, "Double", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + [TestCase((char)1, "Char", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + [TestCase("ABC", "String", IncludeTypes = new[] { typeof(TypeInitializer_Struct_Field) })] + public sealed class TypeInitializer_Struct + { + public static bool Bool() + { + return TypeInitializer_Struct_Field.BooleanValue; + } + + public static byte Byte() + { + return TypeInitializer_Struct_Field.ByteValue; + } + + public static short Int16() + { + return TypeInitializer_Struct_Field.Int16Value; + } + + public static int Int32() + { + return TypeInitializer_Struct_Field.Int32Value; + } + + public static long Int64() + { + return TypeInitializer_Struct_Field.Int64Value; + } + + public static sbyte SByte() + { + return TypeInitializer_Struct_Field.SByteValue; + } + + public static ushort UInt16() + { + return TypeInitializer_Struct_Field.UInt16Value; + } + + public static uint UInt32() + { + return TypeInitializer_Struct_Field.UInt32Value; + } + + public static ulong UInt64() + { + return TypeInitializer_Struct_Field.UInt64Value; + } + + public static IntPtr IntPtr() + { + return TypeInitializer_Struct_Field.IntPtrValue; + } + + public static UIntPtr UIntPtr() + { + return TypeInitializer_Struct_Field.UIntPtrValue; + } + + public static float Single() + { + return TypeInitializer_Struct_Field.SingleValue; + } + + public static double Double() + { + return TypeInitializer_Struct_Field.DoubleValue; + } + + public static char Char() + { + return TypeInitializer_Struct_Field.CharValue; + } + + public static string String() + { + return TypeInitializer_Struct_Field.StringValue; + } + } +} From 73afbfb15ebf749e56fd2c23eb00dd98bd1bcc23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Mon, 18 Oct 2021 10:04:42 +0200 Subject: [PATCH 29/36] Add Shr and Shr.un IL Code unit tests + fix for it's converter to make C behave more like C# --- .../ILConveters/ArithmeticalConverters.cs | 35 +++++++- tests/IL2C.Core.Test.ILConverters/Shr/Shr.cs | 88 +++++++++++++++++++ tests/IL2C.Core.Test.ILConverters/Shr/Shr.il | 74 ++++++++++++++++ .../Shr_un/Shr_un.cs | 84 ++++++++++++++++++ .../Shr_un/Shr_un.il | 74 ++++++++++++++++ 5 files changed, 352 insertions(+), 3 deletions(-) create mode 100644 tests/IL2C.Core.Test.ILConverters/Shr/Shr.cs create mode 100644 tests/IL2C.Core.Test.ILConverters/Shr/Shr.il create mode 100644 tests/IL2C.Core.Test.ILConverters/Shr_un/Shr_un.cs create mode 100644 tests/IL2C.Core.Test.ILConverters/Shr_un/Shr_un.il diff --git a/IL2C.Core/ILConveters/ArithmeticalConverters.cs b/IL2C.Core/ILConveters/ArithmeticalConverters.cs index deda17cd..76c53fa2 100644 --- a/IL2C.Core/ILConveters/ArithmeticalConverters.cs +++ b/IL2C.Core/ILConveters/ArithmeticalConverters.cs @@ -22,6 +22,7 @@ using Mono.Cecil.Cil; using IL2C.Translators; +using IL2C.Metadata; namespace IL2C.ILConverters { @@ -275,7 +276,7 @@ internal abstract class ShiftConverter : InlineNoneConverter { public abstract ShiftDirection Direction { get; } - public override ExpressionEmitter Prepare(DecodeContext decodeContext) + public ExpressionEmitter Prepare(DecodeContext decodeContext, Func cast) { var si1 = decodeContext.PopStack(); var si0 = decodeContext.PopStack(); @@ -287,13 +288,26 @@ public override ExpressionEmitter Prepare(DecodeContext decodeContext) si0.TargetType.FriendlyName); var result = decodeContext.PushStack(si0.TargetType); - - return (extractContext, _) => new[] { string.Format( + + if (cast == null) + { + return (extractContext, _) => new[] { string.Format( "{0} = {1} {2} {3}", extractContext.GetSymbolName(result), extractContext.GetSymbolName(si0), Direction == ShiftDirection.Left ? "<<" : ">>", extractContext.GetSymbolName(si1)) }; + } + else + { + return (extractContext, _) => new[] { string.Format( + "{0} = ({4}){1} {2} {3}", + extractContext.GetSymbolName(result), + extractContext.GetSymbolName(si0), + Direction == ShiftDirection.Left ? "<<" : ">>", + extractContext.GetSymbolName(si1), + cast(si0)) }; + } } } @@ -302,6 +316,11 @@ internal sealed class ShiftRightConverter : ShiftConverter public override OpCode OpCode => OpCodes.Shr; public override ShiftDirection Direction => ShiftDirection.Right; + + public override ExpressionEmitter Prepare(DecodeContext decodeContext) + { + return Prepare(decodeContext, si => si.TargetType.IsInt32StackFriendlyType ? "int32_t" : "int64_t"); + } } internal sealed class ShiftLeftConverter : ShiftConverter @@ -309,6 +328,11 @@ internal sealed class ShiftLeftConverter : ShiftConverter public override OpCode OpCode => OpCodes.Shl; public override ShiftDirection Direction => ShiftDirection.Left; + + public override ExpressionEmitter Prepare(DecodeContext decodeContext) + { + return Prepare(decodeContext, null); + } } internal sealed class ShiftRightUnConverter : ShiftConverter @@ -316,6 +340,11 @@ internal sealed class ShiftRightUnConverter : ShiftConverter public override OpCode OpCode => OpCodes.Shr_Un; public override ShiftDirection Direction => ShiftDirection.Right; + + public override ExpressionEmitter Prepare(DecodeContext decodeContext) + { + return Prepare(decodeContext, si => si.TargetType.IsInt32StackFriendlyType ? "uint32_t" : "uint64_t"); + } } internal sealed class NegConverter : InlineNoneConverter diff --git a/tests/IL2C.Core.Test.ILConverters/Shr/Shr.cs b/tests/IL2C.Core.Test.ILConverters/Shr/Shr.cs new file mode 100644 index 00000000..0e5a3f37 --- /dev/null +++ b/tests/IL2C.Core.Test.ILConverters/Shr/Shr.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace IL2C.ILConverters +{ + // Arithmetic Shift right (with sign) + // Warning!!! MSIL always operates for bit storage on Int32, or Int64 + // and as it seems, smaller unsigned values (uint8 & uint16) will never + // be able to set the int32 highest bit => they will operate as logical shift right. + // On the other hand: uint32 and uint64 are still operated as arithmetic shift. + [TestCase((byte)123, "ShrByte", (byte)123, 0)] + [TestCase((byte)0, "ShrByte", (byte)1, 1)] + [TestCase((byte)(Byte.MaxValue - 1) / 2, "ShrByte", (byte)Byte.MaxValue, 1)] + [TestCase((byte)(Byte.MaxValue - 1) / 4, "ShrByte", (byte)Byte.MaxValue, 2)] + + [TestCase((sbyte)123, "ShrSByte", (sbyte)123, 0)] + [TestCase((sbyte)0, "ShrSByte", (sbyte)1, 1)] + [TestCase((sbyte)-1, "ShrSByte", (sbyte)-1, 1)] + [TestCase((sbyte)-1, "ShrSByte", (sbyte)-5, 10)] + [TestCase((sbyte)(SByte.MaxValue - 1) / 2, "ShrSByte", (sbyte)SByte.MaxValue, 1)] + [TestCase((sbyte)(SByte.MaxValue - 1) / 4, "ShrSByte", (sbyte)SByte.MaxValue, 2)] + + [TestCase((short)123, "ShrShort", (short)123, 0)] + [TestCase((short)0, "ShrShort", (short)1, 1)] + [TestCase((short)-1, "ShrShort", (short)-1, 1)] + [TestCase((short)-1, "ShrShort", (short)-5, 10)] + [TestCase((short)(Int16.MaxValue - 1) / 2, "ShrShort", (short)Int16.MaxValue, 1)] + [TestCase((short)(Int16.MaxValue - 1) / 4, "ShrShort", (short)Int16.MaxValue, 2)] + + [TestCase((ushort)123, "ShrUshort", (ushort)123, 0)] + [TestCase((ushort)0, "ShrUshort", (ushort)1, 1)] + [TestCase((ushort)(UInt16.MaxValue - 1) / 2, "ShrUshort", (ushort)UInt16.MaxValue, 1)] + [TestCase((ushort)(UInt16.MaxValue - 1) / 4, "ShrUshort", (ushort)UInt16.MaxValue, 2)] + + [TestCase((int)123, "ShrInt", (int)123, 0)] + [TestCase((int)0, "ShrInt", (int)1, 1)] + [TestCase((int)-1, "ShrInt", (int)-1, 1)] + [TestCase((int)-1, "ShrInt", (int)-5, 10)] + [TestCase((int)(Int32.MaxValue - 1) / 2, "ShrInt", (int)Int32.MaxValue, 1)] + [TestCase((int)(Int32.MaxValue - 1) / 4, "ShrInt", (int)Int32.MaxValue, 2)] + + [TestCase((uint)123, "ShrUInt", (uint)123, 0)] + [TestCase((uint)0, "ShrUInt", (uint)1, 1)] + [TestCase((uint)UInt32.MaxValue, "ShrUInt", (uint)UInt32.MaxValue, 1)] + [TestCase((uint)UInt32.MaxValue, "ShrUInt", (uint)UInt32.MaxValue, 2)] + + [TestCase((long)123, "ShrLong", (long)123, 0)] + [TestCase((long)0, "ShrLong", (long)1, 1)] + [TestCase((long)-1, "ShrLong", (long)-1, 1)] + [TestCase((long)-1, "ShrLong", (long)-5, 10)] + [TestCase((long)(Int64.MaxValue - 1) / 2, "ShrLong", (long)Int64.MaxValue, 1)] + [TestCase((long)(Int64.MaxValue - 1) / 4, "ShrLong", (long)Int64.MaxValue, 2)] + + [TestCase((ulong)123, "ShrUlong", (ulong)123, 0)] + [TestCase((ulong)0, "ShrUlong", (ulong)1, 1)] + [TestCase((ulong)UInt64.MaxValue, "ShrUlong", (ulong)UInt64.MaxValue, 1)] + [TestCase((ulong)UInt64.MaxValue, "ShrUlong", (ulong)UInt64.MaxValue, 2)] + public sealed class Shr + { + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern byte ShrByte(byte v, int num); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern sbyte ShrSByte(sbyte v, int num); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern short ShrShort(short v, int num); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern ushort ShrUshort(ushort v, int num); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern int ShrInt(int v, int num); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern uint ShrUInt(uint v, int num); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern long ShrLong(long v, int num); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern ulong ShrUlong(ulong v, int num); + } +} diff --git a/tests/IL2C.Core.Test.ILConverters/Shr/Shr.il b/tests/IL2C.Core.Test.ILConverters/Shr/Shr.il new file mode 100644 index 00000000..d54fcfea --- /dev/null +++ b/tests/IL2C.Core.Test.ILConverters/Shr/Shr.il @@ -0,0 +1,74 @@ +.class public IL2C.ILConverters.Shr +{ + .method public static uint8 ShrByte(uint8 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr + ret + } + + .method public static int8 ShrSByte(int8 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr + ret + } + + .method public static int16 ShrShort(int16 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr + ret + } + + .method public static uint16 ShrUshort(uint16 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr + ret + } + + .method public static int32 ShrInt(int32 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr + ret + } + + .method public static uint32 ShrUInt(uint32 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr + ret + } + + .method public static int64 ShrLong(int64 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr + ret + } + + .method public static uint64 ShrUlong(uint64 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr + ret + } +} diff --git a/tests/IL2C.Core.Test.ILConverters/Shr_un/Shr_un.cs b/tests/IL2C.Core.Test.ILConverters/Shr_un/Shr_un.cs new file mode 100644 index 00000000..ae5f8eb4 --- /dev/null +++ b/tests/IL2C.Core.Test.ILConverters/Shr_un/Shr_un.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace IL2C.ILConverters +{ + // Logical Shift right (without sign) + [TestCase((byte)123, "ShrByte", (byte)123, 0)] + [TestCase((byte)0, "ShrByte", (byte)1, 1)] + [TestCase((byte)(Byte.MaxValue - 1) / 2, "ShrByte", (byte)Byte.MaxValue, 1)] + [TestCase((byte)(Byte.MaxValue - 1) / 4, "ShrByte", (byte)Byte.MaxValue, 2)] + + [TestCase((sbyte)123, "ShrSByte", (sbyte)123, 0)] + [TestCase((sbyte)0, "ShrSByte", (sbyte)1, 1)] + [TestCase((sbyte)-1, "ShrSByte", (sbyte)-1, 1)] + [TestCase((sbyte)-1, "ShrSByte", (sbyte)-5, 10)] + [TestCase((sbyte)(SByte.MaxValue - 1) / 2, "ShrSByte", (sbyte)SByte.MaxValue, 1)] + [TestCase((sbyte)(SByte.MaxValue - 1) / 4, "ShrSByte", (sbyte)SByte.MaxValue, 2)] + + [TestCase((short)123, "ShrShort", (short)123, 0)] + [TestCase((short)0, "ShrShort", (short)1, 1)] + [TestCase((short)-1, "ShrShort", (short)-1, 1)] + [TestCase((short)-1, "ShrShort", (short)-5, 10)] + [TestCase((short)(Int16.MaxValue - 1) / 2, "ShrShort", (short)Int16.MaxValue, 1)] + [TestCase((short)(Int16.MaxValue - 1) / 4, "ShrShort", (short)Int16.MaxValue, 2)] + + [TestCase((ushort)123, "ShrUshort", (ushort)123, 0)] + [TestCase((ushort)0, "ShrUshort", (ushort)1, 1)] + [TestCase((ushort)(UInt16.MaxValue - 1) / 2, "ShrUshort", (ushort)UInt16.MaxValue, 1)] + [TestCase((ushort)(UInt16.MaxValue - 1) / 4, "ShrUshort", (ushort)UInt16.MaxValue, 2)] + + [TestCase((int)123, "ShrInt", (int)123, 0)] + [TestCase((int)0, "ShrInt", (int)1, 1)] + [TestCase((int)0x7FFFFFFF, "ShrInt", (int)-1, 1)] + [TestCase((int)0x003FFFFF, "ShrInt", (int)-5, 10)] + [TestCase((int)(Int32.MaxValue - 1) / 2, "ShrInt", (int)Int32.MaxValue, 1)] + [TestCase((int)(Int32.MaxValue - 1) / 4, "ShrInt", (int)Int32.MaxValue, 2)] + + [TestCase((uint)123, "ShrUInt", (uint)123, 0)] + [TestCase((uint)0, "ShrUInt", (uint)1, 1)] + [TestCase((uint)0x7FFFFFFF, "ShrUInt", (uint)UInt32.MaxValue, 1)] + [TestCase((uint)0x3FFFFFFF, "ShrUInt", (uint)UInt32.MaxValue, 2)] + + [TestCase((long)123, "ShrLong", (long)123, 0)] + [TestCase((long)0, "ShrLong", (long)1, 1)] + [TestCase((long)0x7FFFFFFFFFFFFFFF, "ShrLong", (long)-1, 1)] + [TestCase((long)0x003FFFFFFFFFFFFF, "ShrLong", (long)-5, 10)] + [TestCase((long)(Int64.MaxValue - 1) / 2, "ShrLong", (long)Int64.MaxValue, 1)] + [TestCase((long)(Int64.MaxValue - 1) / 4, "ShrLong", (long)Int64.MaxValue, 2)] + + [TestCase((ulong)123, "ShrUlong", (ulong)123, 0)] + [TestCase((ulong)0, "ShrUlong", (ulong)1, 1)] + [TestCase((ulong)0x7FFFFFFFFFFFFFFF, "ShrUlong", (ulong)UInt64.MaxValue, 1)] + [TestCase((ulong)0x3FFFFFFFFFFFFFFF, "ShrUlong", (ulong)UInt64.MaxValue, 2)] + public sealed class Shr_un + { + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern byte ShrByte(byte v, int num); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern sbyte ShrSByte(sbyte v, int num); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern short ShrShort(short v, int num); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern ushort ShrUshort(ushort v, int num); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern int ShrInt(int v, int num); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern uint ShrUInt(uint v, int num); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern long ShrLong(long v, int num); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern ulong ShrUlong(ulong v, int num); + } +} diff --git a/tests/IL2C.Core.Test.ILConverters/Shr_un/Shr_un.il b/tests/IL2C.Core.Test.ILConverters/Shr_un/Shr_un.il new file mode 100644 index 00000000..bc362534 --- /dev/null +++ b/tests/IL2C.Core.Test.ILConverters/Shr_un/Shr_un.il @@ -0,0 +1,74 @@ +.class public IL2C.ILConverters.Shr_un +{ + .method public static uint8 ShrByte(uint8 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr.un + ret + } + + .method public static int8 ShrSByte(int8 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr.un + ret + } + + .method public static int16 ShrShort(int16 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr.un + ret + } + + .method public static uint16 ShrUshort(uint16 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr.un + ret + } + + .method public static int32 ShrInt(int32 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr.un + ret + } + + .method public static uint32 ShrUInt(uint32 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr.un + ret + } + + .method public static int64 ShrLong(int64 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr.un + ret + } + + .method public static uint64 ShrUlong(uint64 v, int32 num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr.un + ret + } +} From a28587a883a470ea24db634e88d0888da44b2d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Mon, 18 Oct 2021 11:06:07 +0200 Subject: [PATCH 30/36] Updated supported-opcodes.md & supported-runtime-system-features.md --- docs/supported-opcodes.md | 12 ++++++------ docs/supported-runtime-system-features.md | 4 ++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/supported-opcodes.md b/docs/supported-opcodes.md index 981ea69c..29e95787 100644 --- a/docs/supported-opcodes.md +++ b/docs/supported-opcodes.md @@ -1,7 +1,7 @@ # Supported IL opcodes -* Number of opcode implementations: 140 / 219 -* Number of opcode tests: 930 [81 / 219] +* Number of opcode implementations: 157 / 219 +* Number of opcode tests: 1070 [86 / 219] OpCode | Binary | Implement | Test | ILConverter |:---|:---|:---|:---|:---| @@ -153,7 +153,7 @@ OpCode | Binary | Implement | Test | ILConverter | [ldloca](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldloca) | 0xfe0d | | | | | [ldloca.s](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldloca_s) | 0x12 | Implemented | [Test [17]](../tests/IL2C.Core.Test.ILConverters/Ldloca_s) | IL2C.ILConverters.Ldloca_sConverter | | [ldnull](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldnull) | 0x14 | Implemented | [Test [3]](../tests/IL2C.Core.Test.ILConverters/Ldnull) | IL2C.ILConverters.LdnullConverter | -| [ldobj](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldobj) | 0x71 | Implemented | [Test [5]](../tests/IL2C.Core.Test.ILConverters/Ldobj) | IL2C.ILConverters.LdobjConverter | +| [ldobj](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldobj) | 0x71 | Implemented | [Test [26]](../tests/IL2C.Core.Test.ILConverters/Ldobj) | IL2C.ILConverters.LdobjConverter | | [ldsfld](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldsfld) | 0x7e | Implemented | [Test [16]](../tests/IL2C.Core.Test.ILConverters/Ldsfld) | IL2C.ILConverters.LdsfldConverter | | [ldsflda](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldsflda) | 0x7f | Implemented | [Test [16]](../tests/IL2C.Core.Test.ILConverters/Ldsflda) | IL2C.ILConverters.LdsfldaConverter | | [ldstr](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldstr) | 0x72 | Implemented | [Test [1]](../tests/IL2C.Core.Test.ILConverters/Ldstr) | IL2C.ILConverters.LdstrConverter | @@ -182,8 +182,8 @@ OpCode | Binary | Implement | Test | ILConverter | [ret](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ret) | 0x2a | Implemented | [Test [6]](../tests/IL2C.Core.Test.ILConverters/Ret) | IL2C.ILConverters.RetConverter | | [rethrow](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.rethrow) | 0xfe1a | Implemented | | IL2C.ILConverters.RethrowConverter | | [shl](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.shl) | 0x62 | Implemented | | IL2C.ILConverters.ShiftLeftConverter | -| [shr](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.shr) | 0x63 | Implemented | | IL2C.ILConverters.ShiftRightConverter | -| [shr.un](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.shr_un) | 0x64 | Implemented | | IL2C.ILConverters.ShiftRightUnConverter | +| [shr](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.shr) | 0x63 | Implemented | [Test [40]](../tests/IL2C.Core.Test.ILConverters/Shr) | IL2C.ILConverters.ShiftRightConverter | +| [shr.un](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.shr_un) | 0x64 | Implemented | [Test [40]](../tests/IL2C.Core.Test.ILConverters/Shr_un) | IL2C.ILConverters.ShiftRightUnConverter | | [sizeof](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.sizeof) | 0xfe1c | Implemented | | IL2C.ILConverters.SizeofConverter | | [starg](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.starg) | 0xfe0b | Implemented | | IL2C.ILConverters.StargConverter | | [starg.s](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.starg_s) | 0x10 | Implemented | | IL2C.ILConverters.StargSConverter | @@ -211,7 +211,7 @@ OpCode | Binary | Implement | Test | ILConverter | [stloc.2](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stloc_2) | 0xc | Implemented | [Test [16]](../tests/IL2C.Core.Test.ILConverters/Stloc_2) | IL2C.ILConverters.Stloc_2Converter | | [stloc.3](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stloc_3) | 0xd | Implemented | [Test [16]](../tests/IL2C.Core.Test.ILConverters/Stloc_3) | IL2C.ILConverters.Stloc_3Converter | | [stloc.s](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stloc_s) | 0x13 | Implemented | [Test [17]](../tests/IL2C.Core.Test.ILConverters/Stloc_s) | IL2C.ILConverters.Stloc_SConverter | -| [stobj](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stobj) | 0x81 | | | | +| [stobj](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stobj) | 0x81 | Implemented | [Test [26]](../tests/IL2C.Core.Test.ILConverters/Stobj) | IL2C.ILConverters.StobjConverter | | [stsfld](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.stsfld) | 0x80 | Implemented | [Test [16]](../tests/IL2C.Core.Test.ILConverters/Stsfld) | IL2C.ILConverters.StsfldConverter | | [sub](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.sub) | 0x59 | Implemented | [Test [11]](../tests/IL2C.Core.Test.ILConverters/Sub) | IL2C.ILConverters.SubConverter | | [sub.ovf](https://docs.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.sub_ovf) | 0xda | | | | diff --git a/docs/supported-runtime-system-features.md b/docs/supported-runtime-system-features.md index ddfb72a1..fd4156de 100644 --- a/docs/supported-runtime-system-features.md +++ b/docs/supported-runtime-system-features.md @@ -12,5 +12,9 @@ Feature | Test | Descrition | Interoperability | [Test [5]](../tests/IL2C.Core.Test.RuntimeSystems/Interoperability) | These tests are verified the IL2C manages interoperability with the P/Invoke adn IL2C/Invoke method and internalcall method. | | Threading | [Test [11]](../tests/IL2C.Core.Test.RuntimeSystems/Threading) | These tests are verified the IL2C can handle threading features. | | TypeInitializer | [Test [15]](../tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer) | These tests are verified the IL2C can handle the type initializer special translation cases. | +| TypeInitializer_Defaults | [Test [16]](../tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer_Defaults) | These tests are verified the IL2C can handle the type initializer special translation cases. | +| TypeInitializer_Non_Static_Class | [Test [15]](../tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer_Non_Static_Class) | These tests are verified the IL2C can handle the type initializer special translation cases. | +| TypeInitializer_Singleton | [Test [2]](../tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer_Singleton) | | +| TypeInitializer_Struct | [Test [15]](../tests/IL2C.Core.Test.RuntimeSystems/TypeInitializer_Struct) | These tests are verified the IL2C can handle the type initializer special translation cases. | | TypeRelations | [Test [95]](../tests/IL2C.Core.Test.RuntimeSystems/TypeRelations) | CLR type system contains single-inheritance class types and multiple-implementation interface types. These tests are verified the IL2C can handle the member methods both simple instance methods and complex overriden virtual methods. | | ValueTypes | [Test [18]](../tests/IL2C.Core.Test.RuntimeSystems/ValueTypes) | Value types are specialized types at the .NET type system. Because the type inherited from the System.ValueType (objref type), all method has the managed pointer at the arg0 and these instances will box and apply the pseudo vptrs. These tests are verified the IL2C can handle value types. | From 76eeee7984011353583f6f17c544e2f77c5686e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Tue, 19 Oct 2021 08:09:04 +0200 Subject: [PATCH 31/36] Add NOT ILCode unit tests --- tests/IL2C.Core.Test.ILConverters/Not/Not.cs | 52 ++++++++++++ tests/IL2C.Core.Test.ILConverters/Not/Not.il | 83 ++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 tests/IL2C.Core.Test.ILConverters/Not/Not.cs create mode 100644 tests/IL2C.Core.Test.ILConverters/Not/Not.il diff --git a/tests/IL2C.Core.Test.ILConverters/Not/Not.cs b/tests/IL2C.Core.Test.ILConverters/Not/Not.cs new file mode 100644 index 00000000..c2de95fd --- /dev/null +++ b/tests/IL2C.Core.Test.ILConverters/Not/Not.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace IL2C.ILConverters +{ + [TestCase(~(sbyte)0x12, "Not_int8", (sbyte)0x12)] + [TestCase(~(byte)0x12, "Not_uint8", (byte)0x12)] + [TestCase(~(short)0x1234, "Not_int16", (short)0x1234)] + [TestCase(~(ushort)0x1234, "Not_uint16", (ushort)0x1234)] + [TestCase(~(int)0x12345678, "Not_int32", (int)0x12345678)] + [TestCase(~(uint)0x12345678, "Not_uint32", (uint)0x12345678)] + [TestCase(~(long)0x12345678, "Not_int64", (long)0x12345678)] + [TestCase(~(ulong)0x12345678, "Not_uint64", (ulong)0x12345678)] + [TestCase(-1, "Not_IntPtr", 0)] + [TestCase(-1, "Not_UIntPtr", 0)] + public sealed class Not + { + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern sbyte Not_int8(sbyte v); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern byte Not_uin8(byte v); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern short Not_int16(short v); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern ushort Not_uint16(short v); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern int Not_int32(int v); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern uint Not_uint32(uint v); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern long Not_int64(long v); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern ulong Not_uint64(ulong v); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern IntPtr Not_IntPtr(IntPtr v); + + [MethodImpl(MethodImplOptions.ForwardRef)] + public static extern UIntPtr Not_UIntPtr(UIntPtr v); + } +} diff --git a/tests/IL2C.Core.Test.ILConverters/Not/Not.il b/tests/IL2C.Core.Test.ILConverters/Not/Not.il new file mode 100644 index 00000000..cfbcbe9a --- /dev/null +++ b/tests/IL2C.Core.Test.ILConverters/Not/Not.il @@ -0,0 +1,83 @@ +.class public IL2C.ILConverters.Not +{ + .method public static int8 Not_int8(int8 v) cil managed + { + .maxstack 1 + ldarg.0 + not + ret + } + + .method public static uint8 Not_uint8(uint8 v) cil managed + { + .maxstack 1 + ldarg.0 + not + ret + } + + .method public static int16 Not_int16(int16 v) cil managed + { + .maxstack 1 + ldarg.0 + not + ret + } + + .method public static uint16 Not_uint16(uint16 v) cil managed + { + .maxstack 1 + ldarg.0 + not + ret + } + + .method public static int32 Not_int32(int32 v) cil managed + { + .maxstack 1 + ldarg.0 + not + ret + } + + .method public static uint32 Not_uint32(uint32 v) cil managed + { + .maxstack 1 + ldarg.0 + not + ret + } + + .method public static int64 Not_int64(int64 v) cil managed + { + .maxstack 1 + ldarg.0 + not + ret + } + + .method public static uint64 Not_uint64(uint64 v) cil managed + { + .maxstack 1 + ldarg.0 + not + ret + } + /* + .method public static native int Not_IntPtr(native int v) cil managed + { + .maxstack 1 + ldarg.0 + not + ret + } + + .method public static native uint Not_UIntPtr(native uint v) cil managed + { + .maxstack 1 + ldarg.0 + not + ret + } + */ +} From 2b7b595fd3866dd0a47c46ce9995caa3ac998dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Tue, 19 Oct 2021 09:09:21 +0200 Subject: [PATCH 32/36] Remove breaking unit tests --- tests/IL2C.Core.Test.ILConverters/Not/Not.cs | 25 +++++----- tests/IL2C.Core.Test.ILConverters/Not/Not.il | 51 +------------------- 2 files changed, 15 insertions(+), 61 deletions(-) diff --git a/tests/IL2C.Core.Test.ILConverters/Not/Not.cs b/tests/IL2C.Core.Test.ILConverters/Not/Not.cs index c2de95fd..11341003 100644 --- a/tests/IL2C.Core.Test.ILConverters/Not/Not.cs +++ b/tests/IL2C.Core.Test.ILConverters/Not/Not.cs @@ -7,23 +7,26 @@ namespace IL2C.ILConverters { - [TestCase(~(sbyte)0x12, "Not_int8", (sbyte)0x12)] - [TestCase(~(byte)0x12, "Not_uint8", (byte)0x12)] - [TestCase(~(short)0x1234, "Not_int16", (short)0x1234)] - [TestCase(~(ushort)0x1234, "Not_uint16", (ushort)0x1234)] + // Breaks unit testing framework??? + //[TestCase(~(sbyte)0x12, "Not_int8", (sbyte)0x12)] + //[TestCase(~(byte)0x12, "Not_uint8", (byte)0x12)] + //[TestCase(~(short)0x1234, "Not_int16", (short)0x1234)] + //[TestCase(~(ushort)0x1234, "Not_uint16", (ushort)0x1234)] [TestCase(~(int)0x12345678, "Not_int32", (int)0x12345678)] [TestCase(~(uint)0x12345678, "Not_uint32", (uint)0x12345678)] [TestCase(~(long)0x12345678, "Not_int64", (long)0x12345678)] [TestCase(~(ulong)0x12345678, "Not_uint64", (ulong)0x12345678)] - [TestCase(-1, "Not_IntPtr", 0)] - [TestCase(-1, "Not_UIntPtr", 0)] + // If I implement in IL, whole testing system goes down. + // C# compiler says: CS0023: Operator '~' cannot be applied to operand of type 'IntPtr' + //[TestCase(~IntPtr.Zero, "not_intptr", 0)] + //[TestCase(-1, "not_uintptr", (uint)0)] public sealed class Not { [MethodImpl(MethodImplOptions.ForwardRef)] public static extern sbyte Not_int8(sbyte v); [MethodImpl(MethodImplOptions.ForwardRef)] - public static extern byte Not_uin8(byte v); + public static extern byte Not_uint8(byte v); [MethodImpl(MethodImplOptions.ForwardRef)] public static extern short Not_int16(short v); @@ -43,10 +46,10 @@ public sealed class Not [MethodImpl(MethodImplOptions.ForwardRef)] public static extern ulong Not_uint64(ulong v); - [MethodImpl(MethodImplOptions.ForwardRef)] - public static extern IntPtr Not_IntPtr(IntPtr v); + //[MethodImpl(MethodImplOptions.ForwardRef)] + //public static extern IntPtr Not_IntPtr(int v); - [MethodImpl(MethodImplOptions.ForwardRef)] - public static extern UIntPtr Not_UIntPtr(UIntPtr v); + //[MethodImpl(MethodImplOptions.ForwardRef)] + //public static extern UIntPtr Not_UIntPtr(uint v); } } diff --git a/tests/IL2C.Core.Test.ILConverters/Not/Not.il b/tests/IL2C.Core.Test.ILConverters/Not/Not.il index cfbcbe9a..3ae7f271 100644 --- a/tests/IL2C.Core.Test.ILConverters/Not/Not.il +++ b/tests/IL2C.Core.Test.ILConverters/Not/Not.il @@ -1,37 +1,5 @@ .class public IL2C.ILConverters.Not { - .method public static int8 Not_int8(int8 v) cil managed - { - .maxstack 1 - ldarg.0 - not - ret - } - - .method public static uint8 Not_uint8(uint8 v) cil managed - { - .maxstack 1 - ldarg.0 - not - ret - } - - .method public static int16 Not_int16(int16 v) cil managed - { - .maxstack 1 - ldarg.0 - not - ret - } - - .method public static uint16 Not_uint16(uint16 v) cil managed - { - .maxstack 1 - ldarg.0 - not - ret - } - .method public static int32 Not_int32(int32 v) cil managed { .maxstack 1 @@ -39,7 +7,7 @@ not ret } - + .method public static uint32 Not_uint32(uint32 v) cil managed { .maxstack 1 @@ -63,21 +31,4 @@ not ret } - /* - .method public static native int Not_IntPtr(native int v) cil managed - { - .maxstack 1 - ldarg.0 - not - ret - } - - .method public static native uint Not_UIntPtr(native uint v) cil managed - { - .maxstack 1 - ldarg.0 - not - ret - } - */ } From bc1476f7f3f676ac34e64e6855595be5a54de03f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Tue, 19 Oct 2021 10:12:17 +0200 Subject: [PATCH 33/36] Refactor ArithmeticalConverters/ NotConverter according to guidelines --- IL2C.Core/ILConveters/ArithmeticalConverters.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/IL2C.Core/ILConveters/ArithmeticalConverters.cs b/IL2C.Core/ILConveters/ArithmeticalConverters.cs index 76c53fa2..35d77529 100644 --- a/IL2C.Core/ILConveters/ArithmeticalConverters.cs +++ b/IL2C.Core/ILConveters/ArithmeticalConverters.cs @@ -243,22 +243,14 @@ internal sealed class NotConverter : InlineNoneConverter public override ExpressionEmitter Prepare(DecodeContext decodeContext) { var si0 = decodeContext.PopStack(); - Metadata.ILocalVariableInformation result; - if (si0.TargetType.IsFloatStackFriendlyType || si0.TargetType.IsByReference) + if (!(si0.TargetType.IsIntegerPrimitive && !si0.TargetType.IsCharType)) throw new InvalidProgramSequenceException( "Invalid arithmetical NOT operation: Location={0}, Type0={1}", decodeContext.CurrentCode.RawLocation, si0.TargetType.FriendlyName); - if (si0.TargetType.IsInt32StackFriendlyType) - { - result = decodeContext.PushStack(decodeContext.PrepareContext.MetadataContext.Int32Type); - } - else - { // Int64 = ~(Int64) - result = decodeContext.PushStack(decodeContext.PrepareContext.MetadataContext.Int64Type); - } + var result = decodeContext.PushStack(si0.TargetType); return (extractContext, _) => new[] { string.Format( "{0} = ~{1}", From 9753e440ad6db252850e199245f73f905a9f7dc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Tue, 19 Oct 2021 11:16:00 +0200 Subject: [PATCH 34/36] Tried to add more Shr unit tests, but discovery fails then for all others as well --- tests/IL2C.Core.Test.ILConverters/Shr/Shr.cs | 12 ++++++++++++ tests/IL2C.Core.Test.ILConverters/Shr/Shr.il | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/tests/IL2C.Core.Test.ILConverters/Shr/Shr.cs b/tests/IL2C.Core.Test.ILConverters/Shr/Shr.cs index 0e5a3f37..89d8a907 100644 --- a/tests/IL2C.Core.Test.ILConverters/Shr/Shr.cs +++ b/tests/IL2C.Core.Test.ILConverters/Shr/Shr.cs @@ -59,6 +59,12 @@ namespace IL2C.ILConverters [TestCase((ulong)0, "ShrUlong", (ulong)1, 1)] [TestCase((ulong)UInt64.MaxValue, "ShrUlong", (ulong)UInt64.MaxValue, 1)] [TestCase((ulong)UInt64.MaxValue, "ShrUlong", (ulong)UInt64.MaxValue, 2)] + + //[TestCase((int)(Int32.MaxValue - 1) / 2, "ShrIntByIntptr", (int)Int32.MaxValue, 1)] + //[TestCase((int)(Int32.MaxValue - 1) / 4, "ShrIntByIntptr", (int)Int32.MaxValue, 2)] + + //[TestCase((long)(Int64.MaxValue - 1) / 2, "ShrUlongByUIntptr", (long)Int64.MaxValue, 1)] + //[TestCase((long)(Int64.MaxValue - 1) / 4, "ShrUlongByUIntptr", (long)Int64.MaxValue, 2)] public sealed class Shr { [MethodImpl(MethodImplOptions.ForwardRef)] @@ -84,5 +90,11 @@ public sealed class Shr [MethodImpl(MethodImplOptions.ForwardRef)] public static extern ulong ShrUlong(ulong v, int num); + + //[MethodImpl(MethodImplOptions.ForwardRef)] + //public static extern int ShrIntByIntptr(int v, IntPtr num); + + //[MethodImpl(MethodImplOptions.ForwardRef)] + //public static extern ulong ShrUlongByUIntptr(ulong v, UIntPtr num); } } diff --git a/tests/IL2C.Core.Test.ILConverters/Shr/Shr.il b/tests/IL2C.Core.Test.ILConverters/Shr/Shr.il index d54fcfea..71bf892d 100644 --- a/tests/IL2C.Core.Test.ILConverters/Shr/Shr.il +++ b/tests/IL2C.Core.Test.ILConverters/Shr/Shr.il @@ -71,4 +71,23 @@ shr ret } + /* + .method public static int32 ShrIntByIntptr(int32 v, native int num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr + ret + } + + .method public static uint64 ShrUlongByUIntptr(uint64 v, native uint num) cil managed + { + .maxstack 2 + ldarg.0 + ldarg.1 + shr + ret + } + */ } From 47904114906efc4006fedb1934ce7420c84ced73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Tue, 19 Oct 2021 11:20:46 +0200 Subject: [PATCH 35/36] Remove method filter comment also for AssemblyPreparer --- IL2C.Core/AssemblyPreparer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IL2C.Core/AssemblyPreparer.cs b/IL2C.Core/AssemblyPreparer.cs index 49d824fb..389d00f8 100644 --- a/IL2C.Core/AssemblyPreparer.cs +++ b/IL2C.Core/AssemblyPreparer.cs @@ -321,7 +321,7 @@ public static PreparedInformations Prepare(TranslateContext translateContext) translateContext, // All types type => true, - // The methods except type initializer. + // All methods method => true); } } From ca5706c066a280d3212bec9f6293b9cf708d9660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Vir=C3=A1gh?= Date: Tue, 19 Oct 2021 11:34:22 +0200 Subject: [PATCH 36/36] StargConverter simplification --- IL2C.Core/ILConveters/StargConverters .cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/IL2C.Core/ILConveters/StargConverters .cs b/IL2C.Core/ILConveters/StargConverters .cs index ecdfb216..a279242b 100644 --- a/IL2C.Core/ILConveters/StargConverters .cs +++ b/IL2C.Core/ILConveters/StargConverters .cs @@ -29,20 +29,16 @@ namespace IL2C.ILConverters internal static class StargConverterUtilities { public static ExpressionEmitter Prepare( - int parameterIndex, DecodeContext decodeContext, bool isReference) + int parameterIndex, DecodeContext decodeContext) { var si = decodeContext.PopStack(); var parameter = decodeContext.Method.Parameters[parameterIndex]; - var targetType = isReference ? parameter.TargetType.MakeByReference() : parameter.TargetType; // TODO: check target and source type return (extractContext, _) => new[] { string.Format( - "{0} = {1}{2}", + "{0} = {1}", parameter.ParameterName, - // NOTE: Don't check "targetType.IsByReference" instead "isReference." - // Because it's maybe double encoded byref type. - isReference ? "&" : string.Empty, extractContext.GetSymbolName(si)) }; } } @@ -53,7 +49,7 @@ internal sealed class StargSConverter : ShortInlineParamConverter public override ExpressionEmitter Prepare(VariableInformation operand, DecodeContext decodeContext) { - return StargConverterUtilities.Prepare(operand.Index, decodeContext, false); + return StargConverterUtilities.Prepare(operand.Index, decodeContext); } } @@ -63,7 +59,7 @@ internal sealed class StargConverter : InlineParamConverter public override ExpressionEmitter Prepare(VariableInformation operand, DecodeContext decodeContext) { - return StargConverterUtilities.Prepare(operand.Index, decodeContext, false); + return StargConverterUtilities.Prepare(operand.Index, decodeContext); } } }