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 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 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 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 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()); } }