public void IdentifierExpression(CParser.IdentifierExpression IdentifierExpression) { var Variable = VariableScope.Find(IdentifierExpression.Identifier); var Function = FunctionScope.Find(IdentifierExpression.Identifier); if (Variable != null) { // For fixed array types, get always the address? if (Variable.CType is CArrayType && (Variable.CType as CArrayType).Size != 0) { Variable.LoadAddress(SafeILGenerator); } else if (GenerateAddress) { //Console.WriteLine(" Left"); Variable.LoadAddress(SafeILGenerator); } else { //Console.WriteLine(" No Left"); Variable.Load(SafeILGenerator); } } else if (Function != null) { //SafeILGenerator.Push(Function.MethodInfo); SafeILGenerator.LoadFunctionPointer(Function.MethodInfo, false); SafeILGenerator.ConvertTo(typeof(void *)); } else { throw (new Exception(string.Format("Not variable or function for identifier {0}", IdentifierExpression))); } }
public void ArrayAccessExpression(CParser.ArrayAccessExpression ArrayAccessExpression) { var LeftExpression = ArrayAccessExpression.Left; var LeftCType = (LeftExpression.GetCachedCType(this) as CBasePointerType); var LeftType = ConvertCTypeToType(LeftCType); var ElementCType = LeftCType.ElementCType; var ElementType = ConvertCTypeToType(ElementCType); var IndexExpression = ArrayAccessExpression.Index; DoGenerateAddress(false, () => { Traverse(LeftExpression); }); DoGenerateAddress(false, () => { Traverse(new CParser.BinaryExpression(IndexExpression, "*", new CParser.SizeofTypeExpression(ElementCType))); //Traverse(IndexExpression); }); //SafeILGenerator.Sizeof(ElementType); //SafeILGenerator.BinaryOperation(SafeBinaryOperator.MultiplySigned); SafeILGenerator.BinaryOperation(SafeBinaryOperator.AdditionSigned); // For fixed array types, get always the address? if (ElementCType is CArrayType && (ElementCType as CArrayType).Size != 0) { } else if (!GenerateAddress) { SafeILGenerator.LoadIndirect(ConvertCTypeToType(ElementCType)); } }
public void TrinaryExpression(CParser.TrinaryExpression TrinaryExpression) { var Condition = TrinaryExpression.Condition; var TrueExpression = TrinaryExpression.TrueExpression; var FalseExpression = TrinaryExpression.FalseExpression; var CommonCType = CType.CommonType(TrueExpression.GetCachedCType(this), FalseExpression.GetCachedCType(this)); var CommonType = GetRealType(ConvertCTypeToType(CommonCType)); var TrinaryTempLocal = SafeILGenerator.DeclareLocal(CommonType, "TrinaryTempLocal"); // Condition. Traverse(TrinaryExpression.Condition); // Check the value and store the result in the temp local. SafeILGenerator.MacroIfElse(() => { Traverse(TrinaryExpression.TrueExpression); SafeILGenerator.ConvertTo(CommonType); SafeILGenerator.StoreLocal(TrinaryTempLocal); }, () => { Traverse(TrinaryExpression.FalseExpression); SafeILGenerator.ConvertTo(CommonType); SafeILGenerator.StoreLocal(TrinaryTempLocal); }); // Load temp local. SafeILGenerator.LoadLocal(TrinaryTempLocal); }
public void StringExpression(CParser.StringExpression StringExpression) { //CurrentClass.DefineField( //SafeILGenerator.LoadNull(); //SafeILGenerator.CastClass(CurrentClass); SafeILGenerator.LoadField(GetStringPointerField(StringExpression.String)); //SafeILGenerator.Push(StringExpression.Value); }
/// <summary> /// /// </summary> /// <param name="Operator"></param> private void _DoBinaryLeftRightPost(string Operator) { switch (Operator) { case "&&": case "||": SafeILGenerator.ConvertTo <bool>(); break; } }
protected VertexReaderDynarec(SafeILGenerator SafeILGenerator, VertexTypeStruct VertexType) { this.Offset = 0; this.SafeILGenerator = SafeILGenerator; this.VertexType = VertexType; this.VertexDataArgument = SafeILGenerator.DeclareArgument(typeof(void*), 0); this.VertexInfoArgument = SafeILGenerator.DeclareArgument(typeof(VertexInfo*), 0); this.IndexArgument = SafeILGenerator.DeclareArgument(typeof(int), 0); this.CountArgument = SafeILGenerator.DeclareArgument(typeof(int), 0); this.LocalColor = SafeILGenerator.DeclareLocal<uint>("LocalColor", false); }
private void ConvertTo(Type Type) { var FixedArrayAttributes = Type.GetCustomAttributes(typeof(FixedArrayAttribute), true); if ((FixedArrayAttributes != null) && (FixedArrayAttributes.Length > 0)) { SafeILGenerator.ConvertTo(Type.GetField("FirstElement").FieldType.MakePointerType()); } else { SafeILGenerator.ConvertTo(Type); } }
/// <summary> /// /// </summary> /// <param name="Operator"></param> /// <param name="Left"></param> /// <param name="Right"></param> private void DoBinaryOperation(string Operator, CParser.Expression Left, CParser.Expression Right) { bool EmitConstantValue = true; DoGenerateAddress(false, () => { var LeftConstant = Left.GetCachedConstantValue(null); var RightConstant = Right.GetCachedConstantValue(null); // Optimization. if ((LeftConstant != null) && (RightConstant != null)) { //Console.WriteLine("{0} {1} {2}", LeftConstant, Operator, RightConstant); if (LeftConstant.GetType() == typeof(int) && RightConstant.GetType() == typeof(int)) { int LeftConstantValue = (int)LeftConstant; int RightConstantValue = (int)RightConstant; switch (Operator) { case "+": SafeILGenerator.Push(LeftConstantValue + RightConstantValue); return; case "-": SafeILGenerator.Push(LeftConstantValue - RightConstantValue); return; case "*": SafeILGenerator.Push(LeftConstantValue * RightConstantValue); return; case "/": SafeILGenerator.Push(LeftConstantValue / RightConstantValue); return; default: Console.Error.WriteLine("Unoptimized binary operator {0}", Operator); break; } } } Traverse(Left); _DoBinaryLeftRightPost(Operator); Traverse(Right); _DoBinaryLeftRightPost(Operator); EmitConstantValue = false; }); if (!EmitConstantValue) { var LeftCType = Left.GetCachedCType(this).GetCSimpleType(); var RightCType = Right.GetCachedCType(this).GetCSimpleType(); _DoBinaryOperation(Operator, LeftCType.Sign); } }
public void LoadAddress(SafeILGenerator SafeILGenerator) { if (Field != null) { SafeILGenerator.LoadFieldAddress(Field, UseLoadFieldAddress: true); } else if (Local != null) { SafeILGenerator.LoadLocalAddress(Local); //SafeILGenerator.LoadLocal(Local); } else { SafeILGenerator.LoadArgumentAddress(Argument); } }
public void ExpressionCommaList(CParser.ExpressionCommaList ExpressionCommaList) { var Expressions = ExpressionCommaList.Expressions; #if false Traverse(Expressions[Expressions.Length - 1]); #else Traverse(Expressions[0]); foreach (var Expression in Expressions.Skip(1)) { SafeILGenerator.PopLeft(); Traverse(Expression); } #endif }
/// <summary> /// /// </summary> /// <param name="Operator"></param> /// <param name="Signed"></param> private void _DoBinaryOperation(string Operator, CTypeSign Signed) { switch (Operator) { case "+": SafeILGenerator.BinaryOperation(Signed == CTypeSign.Signed ? SafeBinaryOperator.AdditionSigned : SafeBinaryOperator.AdditionUnsigned); break; case "-": SafeILGenerator.BinaryOperation(Signed == CTypeSign.Signed ? SafeBinaryOperator.SubstractionSigned : SafeBinaryOperator.SubstractionUnsigned); break; case "*": SafeILGenerator.BinaryOperation(Signed == CTypeSign.Signed ? SafeBinaryOperator.MultiplySigned : SafeBinaryOperator.MultiplyUnsigned); break; case "/": SafeILGenerator.BinaryOperation(Signed == CTypeSign.Signed ? SafeBinaryOperator.DivideSigned : SafeBinaryOperator.DivideUnsigned); break; case "%": SafeILGenerator.BinaryOperation(Signed == CTypeSign.Signed ? SafeBinaryOperator.RemainingSigned : SafeBinaryOperator.RemainingUnsigned); break; case "&": SafeILGenerator.BinaryOperation(SafeBinaryOperator.And); break; case "|": SafeILGenerator.BinaryOperation(SafeBinaryOperator.Or); break; case "^": SafeILGenerator.BinaryOperation(SafeBinaryOperator.Xor); break; case "<<": SafeILGenerator.BinaryOperation(SafeBinaryOperator.ShiftLeft); break; case ">>": SafeILGenerator.BinaryOperation(Signed == CTypeSign.Signed ? SafeBinaryOperator.ShiftRightSigned : SafeBinaryOperator.ShiftRightUnsigned); break; case "&&": SafeILGenerator.BinaryOperation(SafeBinaryOperator.And); break; case "||": SafeILGenerator.BinaryOperation(SafeBinaryOperator.Or); break; case "<": SafeILGenerator.CompareBinary(Signed == CTypeSign.Signed ? SafeBinaryComparison.LessThanSigned : SafeBinaryComparison.LessThanUnsigned); break; case ">": SafeILGenerator.CompareBinary(Signed == CTypeSign.Signed ? SafeBinaryComparison.GreaterThanSigned : SafeBinaryComparison.GreaterThanUnsigned); break; case "<=": SafeILGenerator.CompareBinary(Signed == CTypeSign.Signed ? SafeBinaryComparison.LessOrEqualSigned : SafeBinaryComparison.LessOrEqualUnsigned); break; case ">=": SafeILGenerator.CompareBinary(Signed == CTypeSign.Signed ? SafeBinaryComparison.GreaterOrEqualSigned : SafeBinaryComparison.GreaterOrEqualUnsigned); break; case "==": SafeILGenerator.CompareBinary(SafeBinaryComparison.Equals); break; case "!=": SafeILGenerator.CompareBinary(SafeBinaryComparison.NotEquals); break; default: throw (new NotImplementedException(String.Format("Operator {0} not implemented", Operator))); } }
public void Load(SafeILGenerator SafeILGenerator) { if (Field != null) { SafeILGenerator.LoadField(Field); } else if (Local != null) { //Console.WriteLine("Load local!"); SafeILGenerator.LoadLocal(Local); } else if (Argument != null) { SafeILGenerator.LoadArgument(Argument); } else { throw (new Exception("Invalid Variable Reference")); } }
public void DereferenceExpression(CParser.DereferenceExpression DereferenceExpression) { var Expression = DereferenceExpression.Expression; var ExpressionType = ConvertCTypeToType(Expression.GetCachedCType(this)); DoGenerateAddress(false, () => { Traverse(Expression); }); //SafeILGenerator.LoadIndirect(ExpressionType); //Console.WriteLine("{0}, {1}", ExpressionType, ElementType); if (!GenerateAddress) { var ElementType = ExpressionType.GetElementType(); SafeILGenerator.LoadIndirect(ElementType); } }
public void FunctionDeclaration(CParser.FunctionDeclaration FunctionDeclaration) { PutDebugLine(FunctionDeclaration); var FunctionName = FunctionDeclaration.CFunctionType.Name; var ReturnType = ConvertCTypeToType(FunctionDeclaration.CFunctionType.Return); var ParameterTypes = FunctionDeclaration.CFunctionType.Parameters.Select(Item => ConvertCTypeToType(Item.CType)).ToArray(); var ParameterCSymbols = FunctionDeclaration.CFunctionType.Parameters; if (ParameterTypes.Length == 1 && ParameterTypes[0] == typeof(void)) { ParameterTypes = new Type[0]; } var FunctionReference = FunctionScope.Find(FunctionName); if (FunctionReference == null) { var CurrentMethodLazy = new Lazy <MethodInfo>(() => { var MethodBuilder = CurrentClass.DefineMethod( FunctionName, MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, ReturnType, ParameterTypes ); for (int n = 0; n < ParameterCSymbols.Length; n++) { MethodBuilder.DefineParameter(n, ParameterAttributes.None, ParameterCSymbols[n].Name); } return(MethodBuilder); }); FunctionReference = new FunctionReference(this, FunctionName, CurrentMethodLazy, new SafeMethodTypeInfo() { IsStatic = true, ReturnType = ReturnType, Parameters = ParameterTypes, }) { BodyFinalized = false, }; FunctionScope.Push(FunctionName, FunctionReference); } // Just declaration if (FunctionDeclaration.FunctionBody == null) { } // Has function body. else { var CurrentMethod = (FunctionReference.MethodInfo as MethodBuilder); if (FunctionName == "main") { //HasEntryPoint = true; var StartupMethod = CurrentClass.DefineMethod( "__startup", MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, typeof(int), new Type[] { typeof(string[]) } ); var StartupSafeILGenerator = new SafeILGenerator(StartupMethod.GetILGenerator(), CheckTypes: true, DoDebug: false, DoLog: false); var ArgsArgument = StartupSafeILGenerator.DeclareArgument(typeof(string[]), 0); StartupSafeILGenerator.Push(CurrentClass); StartupSafeILGenerator.Call((Func <RuntimeTypeHandle, Type>)Type.GetTypeFromHandle); StartupSafeILGenerator.LoadArgument(ArgsArgument); StartupSafeILGenerator.Call((Func <Type, string[], int>)CLibUtils.RunTypeMain); //StartupSafeILGenerator.Call((Func<Type, string[], int>)CLibUtils.RunTypeMain); StartupSafeILGenerator.Return(typeof(int)); EntryPoint = StartupMethod; //EntryPoint = CurrentMethod; } var ILGenerator = CurrentMethod.GetILGenerator(); var CurrentSafeILGenerator = new SafeILGenerator(ILGenerator, CheckTypes: false, DoDebug: false, DoLog: true); AScope <VariableReference> .NewScope(ref this.VariableScope, () => { Scopable.RefScope(ref this.GotoContext, new LabelsContext(CurrentSafeILGenerator), () => { Scopable.RefScope(ref this.CurrentMethod, CurrentMethod, () => { Scopable.RefScope(ref this.SafeILGenerator, CurrentSafeILGenerator, () => { // Set argument variables ushort ArgumentIndex = 0; foreach (var Parameter in FunctionDeclaration.CFunctionType.Parameters) { var Argument = SafeILGenerator.DeclareArgument(ConvertCTypeToType(Parameter.CType), ArgumentIndex); this.VariableScope.Push(Parameter.Name, new VariableReference(Parameter.Name, Parameter.CType, Argument)); ArgumentIndex++; } Traverse(FunctionDeclaration.FunctionBody); if (FunctionDeclaration.FunctionBody.Statements.Length == 0 || !(FunctionDeclaration.FunctionBody.Statements.Last() is CParser.ReturnStatement)) //if (true) { if (CurrentMethod.ReturnType != typeof(void)) { SafeILGenerator.Push((int)0); } SafeILGenerator.Return(CurrentMethod.ReturnType); } }); #if SHOW_INSTRUCTIONS Console.WriteLine("Code for '{0}':", FunctionName); foreach (var Instruction in CurrentSafeILGenerator.GetEmittedInstructions()) { Console.WriteLine(" {0}", Instruction); } #endif }); }); }); FunctionReference.BodyFinalized = true; } }
public Result CreateDelegate(AstNodeStm astNodeStm, int totalInstructions) { var time0 = DateTime.UtcNow; astNodeStm = AstOptimizerPsp.GlobalOptimize(_processor, Ast.Statements(astNodeStm, Ast.Return())); var time1 = DateTime.UtcNow; #if DEBUG_GENERATE_IL Console.WriteLine("{0}", GeneratorIL.GenerateToString <GeneratorILPsp>(DynamicMethod, AstNodeStm)); #endif #if DEBUG_GENERATE_IL_CSHARP Console.WriteLine("{0}", AstNodeExtensions.ToCSharpString(AstNodeStm).Replace("CpuThreadState.", "")); #endif Action <CpuThreadState> Delegate; var time2 = time1; var disableOptimizations = DynarecConfig.DisableDotNetJitOptimizations; if (totalInstructions >= DynarecConfig.InstructionCountToDisableOptimizations) { disableOptimizations = true; } if (Platform.IsMono) { disableOptimizations = false; } if (DynarecConfig.ForceJitOptimizationsOnEvenLargeFunctions) { disableOptimizations = false; } try { Delegate = MethodCreator.CreateDynamicMethod <Action <CpuThreadState> >( //Delegate = MethodCreator.CreateMethodInClass<Action<CpuThreadState>>( Assembly.GetExecutingAssembly().ManifestModule, $"DynamicMethod_0x{this._pc:X}", disableOptimizations, dynamicMethod => { astNodeStm.GenerateIl(dynamicMethod); time2 = DateTime.UtcNow; } ); } catch (InvalidProgramException) { Console.Error.WriteLine("Invalid Delegate:"); #if LOG_TRACE Console.WriteLine("Invalid Delegate:"); foreach (var Line in SafeILGenerator.GetEmittedInstructions()) { if (Line.Substr(0, 1) == ":") { Console.WriteLine("{0}", Line); } else { Console.WriteLine(" {0}", Line); } } #endif throw; } var time3 = DateTime.UtcNow; return(new Result { Delegate = Delegate, DisableOptimizations = disableOptimizations, TimeOptimize = time1 - time0, TimeGenerateIl = time2 - time1, TimeCreateDelegate = time3 - time2, }); }
public void UnaryExpression(CParser.UnaryExpression UnaryExpression) { var Operator = UnaryExpression.Operator; var OperatorPosition = UnaryExpression.OperatorPosition; var Right = UnaryExpression.Right; var RightCType = Right.GetCachedCType(this); var RightType = ConvertCTypeToType(RightCType); switch (Operator) { case "~": { if (OperatorPosition != CParser.OperatorPosition.Left) { throw (new InvalidOperationException()); } DoGenerateAddress(false, () => { Traverse(Right); }); SafeILGenerator.UnaryOperation(SafeUnaryOperator.Not); } break; case "!": { if (OperatorPosition != CParser.OperatorPosition.Left) { throw (new InvalidOperationException()); } DoGenerateAddress(false, () => { Traverse(Right); }); SafeILGenerator.ConvertTo <bool>(); SafeILGenerator.Push(0); SafeILGenerator.CompareBinary(SafeBinaryComparison.Equals); } break; case "-": { if (OperatorPosition != CParser.OperatorPosition.Left) { throw (new InvalidOperationException()); } DoGenerateAddress(false, () => { Traverse(Right); }); SafeILGenerator.UnaryOperation(SafeUnaryOperator.Negate); } break; case "+": { if (OperatorPosition != CParser.OperatorPosition.Left) { throw (new InvalidOperationException()); } DoGenerateAddress(false, () => { Traverse(Right); }); } break; case "++": case "--": { /* * var RightFieldAccess = Right as CParser.FieldAccessExpression; * if (RightFieldAccess != null) * { * } */ //DoGenerateAddress(true, () => { Traverse(Right); }); LocalBuilder VariableToIncrementAddressLocal = null; LocalBuilder InitialVariableToIncrementValueLocal = null; LocalBuilder PostVariableToIncrementValueLocal = null; //RequireYieldResult = true; if (RequireYieldResult) { VariableToIncrementAddressLocal = SafeILGenerator.DeclareLocal(typeof(IntPtr)); } // Load address. DoGenerateAddress(true, () => { Traverse(Right); }); //Console.WriteLine("DEBUG: {0}", RightType); // Store. if (VariableToIncrementAddressLocal != null) { // Store initial address SafeILGenerator.Duplicate(); SafeILGenerator.StoreLocal(VariableToIncrementAddressLocal); } // Load Value SafeILGenerator.Duplicate(); SafeILGenerator.LoadIndirect(RightType); if (RequireYieldResult && (OperatorPosition == CParser.OperatorPosition.Right)) { // Store initial value InitialVariableToIncrementValueLocal = SafeILGenerator.DeclareLocal(RightType); SafeILGenerator.Duplicate(); SafeILGenerator.StoreLocal(InitialVariableToIncrementValueLocal); } // Increment/Decrement by 1 the value. if (RightType.IsPointer) { SafeILGenerator.Sizeof(RightType.GetElementType()); } else { SafeILGenerator.Push(1); } SafeILGenerator.BinaryOperation((Operator == "++") ? SafeBinaryOperator.AdditionSigned : SafeBinaryOperator.SubstractionSigned); if (RequireYieldResult && (OperatorPosition == CParser.OperatorPosition.Left)) { // Store the post value PostVariableToIncrementValueLocal = SafeILGenerator.DeclareLocal(RightType); SafeILGenerator.Duplicate(); SafeILGenerator.StoreLocal(PostVariableToIncrementValueLocal); } // Store the updated value. SafeILGenerator.StoreIndirect(RightType); /* * if (GenerateAddress) * { * //throw(new NotImplementedException("Can't generate address for a ++ or -- expression")); * SafeILGenerator.LoadLocal(VariableToIncrementAddressLocal); * } * else */ if (RequireYieldResult) { if (OperatorPosition == CParser.OperatorPosition.Left) { SafeILGenerator.LoadLocal(PostVariableToIncrementValueLocal); } else if (OperatorPosition == CParser.OperatorPosition.Right) { SafeILGenerator.LoadLocal(InitialVariableToIncrementValueLocal); } } } break; default: throw (new NotImplementedException(String.Format("Unimplemented unary operator '{0}'", Operator))); } }
public void SizeofTypeExpression(CParser.SizeofTypeExpression SizeofTypeExpression) { var Type = ConvertCTypeToType(SizeofTypeExpression.CType); SafeILGenerator.Sizeof(Type); }
public void FunctionCallExpression(CParser.FunctionCallExpression FunctionCallExpression) { var Function = FunctionCallExpression.Function; if (Function is CParser.IdentifierExpression) { var IdentifierExpression = Function as CParser.IdentifierExpression; var FunctionName = IdentifierExpression.Identifier; var ParametersExpressions = FunctionCallExpression.Parameters.Expressions; // Special functions. switch (FunctionName) { // Alloca Special Function. case "alloca": { #if true // alloca requires the stack to be empty after calling it? var Stack = SafeILGenerator.StackSave(); var AllocaAddressLocal = SafeILGenerator.DeclareLocal(typeof(void *)); { Traverse(ParametersExpressions); SafeILGenerator.StackAlloc(); } SafeILGenerator.StoreLocal(AllocaAddressLocal); SafeILGenerator.StackRestore(Stack); SafeILGenerator.LoadLocal(AllocaAddressLocal); #else var AllocaLocal = SafeILGenerator.DeclareLocal(typeof(void *), "AllocaLocal"); Traverse(FunctionCallExpression.Parameters.Expressions); //SafeILGenerator.ConvertTo(typeof(void*)); SafeILGenerator.StackAlloc(); SafeILGenerator.ConvertTo(typeof(void *)); SafeILGenerator.StoreLocal(AllocaLocal); SafeILGenerator.LoadLocal(AllocaLocal); //throw(new NotImplementedException("Currently this does not work!")); #endif } break; // Normal plain function. default: { var VariableReference = VariableScope.Find(IdentifierExpression.Identifier); var FunctionReference = FunctionScope.Find(IdentifierExpression.Identifier); if (VariableReference != null) { var CFunctionType = VariableReference.CType.GetSpecifiedCType <CFunctionType>(); var ReturnType = ConvertCTypeToType(CFunctionType.Return); var ParameterTypes = CFunctionType.Parameters.Select(Item => ConvertCTypeToType(Item.CType)).ToArray(); Traverse(ParametersExpressions); Traverse(IdentifierExpression); SafeILGenerator.CallManagedFunction(CallingConventions.Standard, ReturnType, ParameterTypes, null); } else if (FunctionReference != null) { Type[] ParameterTypes; if (FunctionReference.SafeMethodTypeInfo == null) { if (FunctionReference.MethodInfo.CallingConvention == CallingConventions.VarArgs) { ParameterTypes = FunctionCallExpression.Parameters.Expressions.Select(Expression => ConvertCTypeToType(Expression.GetCachedCType(this))).ToArray(); } else { ParameterTypes = FunctionReference.MethodInfo.GetParameters().Select(Parameter => Parameter.ParameterType).ToArray(); } } else { ParameterTypes = FunctionReference.SafeMethodTypeInfo.Parameters; } if (ParameterTypes.Length != ParametersExpressions.Length) { throw (new Exception(String.Format( "Function parameter count mismatch {0} != {1} calling function '{2}'", ParameterTypes.Length, ParametersExpressions.Length, FunctionName ))); } ParameterTypes = ParameterTypes.Select(Item => GetRealType(Item)).ToArray(); for (int n = 0; n < ParametersExpressions.Length; n++) { var Expression = ParametersExpressions[n]; var ExpressionCType = Expression.GetCachedCType(this); var ExpressionType = ConvertCTypeToType(ExpressionCType); var ParameterType = GetRealType(ParameterTypes[n]); Traverse(Expression); // Expected a string. Convert it! if (ParameterType == typeof(string)) { if (ExpressionType == typeof(sbyte *)) { SafeILGenerator.ConvertTo(typeof(sbyte *)); SafeILGenerator.Call((CLibUtils.PointerToStringDelegate)CLibUtils.GetStringFromPointer); } else { throw (new NotImplementedException(String.Format("Invalid string expression {0}", ExpressionType))); } } else { SafeILGenerator.ConvertTo(ParameterType); } } if (FunctionReference.SafeMethodTypeInfo == null && FunctionReference.MethodInfo.CallingConvention == CallingConventions.VarArgs) { //SafeILGenerator.LoadFunctionPointer(FunctionReference.MethodInfo, IsVirtual: false); //SafeILGenerator.CallManagedFunction(CallingConventions.VarArgs, FunctionReference.MethodInfo.ReturnType, ParameterTypes, null); SafeILGenerator.Call(FunctionReference.MethodInfo, FunctionReference.SafeMethodTypeInfo, ParameterTypes); } else { SafeILGenerator.Call(FunctionReference.MethodInfo, FunctionReference.SafeMethodTypeInfo); } } else { throw (new Exception(String.Format("Unknown function '{0}'", IdentifierExpression.Identifier))); } //SafeILGenerator.__ILGenerator.Emit(OpCodes.Call //throw (new NotImplementedException("Function: " + IdentifierExpression.Value)); } break; } } else { throw (new NotImplementedException()); } }
public void BinaryExpression(CParser.BinaryExpression BinaryExpression) { var Operator = BinaryExpression.Operator; var Left = BinaryExpression.Left; var LeftCType = Left.GetCachedCType(this); var LeftType = ConvertCTypeToType(LeftCType); var Right = BinaryExpression.Right; var RightCType = Right.GetCachedCType(this); var RightType = ConvertCTypeToType(RightCType); // Assignments switch (Operator) { case "<<=": case ">>=": case "&=": case "|=": case "^=": case "*=": case "/=": case "%=": case "-=": case "+=": case "=": { LocalBuilder LeftValueLocal = null; if (RequireYieldResult) { LeftValueLocal = SafeILGenerator.DeclareLocal(LeftType, "TempLocal"); } var LeftFieldAccess = Left as CParser.FieldAccessExpression; FieldInfo FieldToStore = null; MethodInfo MethodInfoToCallSet = null; MethodInfo MethodInfoToCallGet = null; // This is a field? Instead of loading the address try to perform a StoreField. if (LeftFieldAccess != null && LeftFieldAccess.Operator == ".") { var StructureCType = LeftFieldAccess.LeftExpression.GetCachedCType(this); var StructureType = ConvertCTypeToType(StructureCType); FieldToStore = StructureType.GetField(LeftFieldAccess.FieldName); MethodInfoToCallSet = StructureType.GetMethod("set_" + LeftFieldAccess.FieldName); MethodInfoToCallGet = StructureType.GetMethod("get_" + LeftFieldAccess.FieldName); if (FieldToStore == null && MethodInfoToCallSet == null) { throw(new InvalidOperationException("Null")); } DoGenerateAddress(true, () => { Traverse(LeftFieldAccess.LeftExpression); }); } // Other kind, get the address and later it will perform a StoreIndirect. else { DoGenerateAddress(true, () => { Traverse(Left); }); } // Just store. if (Operator == "=") { DoGenerateAddress(false, () => { Traverse(Right); }); } // Store the value modified. else { SafeILGenerator.Duplicate(); if (MethodInfoToCallGet != null) { SafeILGenerator.Call(MethodInfoToCallGet); } else { SafeILGenerator.LoadIndirect(LeftType); } DoGenerateAddress(false, () => { Traverse(Right); }); _DoBinaryOperation(Operator.Substring(0, Operator.Length - 1), LeftCType.GetCSimpleType().Sign); } // Convert the value to the LeftType. SafeILGenerator.ConvertTo(LeftType); // Stores the value into the temp variable without poping it. if (LeftValueLocal != null) { SafeILGenerator.Duplicate(); SafeILGenerator.StoreLocal(LeftValueLocal); } // Stores the result if (FieldToStore != null) { SafeILGenerator.StoreField(FieldToStore); } else if (MethodInfoToCallSet != null) { SafeILGenerator.Call(MethodInfoToCallSet); } else { SafeILGenerator.StoreIndirect(LeftType); } // Yields the result. if (LeftValueLocal != null) { SafeILGenerator.LoadLocal(LeftValueLocal); } } return; default: { // Pointer operations. if (LeftType.IsPointer || RightType.IsPointer) { switch (Operator) { case "+": DoGenerateAddress(false, () => { Traverse(Left); //Traverse(Right); Traverse(new CParser.BinaryExpression(Right, "*", new CParser.SizeofTypeExpression(((CPointerType)LeftCType).ElementCType))); }); //SafeILGenerator.Sizeof(LeftType.GetElementType()); //SafeILGenerator.BinaryOperation(SafeBinaryOperator.MultiplyUnsigned); SafeILGenerator.BinaryOperation(SafeBinaryOperator.AdditionUnsigned); break; case "-": // TODO: Check both types?! DoGenerateAddress(false, () => { Traverse(Left); Traverse(Right); }); SafeILGenerator.BinaryOperation(SafeBinaryOperator.SubstractionSigned); SafeILGenerator.Sizeof(LeftType.GetElementType()); SafeILGenerator.BinaryOperation(SafeBinaryOperator.DivideUnsigned); break; case ">=": case "<=": case ">": case "<": case "==": case "!=": case "&&": case "||": DoGenerateAddress(false, () => { Traverse(Left); Traverse(Right); }); _DoBinaryOperation(Operator, Left.GetCachedCType(this).GetCSimpleType().Sign); break; default: Console.Error.WriteLine("Not supported operator '{0}' for pointer aritmetic types : {1}, {2}", Operator, LeftType, RightType); throw (new NotImplementedException(String.Format("Not supported operator '{0}' for pointer aritmetic types : {1}, {2}", Operator, LeftType, RightType))); } } // Non-pointer operations else { DoBinaryOperation(Operator, Left, Right); } } break; } }
public void SizeofExpressionExpression(CParser.SizeofExpressionExpression SizeofExpressionExpression) { var Type = ConvertCTypeToType(SizeofExpressionExpression.Expression.GetCachedCType(this)); SafeILGenerator.Sizeof(Type); }
private Type DefineType(string Name, CType CType) { if (Name == null) { Name = String.Format("__anonymous_type_{0}", anonymous_type_index++); } var CUnionStructType = CType as CUnionStructType; if (CUnionStructType != null) { //var StructType = RootTypeBuilder.DefineNestedType(CSymbol.Name, TypeAttributes.NestedPublic | TypeAttributes.SequentialLayout | TypeAttributes.AnsiClass | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, typeof(ValueType), (PackingSize)4); var StructTypeAttributes = TypeAttributes.Public | TypeAttributes.AnsiClass | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit; StructTypeAttributes |= CUnionStructType.IsUnion ? TypeAttributes.ExplicitLayout : TypeAttributes.SequentialLayout; var StructType = ModuleBuilder.DefineType(Name, StructTypeAttributes, typeof(ValueType), (PackingSize)4); int AvailableBits = 0; int BitOffset = 0; FieldBuilder CurrentBitsField = null; //StructType.StructLayoutAttribute = new StructLayoutAttribute(LayoutKind.Sequential); { foreach (var Item in CUnionStructType.Items) { var ItemType = ConvertCTypeToType(Item.CType); if (Item.BitCount > 0) { if (CUnionStructType.IsUnion) { throw (new NotImplementedException()); } if (AvailableBits <= 0) { CurrentBitsField = StructType.DefineField("_bits_" + UniqueId, ItemType, FieldAttributes.Private); AvailableBits = Marshal.SizeOf(ItemType) * 8; } var PropertyGetMethod = StructType.DefineMethod("get_" + Item.Name, MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.HasThis, ItemType, new Type[] { }); var PropertySetMethod = StructType.DefineMethod("set_" + Item.Name, MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(void), new Type[] { ItemType }); int BitMask = (1 << Item.BitCount) - 1; // Getter { var ILGenerator = new SafeILGenerator(PropertyGetMethod.GetILGenerator(), CheckTypes: false, DoDebug: false, DoLog: false); var This = ILGenerator.DeclareArgument(StructType, 0, "this"); ILGenerator.LoadArgument(This); ILGenerator.LoadField(CurrentBitsField); ILGenerator.Push(BitOffset); ILGenerator.BinaryOperation(SafeBinaryOperator.ShiftRightUnsigned); ILGenerator.Push(BitMask); ILGenerator.BinaryOperation(SafeBinaryOperator.And); ILGenerator.Return(ItemType); } // Setter { var ILGenerator = new SafeILGenerator(PropertySetMethod.GetILGenerator(), CheckTypes: false, DoDebug: false, DoLog: false); var This = ILGenerator.DeclareArgument(StructType, 0, "this"); var Value = ILGenerator.DeclareArgument(ItemType, 1, "value"); ILGenerator.LoadArgument(This); { // Loads the previous value with the bits to set cleared. ILGenerator.LoadArgument(This); ILGenerator.LoadField(CurrentBitsField); ILGenerator.Push(BitMask << BitOffset); ILGenerator.UnaryOperation(SafeUnaryOperator.Not); ILGenerator.BinaryOperation(SafeBinaryOperator.And); // Loads the argument displaced. ILGenerator.LoadArgument(Value); ILGenerator.Push(BitMask); ILGenerator.BinaryOperation(SafeBinaryOperator.And); ILGenerator.Push(BitOffset); ILGenerator.BinaryOperation(SafeBinaryOperator.ShiftLeft); // Ors the old value cleared with the displaced new value. ILGenerator.BinaryOperation(SafeBinaryOperator.Or); } ILGenerator.StoreField(CurrentBitsField); ILGenerator.Return(typeof(void)); } var Property = StructType.DefineProperty(Item.Name, PropertyAttributes.None, ItemType, new Type[0]); Property.SetGetMethod(PropertyGetMethod); Property.SetSetMethod(PropertySetMethod); AvailableBits -= Item.BitCount; BitOffset += Item.BitCount; } else { var Field = StructType.DefineField(Item.Name, ItemType, FieldAttributes.Public); if (CUnionStructType.IsUnion) { Field.SetCustomAttribute(new CustomAttributeBuilder(typeof(FieldOffsetAttribute).GetConstructor(new Type[] { typeof(int) }), new object[] { 0 })); } } } //Console.Error.WriteLine("Not implemented TypeDeclaration"); } //PendingTypesToCreate.Add(StructType); StructType.CreateType(); return(StructType); } else { return(ConvertCTypeToType(CType)); //return null; //throw (new InvalidOperationException(String.Format("CStructType == null : {0}", CType))); } }
public LabelsContext(SafeILGenerator SafeILGenerator) { this.SafeILGenerator = SafeILGenerator; }
public void CastExpression(CParser.CastExpression CastExpression) { Traverse(CastExpression.Right); SafeILGenerator.ConvertTo(GetRealType(ConvertCTypeToType(CastExpression.CastType))); }
public void FloatExpression(CParser.FloatExpression FloatExpression) { SafeILGenerator.Push(FloatExpression.Value); }
public void IntegerExpression(CParser.IntegerExpression IntegerExpression) { SafeILGenerator.Push(IntegerExpression.Value); }
public void TranslationUnit(CParser.TranslationUnit TranslationUnit) { #if false try { #endif PutDebugLine(TranslationUnit); try { File.Delete(OutFolder + "\\" + OutputName); } catch { } var ClassName = Path.GetFileNameWithoutExtension(OutputName); this.AssemblyBuilder = SafeAssemblyUtils.CreateAssemblyBuilder(ClassName, OutFolder); this.ModuleBuilder = this.AssemblyBuilder.CreateModuleBuilder(OutputName); this.RootTypeBuilder = this.ModuleBuilder.DefineType(ClassName, TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit); PendingTypesToCreate.Add(this.RootTypeBuilder); var InitializerBuilder = this.RootTypeBuilder.DefineTypeInitializer(); var CurrentStaticInitializerSafeILGenerator = new SafeILGenerator(InitializerBuilder.GetILGenerator(), CheckTypes: false, DoDebug: false, DoLog: false); Scopable.RefScope(ref this.StaticInitializerSafeILGenerator, CurrentStaticInitializerSafeILGenerator, () => { Scopable.RefScope(ref this.CurrentClass, this.RootTypeBuilder, () => { AScope <VariableReference> .NewScope(ref this.VariableScope, () => { Traverse(TranslationUnit.Declarations); this.StaticInitializerSafeILGenerator.Return(typeof(void)); //RootTypeBuilder.CreateType(); foreach (var FunctionReference in FunctionScope.GetAll()) { if (!FunctionReference.BodyFinalized && FunctionReference.HasStartedBody) { Console.WriteLine("Function {0} without body", FunctionReference.Name); var FakeSafeILGenerator = new SafeILGenerator((FunctionReference.MethodInfo as MethodBuilder).GetILGenerator(), CheckTypes: true, DoDebug: true, DoLog: false); FakeSafeILGenerator.Push(String.Format("Not implemented '{0}'", FunctionReference.Name)); FakeSafeILGenerator.NewObject(typeof(NotImplementedException).GetConstructor(new Type[] { typeof(string) })); FakeSafeILGenerator.Throw(); } } foreach (var TypeToCreate in PendingTypesToCreate) { TypeToCreate.CreateType(); } if (EntryPoint != null) { this.AssemblyBuilder.SetEntryPoint(EntryPoint); } if (SaveAssembly) { // Copy the runtime. var RuntimePath = typeof(CModuleAttribute).Assembly.Location; try { File.Copy(RuntimePath, OutFolder + "\\" + Path.GetFileName(RuntimePath), overwrite: true); } catch { } /* * if (EntryPoint != null) * { * OutputName = Path.GetFileNameWithoutExtension(OutputName) + ".exe"; * } * else * { * OutputName = Path.GetFileNameWithoutExtension(OutputName) + ".dll"; * } */ #if false Console.WriteLine("Writting to {0}", OutputName); #endif //this.AssemblyBuilder.Save(OutputName, PortableExecutableKinds.Required32Bit, ImageFileMachine.I386); this.AssemblyBuilder.Save(OutputName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386); } }); }); }); #if false } catch (Exception Exception) { if (ThrowException) { throw (Exception); } while (Exception.InnerException != null) { Exception = Exception.InnerException; } Console.Error.WriteLine(""); Console.Error.WriteLine("LastPosition: {0}", LastPositionInfo); Console.Error.WriteLine("{0} : '{1}'", Exception.TargetSite, Exception.Message); if (Exception.StackTrace != null) { Console.Error.WriteLine("{0}", String.Join("\n", Exception.StackTrace.Split('\n').Take(4))); Console.Error.WriteLine(" ..."); } } #endif }
public void CharExpression(CParser.CharExpression CharExpression) { //SafeILGenerator.Push((char)CharExpression.Value); SafeILGenerator.Push((sbyte)CharExpression.Value); //SafeILGenerator.ConvertTo<sbyte>(); }
public void LongExpression(CParser.LongExpression LongExpression) { SafeILGenerator.Push(LongExpression.Value); }
/// <summary> /// /// </summary> /// <param name="ElementType"></param> /// <param name="ArrayFixedLength"></param> /// <returns></returns> protected override Type ConvertCTypeToType_GetFixedArrayType(CType ElementCType, Type ElementType, int ArrayFixedLength) { //var StructType = ModuleBuilder.DefineType(CSymbol.Name, TypeAttributes.Public | TypeAttributes.SequentialLayout | TypeAttributes.AnsiClass | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, typeof(ValueType), (PackingSize)4); var TypeName = "FixedArrayType_" + ElementType.Name.Replace("*", "Pointer") + "_" + ArrayFixedLength; var ReusedType = ModuleBuilder.GetType(TypeName); if (ReusedType != null) { return(ReusedType); } int ElementSize = 4; if (ElementType is TypeBuilder) { Console.Error.WriteLine("!(ElementType is RuntimeType) :: {0}", ElementType.GetType()); ElementSize = (ElementType as TypeBuilder).Size; if (ElementSize == 0) { ElementSize = ElementCType.GetSize(this).Value; if (ElementSize == 0) { throw (new NotImplementedException(String.Format("ElementSize = 0 : {0}", ElementSize))); } } } else { // TODO: HACK! This way we get the size of the structue on the compiling platform, not the real platform. Pointers have distinct sizes. ElementSize = (ElementType != null) ? Marshal.SizeOf(ElementType) : 8; } // TODO: Fake to get the higher size a pointer would get on x64. if (ElementType.IsPointer) { ElementSize = 8; } #if true var TempStruct = ModuleBuilder.DefineType( TypeName, TypeAttributes.Public | TypeAttributes.SequentialLayout | TypeAttributes.AnsiClass | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, typeof(ValueType), PackingSize.Unspecified, ArrayFixedLength * ElementSize ); #else var TempStruct = RootTypeBuilder.DefineNestedType( TypeName, TypeAttributes.NestedPublic | TypeAttributes.SequentialLayout | TypeAttributes.AnsiClass | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, typeof(ValueType), //PackingSize.Unspecified, ArrayFixedLength * ElementSize ); #endif var FirstElementField = TempStruct.DefineField("FirstElement", ElementType, FieldAttributes.Public); #if false var Method_get_Item = TempStruct.DefineMethod("get_Item", MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public, CallingConventions.HasThis, ElementType, new Type[] { typeof(int) }); var Method_set_Item = TempStruct.DefineMethod("set_Item", MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public, CallingConventions.HasThis, typeof(void), new Type[] { typeof(int), ElementType }); var Method_get_Item_IL = new SafeILGenerator(Method_get_Item.GetILGenerator(), CheckTypes: true, DoDebug: false, DoLog: false); var Method_set_Item_IL = new SafeILGenerator(Method_set_Item.GetILGenerator(), CheckTypes: true, DoDebug: false, DoLog: false); { // TODO: Fix address. var ThisArgument = Method_get_Item_IL.DeclareArgument(TempStruct.MakePointerType(), 0); var IndexArgument = Method_get_Item_IL.DeclareArgument(typeof(int), 1); Method_get_Item_IL.LoadArgument(ThisArgument); Method_get_Item_IL.LoadFieldAddress(FirstElementField); Method_get_Item_IL.LoadArgument(IndexArgument); Method_get_Item_IL.Sizeof(ElementType); Method_get_Item_IL.BinaryOperation(SafeBinaryOperator.MultiplySigned); Method_get_Item_IL.BinaryOperation(SafeBinaryOperator.AdditionSigned); Method_get_Item_IL.LoadIndirect(ElementType); Method_get_Item_IL.Return(ElementType); } { // TODO: Fix address. var ThisArgument = Method_get_Item_IL.DeclareArgument(TempStruct.MakePointerType(), 0); var IndexArgument = Method_get_Item_IL.DeclareArgument(typeof(int), 1); var ValueArgument = Method_get_Item_IL.DeclareArgument(ElementType, 2); Method_set_Item_IL.LoadArgument(ThisArgument); Method_set_Item_IL.LoadFieldAddress(FirstElementField); Method_set_Item_IL.LoadArgument(IndexArgument); Method_set_Item_IL.Sizeof(ElementType); Method_set_Item_IL.BinaryOperation(SafeBinaryOperator.MultiplySigned); Method_set_Item_IL.BinaryOperation(SafeBinaryOperator.AdditionSigned); Method_set_Item_IL.LoadArgument(ValueArgument); Method_set_Item_IL.StoreIndirect(ElementType); Method_set_Item_IL.Return(typeof(void)); } var PropartyItem = TempStruct.DefineProperty("Item", PropertyAttributes.SpecialName, CallingConventions.HasThis, ElementType, new Type[] { typeof(int) }); PropartyItem.SetGetMethod(Method_get_Item); PropartyItem.SetSetMethod(Method_set_Item); #endif //Method_get_Item_IL.NewObject(); //Method_get_Item_IL.Throw(); TempStruct.AddCustomAttribute <CFixedArrayAttribute>(); TempStruct.CreateType(); return(TempStruct); }
public void FieldAccessExpression(CParser.FieldAccessExpression FieldAccessExpression) { var FieldName = FieldAccessExpression.FieldName; var LeftExpression = FieldAccessExpression.LeftExpression; var LeftCType = LeftExpression.GetCachedCType(this); var LeftType = ConvertCTypeToType(LeftCType); var CUnionStructType = LeftCType.GetCUnionStructType(); CType FieldCType; if (CUnionStructType != null) { FieldCType = CUnionStructType.GetFieldByName(FieldName).CType; } else { throw (new NotImplementedException(String.Format("Unknown CTYpe {0}", LeftCType))); } //Console.WriteLine(LeftCType.GetType()); //= LeftCType.GetFieldByName(FieldName).CType; FieldInfo FieldInfo; MethodInfo MethodInfo; Type FinalStructType; if (LeftType.IsPointer) { if (FieldAccessExpression.Operator != "->") { throw (new InvalidOperationException("A pointer structure should be accesses with the '->' operator")); } FinalStructType = LeftType.GetElementType(); } else { if (FieldAccessExpression.Operator != ".") { throw (new InvalidOperationException("A non-pointer structure should be accesses with the '.' operator")); } FinalStructType = LeftType; } FieldInfo = FinalStructType.GetField(FieldName); MethodInfo = FinalStructType.GetMethod("get_" + FieldName); if (FieldInfo == null && MethodInfo == null) { throw (new Exception(String.Format("Can't find field name {0}.{1}", LeftType, FieldName))); } if (MethodInfo != null && GenerateAddress) { throw(new InvalidOperationException("Can't generate address for a property")); } //Console.WriteLine(FieldInfo); DoGenerateAddress(true, () => { Traverse(FieldAccessExpression.LeftExpression); }); //Console.WriteLine(FieldCType); // For fixed array types, get always the address? if (GenerateAddress || FieldCType is CArrayType) { if (FieldInfo != null) { SafeILGenerator.LoadFieldAddress(FieldInfo, UseLoadFieldAddress: false); } else { throw(new InvalidOperationException()); } } else { if (FieldInfo != null) { SafeILGenerator.LoadField(FieldInfo); } else if (MethodInfo != null) { SafeILGenerator.Call(MethodInfo); } else { throw (new InvalidOperationException()); } } //SafeILGenerator.LoadField //throw(new NotImplementedException()); }