Пример #1
0
        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)));
            }
        }
Пример #2
0
        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));
            }
        }
Пример #3
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);
        }
Пример #4
0
        public void StringExpression(CParser.StringExpression StringExpression)
        {
            //CurrentClass.DefineField(
            //SafeILGenerator.LoadNull();
            //SafeILGenerator.CastClass(CurrentClass);

            SafeILGenerator.LoadField(GetStringPointerField(StringExpression.String));
            //SafeILGenerator.Push(StringExpression.Value);
        }
Пример #5
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="Operator"></param>
 private void _DoBinaryLeftRightPost(string Operator)
 {
     switch (Operator)
     {
     case "&&":
     case "||":
         SafeILGenerator.ConvertTo <bool>();
         break;
     }
 }
Пример #6
0
 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);
 }
Пример #7
0
        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);
            }
        }
Пример #8
0
        /// <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);
            }
        }
Пример #9
0
 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);
     }
 }
Пример #10
0
        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
        }
Пример #11
0
 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);
     }
 }
Пример #12
0
        /// <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)));
            }
        }
Пример #13
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"));
     }
 }
Пример #14
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"));
     }
 }
Пример #15
0
        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);
            }
        }
Пример #16
0
        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,
            });
        }
Пример #18
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)));
            }
        }
Пример #19
0
        public void SizeofTypeExpression(CParser.SizeofTypeExpression SizeofTypeExpression)
        {
            var Type = ConvertCTypeToType(SizeofTypeExpression.CType);

            SafeILGenerator.Sizeof(Type);
        }
Пример #20
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());
            }
        }
Пример #21
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;
            }
        }
Пример #22
0
        public void SizeofExpressionExpression(CParser.SizeofExpressionExpression SizeofExpressionExpression)
        {
            var Type = ConvertCTypeToType(SizeofExpressionExpression.Expression.GetCachedCType(this));

            SafeILGenerator.Sizeof(Type);
        }
Пример #23
0
        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)));
            }
        }
Пример #24
0
 public LabelsContext(SafeILGenerator SafeILGenerator)
 {
     this.SafeILGenerator = SafeILGenerator;
 }
Пример #25
0
 public void CastExpression(CParser.CastExpression CastExpression)
 {
     Traverse(CastExpression.Right);
     SafeILGenerator.ConvertTo(GetRealType(ConvertCTypeToType(CastExpression.CastType)));
 }
Пример #26
0
 public void FloatExpression(CParser.FloatExpression FloatExpression)
 {
     SafeILGenerator.Push(FloatExpression.Value);
 }
Пример #27
0
 public void IntegerExpression(CParser.IntegerExpression IntegerExpression)
 {
     SafeILGenerator.Push(IntegerExpression.Value);
 }
Пример #28
0
        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
        }
Пример #29
0
 public void CharExpression(CParser.CharExpression CharExpression)
 {
     //SafeILGenerator.Push((char)CharExpression.Value);
     SafeILGenerator.Push((sbyte)CharExpression.Value);
     //SafeILGenerator.ConvertTo<sbyte>();
 }
Пример #30
0
 public void LongExpression(CParser.LongExpression LongExpression)
 {
     SafeILGenerator.Push(LongExpression.Value);
 }
Пример #31
0
        /// <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);
        }
Пример #32
0
        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());
        }