From 7c751492e9e7e938ee980cd1dcc61ca2212dca5c Mon Sep 17 00:00:00 2001 From: Quajak Date: Sun, 29 Dec 2019 06:20:45 -0500 Subject: [PATCH 1/2] Fix handling of enums as integer type --- source/Cosmos.IL2CPU/ILOpCode.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/source/Cosmos.IL2CPU/ILOpCode.cs b/source/Cosmos.IL2CPU/ILOpCode.cs index f10385f08..a830cb047 100644 --- a/source/Cosmos.IL2CPU/ILOpCode.cs +++ b/source/Cosmos.IL2CPU/ILOpCode.cs @@ -393,6 +393,7 @@ public void InterpretStackTypes(IDictionary aOpCodes, Stack || ((StackPopTypes[i] == typeof(ushort)) || (StackPopTypes[i] == typeof(short))) || ((StackPopTypes[i] == typeof(uint)) || (StackPopTypes[i] == typeof(int))) || ((StackPopTypes[i] == typeof(ulong)) || (StackPopTypes[i] == typeof(long))) + || (StackPopTypes[i].IsEnum) || ((StackPopTypes[i] == typeof(UIntPtr)) || (StackPopTypes[i] == typeof(IntPtr))))) { StackPopTypes[i] = xActualStackItem; From ca20205069e73217ae927c38e17c42bd622d93c5 Mon Sep 17 00:00:00 2001 From: Quajak Date: Wed, 3 Jun 2020 21:47:09 +0200 Subject: [PATCH 2/2] Add index in range checks for additional opcodes --- source/Cosmos.IL2CPU/IL/Ldelem.cs | 5 +- source/Cosmos.IL2CPU/IL/Ldelema.cs | 69 ++++++++++-------------- source/Cosmos.IL2CPU/IL/Stelem_Ref.cs | 77 +++++++++++++++++++++------ 3 files changed, 90 insertions(+), 61 deletions(-) diff --git a/source/Cosmos.IL2CPU/IL/Ldelem.cs b/source/Cosmos.IL2CPU/IL/Ldelem.cs index 9498ea008..9d388cee3 100644 --- a/source/Cosmos.IL2CPU/IL/Ldelem.cs +++ b/source/Cosmos.IL2CPU/IL/Ldelem.cs @@ -1,4 +1,3 @@ - using Cosmos.IL2CPU.ILOpCodes; namespace Cosmos.IL2CPU.X86.IL @@ -17,11 +16,11 @@ public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) var xSize = SizeOfType(xOpType.Value); if (xOpType.Value.IsValueType && !xOpType.Value.IsPrimitive) { - Ldelema.Assemble(Assembler, xOpType, xSize, DebugEnabled); + Ldelema.Assemble(Assembler, xOpType, xSize, DebugEnabled, aMethod, aOpCode); Ldobj.DoAssemble(xOpType.Value); return; } Ldelem_Ref.Assemble(Assembler, xSize, false, aMethod, aOpCode, DebugEnabled); } } -} \ No newline at end of file +} diff --git a/source/Cosmos.IL2CPU/IL/Ldelema.cs b/source/Cosmos.IL2CPU/IL/Ldelema.cs index 9659b43ae..395db2464 100644 --- a/source/Cosmos.IL2CPU/IL/Ldelema.cs +++ b/source/Cosmos.IL2CPU/IL/Ldelema.cs @@ -1,4 +1,5 @@ using System.Linq; +using CPUx86 = XSharp.Assembler.x86; using Cosmos.IL2CPU.ILOpCodes; using IL2CPU.API; @@ -15,12 +16,36 @@ public Ldelema(XSharp.Assembler.Assembler aAsmblr) { } - public static void Assemble(XSharp.Assembler.Assembler aAssembler, OpType aOpType, uint aElementSize, bool debugEnabled) + public static void Assemble(XSharp.Assembler.Assembler aAssembler, OpType aOpType, uint aElementSize, bool debugEnabled, _MethodInfo aMethod, ILOpCode aOpCode) { XS.Comment("Arraytype: " + aOpType.StackPopTypes.Last().FullName); XS.Comment("Size: " + aElementSize); DoNullReferenceCheck(aAssembler, debugEnabled, 8); + + //Do check for index out of range + var xBaseLabel = GetLabel(aMethod, aOpCode); + var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException"; + var xIndexOutOfRangeExeptionLabel = xBaseLabel + "_IndexOutOfRangeException"; + XS.Pop(EBX); //get Position _, array, 0, index -> _, array, 0 + XS.Push(ESP, true, 4); // _, array, 0 => _, array, 0, array + XS.Push(ESP, true, 12); // _, array, 0, array => _, array, 0, array, 0 + Ldlen.Assemble(aAssembler, debugEnabled, false); // _, array, 0, array, 0 -> _, array, 0, length + XS.Pop(EAX); //Length of array _, array, 0, length -> _, array, 0 + XS.Compare(EAX, EBX); + XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel); + + XS.Compare(EBX, 0); + XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel); + + XS.Label(xIndexOutOfRangeExeptionLabel); + XS.Pop(EAX); + XS.Pop(EAX); + Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled); + + XS.Label(xNoIndexOutOfRangeExeptionLabel); + XS.Push(EBX); //_, array, 0 -> _, array, 0, index + // calculate element offset into array memory (including header) XS.Pop(EAX); XS.Set(EDX, aElementSize); @@ -39,47 +64,7 @@ public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { var xOpType = (OpType)aOpCode; var xSize = SizeOfType(xOpType.Value); - Assemble(Assembler, xOpType, xSize, DebugEnabled); + Assemble(Assembler, xOpType, xSize, DebugEnabled, aMethod, aOpCode); } - - - // using System; - // using System.IO; - // - // - // using CPU = XSharp.Assembler.x86; - // using CPUx86 = XSharp.Assembler.x86; - // using Cosmos.IL2CPU.X86; - // using Cosmos.IL2CPU.Compiler; - // - // namespace Cosmos.IL2CPU.IL.X86 { - // [XSharp.Assembler.OpCode(OpCodeEnum.Ldelema)] - // public class Ldelema: Op { - // private Type mType; - // public Ldelema(ILReader aReader, MethodInformation aMethodInfo) - // : base(aReader, aMethodInfo) { - // mType= aReader.OperandValueType; - // } - // - // public static void Assemble(CPU.Assembler aAssembler, uint aElementSize) { - // aAssembler.Stack.Pop(); - // aAssembler.Stack.Pop(); - // aAssembler.Stack.Push(new StackContent(4, typeof(uint))); - // XS.Pop(XSRegisters.EAX); - // XS.Mov(XSRegisters.EDX, aElementSize); - // XS.Multiply(XSRegisters.EDX); - // new CPUx86.Add { DestinationReg = CPUx86.Registers.EAX, SourceValue = (uint)(ObjectImpl.FieldDataOffset + 4) }; - // XS.Pop(XSRegisters.EDX); - // XS.Add(XSRegisters.EDX, XSRegisters.CPUx86.Registers.EAX); - // XS.Push(XSRegisters.EDX); - // } - // - // public override void DoAssemble() { - // var xElementSize = GetService().SizeOfType(mType); - // Assemble(Assembler, xElementSize); - // } - // } - // } - } } diff --git a/source/Cosmos.IL2CPU/IL/Stelem_Ref.cs b/source/Cosmos.IL2CPU/IL/Stelem_Ref.cs index 3b9abbee2..e5e2fc5d6 100644 --- a/source/Cosmos.IL2CPU/IL/Stelem_Ref.cs +++ b/source/Cosmos.IL2CPU/IL/Stelem_Ref.cs @@ -1,6 +1,8 @@ using System; using CPUx86 = XSharp.Assembler.x86; using XSharp.Assembler; +using static XSharp.XSRegisters; + using IL2CPU.API; using XSharp; @@ -27,39 +29,82 @@ public static void Assemble(Assembler aAssembler, uint aElementSize, _MethodInfo { xStackSize += 4 - xStackSize % 4; } + // Do index out of range check + var xBaseLabel = GetLabel(aMethod, aOpCode); + var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException"; + var xIndexOutOfRangeExeptionLabel = xBaseLabel + "_IndexOutOfRangeException"; + if (xStackSize == 4) + { + XS.Pop(ECX); //get value _, array, 0, index, value -> _, array, 0, index + } + else if(xStackSize == 8) + { + XS.Pop(ECX); //get value _, array, 0, index, value0, value1 -> _, array, 0, index, value0 + XS.Pop(EDX); //get value _, array, 0, index, value0 -> _, array, 0, index + } + else + { + throw new NotImplementedException(); + } + XS.Pop(EBX); //get Position _, array, 0, index -> _, array, 0 + XS.Push(ESP, true, 4); // _, array, 0 => _, array, 0, array + XS.Push(ESP, true, 12); // _, array, 0, array => _, array, 0, array, 0 + Ldlen.Assemble(aAssembler, debugEnabled, false); // _, array, 0, array, 0 -> _, array, 0, length + XS.Pop(EAX); //Length of array _, array, 0, length -> _, array, 0 + XS.Compare(EAX, EBX); + XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel); + + XS.Compare(EBX, 0); + XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel); + + XS.Label(xIndexOutOfRangeExeptionLabel); + XS.Pop(EAX); + XS.Pop(EAX); + Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled); + + XS.Label(xNoIndexOutOfRangeExeptionLabel); + XS.Push(EBX); //_, array, 0 -> _, array, 0, index + if (xStackSize == 4) + { + XS.Push(ECX); //_, array, 0 -> _, array, 0, index, value + } else if(xStackSize == 8) + { + XS.Push(EDX); //_, array, 0, index -> _, array, 0, index, value0 + XS.Push(ECX); //_, array, 0, index, value0 -> _, array, 0, index, value0, value1 + } // calculate element offset into array memory (including header) - XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: (int)xStackSize); // the index - XS.Set(XSRegisters.EDX, aElementSize); - XS.Multiply(XSRegisters.EDX); - XS.Add(XSRegisters.EAX, ObjectUtils.FieldDataOffset + 4); + XS.Set(EAX, ESP, sourceDisplacement: (int)xStackSize); // the index + XS.Set(EDX, aElementSize); + XS.Multiply(EDX); + XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); - XS.Set(XSRegisters.EDX, XSRegisters.ESP, sourceDisplacement: (int)xStackSize + 8); // the array - XS.Add(XSRegisters.EDX, XSRegisters.EAX); - XS.Push(XSRegisters.EDX); + XS.Set(EDX, ESP, sourceDisplacement: (int)xStackSize + 8); // the array + XS.Add(EDX, EAX); + XS.Push(EDX); - XS.Pop(XSRegisters.ECX); + XS.Pop(ECX); for (int i = (int)(aElementSize / 4) - 1; i >= 0; i -= 1) { new Comment(aAssembler, "Start 1 dword"); - XS.Pop(XSRegisters.EBX); - XS.Set(XSRegisters.ECX, XSRegisters.EBX, destinationIsIndirect: true); - XS.Add(XSRegisters.ECX, 4); + XS.Pop(EBX); + XS.Set(ECX, EBX, destinationIsIndirect: true); + XS.Add(ECX, 4); } switch (aElementSize % 4) { case 1: { new Comment(aAssembler, "Start 1 byte"); - XS.Pop(XSRegisters.EBX); - XS.Set(XSRegisters.ECX, XSRegisters.BL, destinationIsIndirect: true); + XS.Pop(EBX); + XS.Set(ECX, BL, destinationIsIndirect: true); break; } case 2: { new Comment(aAssembler, "Start 1 word"); - XS.Pop(XSRegisters.EBX); - XS.Set(XSRegisters.ECX, XSRegisters.BX, destinationIsIndirect: true); + XS.Pop(EBX); + XS.Set(ECX, BX, destinationIsIndirect: true); break; } case 0: @@ -70,7 +115,7 @@ public static void Assemble(Assembler aAssembler, uint aElementSize, _MethodInfo throw new Exception("Remainder size " + (aElementSize % 4) + " not supported!"); } - XS.Add(XSRegisters.ESP, 12); + XS.Add(ESP, 12); } public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) {