Пример #1
0
        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);
        }
Пример #2
0
 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"));
     }
 }
Пример #3
0
 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"));
     }
 }
Пример #4
0
        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)));
            }
        }
Пример #5
0
        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;
            }
        }
Пример #6
0
        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());
            }
        }