public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { bool loadAddr = (ILOp.OpCodes)theOp.opCode.Value == OpCodes.Ldloca || (ILOp.OpCodes)theOp.opCode.Value == OpCodes.Ldloca_S; UInt16 localIndex = 0; switch ((ILOp.OpCodes)theOp.opCode.Value) { case OpCodes.Ldloc: case OpCodes.Ldloca: localIndex = (UInt16)Utilities.ReadInt16(theOp.ValueBytes, 0); break; case OpCodes.Ldloc_0: localIndex = 0; break; case OpCodes.Ldloc_1: localIndex = 1; break; case OpCodes.Ldloc_2: localIndex = 2; break; case OpCodes.Ldloc_3: localIndex = 3; break; case OpCodes.Ldloc_S: case OpCodes.Ldloca_S: localIndex = (UInt16)theOp.ValueBytes[0]; break; } Types.VariableInfo theLoc = conversionState.Input.TheMethodInfo.LocalInfos.ElementAt(localIndex); if (loadAddr) { conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isGCManaged = false, isValue = false }); } else { int pushedLocalSizeVal = theLoc.TheTypeInfo.SizeOnStackInBytes; conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = Utilities.IsFloat(theLoc.UnderlyingType), sizeOnStackInBytes = pushedLocalSizeVal, isGCManaged = theLoc.TheTypeInfo.IsGCManaged, isValue = theLoc.TheTypeInfo.IsValueType }); } }
/// <summary> /// See base class documentation. /// <para>To Do's:</para> /// <list type="bullet"> /// <item> /// <term>To do</term> /// <description>Implement storing of float arguments.</description> /// </item> /// </list> /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotImplementedException"> /// Thrown when storing a float argument is required as it currently hasn't been /// implemented. /// </exception> /// <exception cref="System.ArgumentException"> /// Thrown when an invalid number of bytes is specified for the argument to store. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { //Get the index of the argument to load Int16 index = 0; switch ((OpCodes)theOp.opCode.Value) { case OpCodes.Starg: index = Utilities.ReadInt16(theOp.ValueBytes, 0); break; case OpCodes.Starg_S: index = (Int16)theOp.ValueBytes[0]; break; } Types.VariableInfo argInfo = conversionState.Input.TheMethodInfo.ArgumentInfos[index]; //Used to store the number of bytes to add to EBP to get to the arg int BytesOffsetFromEBP = argInfo.Offset; //Pop the argument value from the stack int bytesForArg = argInfo.TheTypeInfo.SizeOnStackInBytes; for (int i = 0; i < bytesForArg; i += 4) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "[EBP+" + (BytesOffsetFromEBP + i) + "]" }); } //Pop the arg value from our stack conversionState.CurrentStackFrame.Stack.Pop(); }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotSupportedException"> /// Thrown if the value to store is floating point. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { UInt16 localIndex = 0; switch ((ILOp.OpCodes)theOp.opCode.Value) { case OpCodes.Stloc: localIndex = (UInt16)Utilities.ReadInt16(theOp.ValueBytes, 0); break; case OpCodes.Stloc_0: localIndex = 0; break; case OpCodes.Stloc_1: localIndex = 1; break; case OpCodes.Stloc_2: localIndex = 2; break; case OpCodes.Stloc_3: localIndex = 3; break; case OpCodes.Stloc_S: localIndex = (UInt16)theOp.ValueBytes[0]; break; } Types.VariableInfo localInfo = conversionState.Input.TheMethodInfo.LocalInfos[localIndex]; StackItem theItem = conversionState.CurrentStackFrame.Stack.Pop(); if (theItem.isFloat) { //SUPPORT - floats throw new NotSupportedException("Float locals not supported yet!"); } int locSize = localInfo.TheTypeInfo.SizeOnStackInBytes; if (locSize == 0) { conversionState.Append(new ASMOps.Comment("0 pop size (?!)")); } else { for (int i = 0; i < locSize; i += 4) { conversionState.Append(new ASMOps.Pop() { Size = ASMOps.OperandSize.Dword, Dest = "[EBP-" + Math.Abs(localInfo.Offset + i).ToString() + "]" }); } } }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotSupportedException"> /// Thrown when loading a float local is required as it currently hasn't been /// implemented. /// Also thrown if arguments are not of size 4 or 8 bytes. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { //Load local bool loadAddr = (ILOp.OpCodes)theOp.opCode.Value == OpCodes.Ldloca || (ILOp.OpCodes)theOp.opCode.Value == OpCodes.Ldloca_S; UInt16 localIndex = 0; switch ((ILOp.OpCodes)theOp.opCode.Value) { case OpCodes.Ldloc: case OpCodes.Ldloca: localIndex = (UInt16)Utilities.ReadInt16(theOp.ValueBytes, 0); break; case OpCodes.Ldloc_0: localIndex = 0; break; case OpCodes.Ldloc_1: localIndex = 1; break; case OpCodes.Ldloc_2: localIndex = 2; break; case OpCodes.Ldloc_3: localIndex = 3; break; case OpCodes.Ldloc_S: case OpCodes.Ldloca_S: localIndex = (UInt16)theOp.ValueBytes[0]; break; } Types.VariableInfo theLoc = conversionState.Input.TheMethodInfo.LocalInfos[localIndex]; if (Utilities.IsFloat(theLoc.UnderlyingType)) { //SUPPORT - floats throw new NotSupportedException("Float locals not supported yet!"); } if (loadAddr) { conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Dword, Src = "EBP", Dest = "EAX" }); conversionState.Append(new ASMOps.Sub() { Src = (-theLoc.Offset).ToString(), Dest = "EAX" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "EAX" }); conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isGCManaged = false, isValue = false }); } else { int localSizeOnStack = theLoc.TheTypeInfo.SizeOnStackInBytes; if ((localSizeOnStack % 4) != 0) { throw new NotSupportedException("Invalid local bytes size!"); } else { for (int i = theLoc.Offset + (localSizeOnStack - 4); i >= theLoc.Offset; i -= 4) { conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Dword, Src = "[EBP-" + Math.Abs(i).ToString() + "]" }); } } conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = Utilities.IsFloat(theLoc.UnderlyingType), sizeOnStackInBytes = localSizeOnStack, isGCManaged = theLoc.TheTypeInfo.IsGCManaged, isValue = theLoc.TheTypeInfo.IsValueType }); } }
/// <summary> /// Preprocesses the specified method. /// </summary> /// <param name="TheLibrary">The library being compiled.</param> /// <param name="theMethodInfo">The method to preprocess.</param> private static void PreprocessMethodInfo(ILLibrary TheLibrary, Types.MethodInfo theMethodInfo) { if (theMethodInfo.Preprocessed) { return; } theMethodInfo.Preprocessed = true; string sig = theMethodInfo.Signature; bool SetMethodID = true; if (!theMethodInfo.IsConstructor) { System.Reflection.MethodInfo methodInf = (System.Reflection.MethodInfo)theMethodInfo.UnderlyingInfo; if (methodInf.GetBaseDefinition() != methodInf) { Types.MethodInfo baseMethodInfo = TheLibrary.GetMethodInfo(methodInf.GetBaseDefinition()); PreprocessMethodInfo(TheLibrary, baseMethodInfo); theMethodInfo.IDValue = baseMethodInfo.IDValue; SetMethodID = false; } } if (SetMethodID) { Types.TypeInfo declarerTypeInfo = TheLibrary.GetTypeInfo(theMethodInfo.UnderlyingInfo.DeclaringType); int ID = GetMethodIDGenerator(TheLibrary, declarerTypeInfo); theMethodInfo.IDValue = ID + 1; declarerTypeInfo.MethodIDGenerator++; } int totalLocalsOffset = 0; foreach (Types.VariableInfo aVarInfo in theMethodInfo.LocalInfos) { //Causes processing of the type - in case it hasn't already been processed Types.TypeInfo aTypeInfo = TheLibrary.GetTypeInfo(aVarInfo.UnderlyingType); aVarInfo.TheTypeInfo = aTypeInfo; aVarInfo.Offset = totalLocalsOffset; totalLocalsOffset += aTypeInfo.SizeOnStackInBytes; } int totalArgsSize = 0; if (!theMethodInfo.IsStatic) { Types.VariableInfo newVarInfo = new Types.VariableInfo() { UnderlyingType = theMethodInfo.UnderlyingInfo.DeclaringType, Position = 0, TheTypeInfo = TheLibrary.GetTypeInfo(theMethodInfo.UnderlyingInfo.DeclaringType) }; theMethodInfo.ArgumentInfos.Add(newVarInfo); totalArgsSize += newVarInfo.TheTypeInfo.SizeOnStackInBytes; } System.Reflection.ParameterInfo[] args = theMethodInfo.UnderlyingInfo.GetParameters(); foreach (System.Reflection.ParameterInfo argItem in args) { Types.VariableInfo newVarInfo = new Types.VariableInfo() { UnderlyingType = argItem.ParameterType, Position = theMethodInfo.ArgumentInfos.Count, TheTypeInfo = TheLibrary.GetTypeInfo(argItem.ParameterType) }; theMethodInfo.ArgumentInfos.Add(newVarInfo); totalArgsSize += newVarInfo.TheTypeInfo.SizeOnStackInBytes; } //System.Reflection.ParameterInfo returnArgItem = (theMethodInfo.IsConstructor ? null : ((System.Reflection.MethodInfo)theMethodInfo.UnderlyingInfo).ReturnParameter); //if (returnArgItem != null) //{ // Types.VariableInfo newVarInfo = new Types.VariableInfo() // { // UnderlyingType = returnArgItem.ParameterType, // Position = theMethodInfo.ArgumentInfos.Count, // TheTypeInfo = TheLibrary.GetTypeInfo(returnArgItem.ParameterType) // }; // theMethodInfo.ArgumentInfos.Add(newVarInfo); // totalArgsSize += newVarInfo.TheTypeInfo.SizeOnStackInBytes; //} int offset = totalArgsSize; for (int i = 0; i < theMethodInfo.ArgumentInfos.Count; i++) { offset -= theMethodInfo.ArgumentInfos[i].TheTypeInfo.SizeOnStackInBytes; theMethodInfo.ArgumentInfos[i].Offset = offset; } }
/// <summary> /// See base class documentation. /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotSupportedException"> /// Thrown when loading a float local is required as it currently hasn't been /// implemented. /// Also thrown if arguments are not of size 4 or 8 bytes. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { //Load local bool loadAddr = (ILOp.OpCodes)theOp.opCode.Value == OpCodes.Ldloca || (ILOp.OpCodes)theOp.opCode.Value == OpCodes.Ldloca_S; UInt16 localIndex = 0; switch ((ILOp.OpCodes)theOp.opCode.Value) { case OpCodes.Ldloc: case OpCodes.Ldloca: localIndex = (UInt16)Utilities.ReadInt16(theOp.ValueBytes, 0); break; case OpCodes.Ldloc_0: localIndex = 0; break; case OpCodes.Ldloc_1: localIndex = 1; break; case OpCodes.Ldloc_2: localIndex = 2; break; case OpCodes.Ldloc_3: localIndex = 3; break; case OpCodes.Ldloc_S: case OpCodes.Ldloca_S: localIndex = (UInt16)theOp.ValueBytes[0]; break; } int bytesOffset = 0; for (int i = 0; i < conversionState.Input.TheMethodInfo.LocalInfos.Count && i <= localIndex; i++) { bytesOffset += conversionState.Input.TheMethodInfo.LocalInfos[i].TheTypeInfo.SizeOnStackInBytes; } Types.VariableInfo theLoc = conversionState.Input.TheMethodInfo.LocalInfos[localIndex]; if (Utilities.IsFloat(theLoc.UnderlyingType)) { //SUPPORT - floats throw new NotSupportedException("Float locals not supported yet!"); } if (loadAddr) { conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$fp", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.RegToReg }); conversionState.Append(new ASMOps.Sub() { Src1 = "$t0", Src2 = bytesOffset.ToString(), Dest = "$t0" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t0" }); conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = false, sizeOnStackInBytes = 4, isGCManaged = false, isValue = false }); } else { int pushedLocalSizeVal = theLoc.TheTypeInfo.SizeOnStackInBytes; if ((pushedLocalSizeVal % 4) != 0) { throw new NotSupportedException("Invalid local bytes size!"); } else { for (int i = bytesOffset - (pushedLocalSizeVal - 4); i <= bytesOffset; i += 4) { conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "-" + i.ToString() + "($fp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t0" }); } } conversionState.CurrentStackFrame.Stack.Push(new StackItem() { isFloat = Utilities.IsFloat(theLoc.UnderlyingType), sizeOnStackInBytes = pushedLocalSizeVal, isGCManaged = theLoc.TheTypeInfo.IsGCManaged, isValue = theLoc.TheTypeInfo.IsValueType }); } }
/// <summary> /// See base class documentation. /// <para>To Do's:</para> /// <list type="bullet"> /// <item> /// <term>To do</term> /// <description>Implement loading of float arguments.</description> /// </item> /// </list> /// </summary> /// <param name="theOp">See base class documentation.</param> /// <param name="conversionState">See base class documentation.</param> /// <returns>See base class documentation.</returns> /// <exception cref="System.NotSupportedException"> /// Thrown when loading a float argument is required as it currently hasn't been /// implemented. /// </exception> /// <exception cref="System.ArgumentException"> /// Thrown when an invalid number of bytes is specified for the argument to load. /// </exception> public override void Convert(ILConversionState conversionState, ILOp theOp) { //Get the index of the argument to load Int16 index = 0; switch ((OpCodes)theOp.opCode.Value) { case OpCodes.Ldarg: index = Utilities.ReadInt16(theOp.ValueBytes, 0); break; case OpCodes.Ldarg_0: index = 0; break; case OpCodes.Ldarg_1: index = 1; break; case OpCodes.Ldarg_2: index = 2; break; case OpCodes.Ldarg_3: index = 3; break; case OpCodes.Ldarg_S: index = (Int16)theOp.ValueBytes[0]; break; case OpCodes.Ldarga: index = Utilities.ReadInt16(theOp.ValueBytes, 0); break; case OpCodes.Ldarga_S: index = (Int16)theOp.ValueBytes[0]; break; } Types.VariableInfo argInfo = conversionState.Input.TheMethodInfo.ArgumentInfos[index]; if (Utilities.IsFloat(argInfo.TheTypeInfo.UnderlyingType)) { //SUPPORT - floats throw new NotSupportedException("Float arguments not supported yet!"); } //Used to store the number of bytes to add to EBP to get to the arg int BytesOffsetFromEBP = argInfo.Offset; if ((OpCodes)theOp.opCode.Value == OpCodes.Ldarga || (OpCodes)theOp.opCode.Value == OpCodes.Ldarga_S) { //Push the address of the argument onto the stack conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = "$fp", Dest = "$t2", MoveType = ASMOps.Mov.MoveTypes.RegToReg }); conversionState.Append(new ASMOps.Add() { Src1 = "$t2", Src2 = BytesOffsetFromEBP.ToString(), Dest = "$t2" }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t2" }); //Push the address onto our stack conversionState.CurrentStackFrame.Stack.Push(new StackItem() { sizeOnStackInBytes = 4, isFloat = false, isGCManaged = false, isValue = false }); } else { //Push the argument onto the stack Types.TypeInfo paramTypeInfo = argInfo.TheTypeInfo; int bytesForArg = paramTypeInfo.SizeOnStackInBytes; if (bytesForArg % 4 != 0) { throw new ArgumentException("Cannot load arg! Don't understand byte size of the arg! Size:" + bytesForArg); } while (bytesForArg > 0) { bytesForArg -= 4; conversionState.Append(new ASMOps.Mov() { Size = ASMOps.OperandSize.Word, Src = (BytesOffsetFromEBP + bytesForArg).ToString() + "($fp)", Dest = "$t0", MoveType = ASMOps.Mov.MoveTypes.SrcMemoryToDestReg }); conversionState.Append(new ASMOps.Push() { Size = ASMOps.OperandSize.Word, Src = "$t0" }); } //Push the arg onto our stack conversionState.CurrentStackFrame.Stack.Push(new StackItem() { sizeOnStackInBytes = paramTypeInfo.SizeOnStackInBytes, isFloat = false, isGCManaged = paramTypeInfo.IsGCManaged, isValue = paramTypeInfo.IsValueType }); } }
public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp) { Int16 index = 0; switch ((OpCodes)theOp.opCode.Value) { case OpCodes.Ldarg: index = Utilities.ReadInt16(theOp.ValueBytes, 0); break; case OpCodes.Ldarg_0: index = 0; break; case OpCodes.Ldarg_1: index = 1; break; case OpCodes.Ldarg_2: index = 2; break; case OpCodes.Ldarg_3: index = 3; break; case OpCodes.Ldarg_S: index = (Int16)theOp.ValueBytes[0]; break; case OpCodes.Ldarga: index = Utilities.ReadInt16(theOp.ValueBytes, 0); break; case OpCodes.Ldarga_S: index = (Int16)theOp.ValueBytes[0]; break; } if ((OpCodes)theOp.opCode.Value == OpCodes.Ldarga || (OpCodes)theOp.opCode.Value == OpCodes.Ldarga_S) { conversionState.CurrentStackFrame.Stack.Push(new StackItem() { sizeOnStackInBytes = 4, isFloat = false, isGCManaged = false, isValue = false }); } else { Types.VariableInfo argInfo = conversionState.Input.TheMethodInfo.ArgumentInfos[index]; Types.TypeInfo paramTypeInfo = argInfo.TheTypeInfo; int bytesForArg = paramTypeInfo.SizeOnStackInBytes; conversionState.CurrentStackFrame.Stack.Push(new StackItem() { sizeOnStackInBytes = bytesForArg, isFloat = false, isGCManaged = paramTypeInfo.IsGCManaged, isValue = paramTypeInfo.IsValueType }); } }