Пример #1
0
		public void Initialize()
		{
			if (options == null)
				InitializeConfig();

			if (compilationContext == null)
			{
				string siteRoot = AppDomain.CurrentDomain.BaseDirectory;
				compilationContext = new WebCompilationContext(
					new DirectoryInfo(siteRoot), new DirectoryInfo(options.CompilerOptions.TemporarySourceFilesDirectory));
			}
			#region TODO
			//TODO: think about CommonScripts implementation in c#/VB.NET 
			#endregion

			LoadCompiledViews();
			if (options.CompilerOptions.AutoRecompilation)
			{
				// invalidate compiled views cache on any change to the view sources
				ViewSourceLoader.ViewChanged += delegate(object sender, FileSystemEventArgs e)
				{
					if (e.Name.EndsWith(".aspx", StringComparison.InvariantCultureIgnoreCase))
					{
						needsRecompiling = true;
					}
				};
			}
		}
Пример #2
0
        /// <inheritdoc/>
        public bool TryCompile(IReadOnlyList <MathExpression> arguments, ICompilationContext <object?> context, ITypeHintHandler typeHintHandler, [MaybeNullWhen(false)] out Expression expr)
        {
            if (arguments.Count != 1)
            {
                expr = null;
                return(false);
            }

            var argExpr = context.Transform(arguments.First());

            if (argExpr.Type == typeof(float) || argExpr.Type == typeof(double))
            { // if this is a floating point
                var method = Helpers.GetMethod <Action <double> >(d => Math.Log(d)) !;

                expr = Expression.Call(method, CompilerHelpers.ConvertToType(argExpr, typeof(double)));
                return(true);
            }
            else if (CompilerHelpers.IsFloating(argExpr.Type) || CompilerHelpers.IsIntegral(argExpr.Type))
            { // if this is a built-in integer or decimal
                var method = Helpers.GetMethod <Action <decimal> >(d => DecimalMath.Ln(d)) !;

                expr = Expression.Call(method, CompilerHelpers.ConvertToType(argExpr, typeof(decimal)));
                return(true);
            }

            expr = null;
            return(false);
        }
Пример #3
0
		public OfflineCompiler(ICodeProviderAdapterFactory codeProviderAdapterFactory, IPreProcessor preProcessor, ICompilationContext context, AspViewCompilerOptions options, IFileSystemAdapter fileSystem)
			: base(codeProviderAdapterFactory, preProcessor, context, options)
		{
			this.fileSystem = fileSystem;
			parameters.GenerateInMemory = false;
			parameters.OutputAssembly = Path.Combine(context.BinFolder.FullName, "CompiledViews.dll");
		}
Пример #4
0
        public void Initialize()
        {
            if (options == null)
            {
                InitializeConfig();
            }

            if (compilationContext == null)
            {
                string siteRoot = AppDomain.CurrentDomain.BaseDirectory;
                compilationContext = new WebCompilationContext(
                    new DirectoryInfo(siteRoot), new DirectoryInfo(options.CompilerOptions.TemporarySourceFilesDirectory));
            }
            #region TODO
            //TODO: think about CommonScripts implementation in c#/VB.NET
            #endregion

            LoadCompiledViews();
            if (options.CompilerOptions.AutoRecompilation)
            {
                // invalidate compiled views cache on any change to the view sources
                ViewSourceLoader.ViewChanged += delegate(object sender, FileSystemEventArgs e)
                {
                    if (e.Name.EndsWith(".aspx", StringComparison.InvariantCultureIgnoreCase))
                    {
                        needsRecompiling = true;
                    }
                };
            }
        }
Пример #5
0
        public ExpressionResult Compile(
            ArrayAllocationExpression expression,
            PreferredRegister target,
            ICompilationContext context
            )
        {
            var codeGen       = context.Generator;
            var linkingInfo   = context.Linking;
            var index         = context.CompileExpression(expression.Count, new PreferredRegister(Register64.R8));
            var indexType     = index.ValueType;
            var valueTypeSize = (sbyte)expression.Type.SizeOf();

            Constants.LongType.AssertCanAssignImplicitly(indexType);

            // Array allocation compiles to function call of HeapAlloc (kernel32)
            index.GenerateMoveTo(Register64.R8, Constants.LongType, codeGen, linkingInfo); // Parameter 3: byte count
            if (valueTypeSize > 1)
            {
                codeGen.Shl(Register64.R8, (sbyte)Math.Log(valueTypeSize, 2)); // 8 byte type -> multiply count by 8 by shifting left 3
            }
            codeGen.Add(Register64.R8, (sbyte)8);                              // llama length value


            codeGen.MovFromDereferenced4(Register64.RCX, Constants.DummyOffsetInt);
            linkingInfo.FixDataOffset(codeGen.StreamPosition, Constants.HeapHandleIdentifier); // Parameter 1: DefaultHeapHandle

            codeGen.Xor(Register64.RDX, Register64.RDX);
            codeGen.Add(Register64.RDX, (sbyte)(0x8 + 0x4)); // Parameter 2: HEAP_ZERO_MEMORY + HEAP_GENERATE_EXCEPTIONS

            codeGen.CallDereferenced4(Constants.DummyOffsetInt);
            linkingInfo.FixIATEntryOffset(codeGen.StreamPosition, "kernel32.dll", "HeapAlloc");

            return(new ExpressionResult(new Type(expression.Type, Type.WrappingType.ArrayOf), Register64.RAX));
        }
Пример #6
0
        public ExpressionResult Compile(
            IExpression expression,
            PreferredRegister target,
            ICompilationContext context
            )
        {
            switch (expression)
            {
            case ArrayAccessExpression arrayAccessExpression:
                return(context.CompileExpression(arrayAccessExpression, target));

            case ArrayAllocationExpression arrayAllocationExpression:
                return(context.CompileExpression(arrayAllocationExpression, target));

            case AtomicExpression atomicExpression:
                return(context.CompileExpression(atomicExpression, target));

            case BinaryOperatorExpression binaryOperatorExpression:
                return(context.CompileExpression(binaryOperatorExpression, target));

            case FunctionCallExpression methodCallExpression:
                return(context.CompileExpression(methodCallExpression, target));

            case TypeCastExpression typeCastExpression:
                return(context.CompileExpression(typeCastExpression, target));

            case UnaryOperatorExpression unaryOperatorExpression:
                return(context.CompileExpression(unaryOperatorExpression, target));

            default:
                throw new NotImplementedException($"Compiler for expression type \"{expression.GetType().Name}\" has not yet been implemented");
            }
        }
Пример #7
0
        private static ExpressionResult CompileModolu(
            IExpression left,
            IExpression right,
            PreferredRegister target,
            ICompilationContext context
            )
        {
            var leftRegisterPref = new PreferredRegister(Register64.RAX, target.FloatRegister);

            var(leftReg, rightExpr, type) = PrepareBinaryExpression(
                left,
                right,
                leftRegisterPref,
                context,
                true
                );

            if (type.IsIntegerRegisterType())
            {
                var typeIsByte = CompileIntegerDivision(context.Generator, context.Linking, type, leftReg, rightExpr);
                if (typeIsByte)                          // for byte op. the remainder is stored in 'ah' instead
                {
                    context.Generator.Write(0x8A, 0xD4); // mov dl, ah
                }
                return(new ExpressionResult(type, new PreferredRegister(Register64.RDX).MakeFor(type)));
            }

            throw new NotImplementedException(
                      $"{nameof(BinaryOperationCompiler)}: {nameof(CompileModolu)}: I do not know how to compile this type: {type}"
                      );
        }
Пример #8
0
        private static ExpressionResult CompileComparison(
            IExpression left,
            IExpression right,
            PreferredRegister target,
            ICompilationContext context,
            Action <sbyte> comparisonJmpSigned,
            Action <sbyte> comparisonJmpUnsignedd,
            bool inverted = false
            )
        {
            var(leftReg, rightExpr, type) = PrepareBinaryExpression(
                left,
                right,
                target,
                context,
                true
                );
            if (type.IsIntegerRegisterType())
            {
                rightExpr.CmpTo(leftReg, context.Generator, context.Linking);
            }
            else if (type == Constants.DoubleType)
            {
                rightExpr.ComisdTo(leftReg, context.Generator, context.Linking);
            }
            else if (type == Constants.FloatType)
            {
                rightExpr.ComissTo(leftReg, context.Generator, context.Linking);
            }
            else
            {
                throw new NotImplementedException(
                          $"{nameof(BinaryOperationCompiler)}: {nameof(CompileComparison)}: I do not know how to compile this type: {type}"
                          );
            }

            var targetRegister = target.MakeFor(Constants.BoolType);

            var mov1CodeGen = new CodeGen();

            mov1CodeGen.Mov(targetRegister.AsR32(), inverted ? 0 : 1);
            var mov0CodeGen = new CodeGen();

            mov0CodeGen.Mov(targetRegister.AsR32(), inverted ? 1 : 0);
            mov0CodeGen.Jmp(mov1CodeGen.GetBufferSpan().Length);

            if (type.IsSignedInteger())
            {
                comparisonJmpSigned((sbyte)mov0CodeGen.GetBufferSpan().Length);
            }
            else
            {
                comparisonJmpUnsignedd((sbyte)mov0CodeGen.GetBufferSpan().Length);
            }

            context.Generator.Write(mov0CodeGen.GetBufferSpan());
            context.Generator.Write(mov1CodeGen.GetBufferSpan());
            return(new ExpressionResult(Constants.BoolType, targetRegister));
        }
 public override Expression Compile(ICompilationContext context, BinaryExpression expression)
 {
     return(Expression.MakeBinary(
                expression.NodeType,
                serializer.Compile(context, expression.Left),
                serializer.Compile(context, expression.Right)
                ));
 }
Пример #10
0
 protected AbstractCompiler(ICodeProviderAdapterFactory codeProviderAdapterFactory, IPreProcessor preProcessor, ICompilationContext context, AspViewCompilerOptions options)
 {
     this.preProcessor = preProcessor;
     this.context      = context;
     this.options      = options;
     codeProvider      = codeProviderAdapterFactory.GetAdapter();
     InitialiseCompilerParameters(options.Debug);
 }
Пример #11
0
		protected AbstractCompiler(ICodeProviderAdapterFactory codeProviderAdapterFactory, IPreProcessor preProcessor, ICompilationContext context, AspViewCompilerOptions options)
		{
			this.preProcessor = preProcessor;
			this.context = context;
			this.options = options;
			codeProvider = codeProviderAdapterFactory.GetAdapter();
			InitialiseCompilerParameters(options.Debug);
		}
Пример #12
0
            public bool TryCompile(IReadOnlyList <MathExpression> arguments, ICompilationContext <object?> context, ITypeHintHandler hinting, out Expression expr)
            {
                var arg          = arguments.First();
                var concatMethod = Helpers.GetMethod <Action <string> >(a => string.Concat(a, a)) !;

                expr = Expression.Call(typeof(Convert), nameof(Convert.ToString), null, context.Transform(arg));
                expr = Expression.Call(concatMethod, Expression.Constant("hello "), expr);
                return(true);
            }
        public override Expression Compile(ICompilationContext context, LambdaExpression expression)
        {
            var parameters = expression.Parameters
                             .Where(parameter => !context.ParametersValues.ContainsKey(parameter.Name))
                             .Select(parameter => serializer.Compile(context, parameter) as ParameterExpression);

            return(Expression.Lambda(
                       serializer.Compile(context, expression.Body),
                       false,
                       parameters
                       ));
        }
Пример #14
0
        public override Expression Compile(ICompilationContext context, ParameterExpression expression)
        {
            if (!context.ParametersValues.ContainsKey(expression.Name))
            {
                return(expression);
            }

            return(Expression.Constant(
                       Convert.ChangeType(context.ParametersValues[expression.Name], expression.Type),
                       expression.Type
                       ));
        }
Пример #15
0
        public void Compile(
            For statement,
            ICompilationContext context
            )
        {
            context.Symbols.PushLocalScope();
            context.CompileStatement(statement.Variable);

            var bodyAndIncrement = statement.Instruction.StatementAsBlock().Statements.Concat(new[] { statement.Increment }).ToArray();
            var equalWhile       = new While(statement.Condition, new CodeBlock(bodyAndIncrement));

            _whileCompiler.Compile(equalWhile, context);
            context.Symbols.PopLocalScope();
        }
Пример #16
0
        public void Compile(
            While statement,
            ICompilationContext context
            )
        {
            var codeGen                = context.Generator;
            var conditionStart         = codeGen.StreamPosition;
            var whileConditionResult   = context.CompileExpression(statement.Condition, new PreferredRegister(Register64.RAX));
            var whileConditionRegister = whileConditionResult.GetOccupiedOrVolatile(Constants.BoolType);

            whileConditionResult.GenerateMoveTo(whileConditionRegister, Constants.BoolType, codeGen, context.Linking);

            codeGen.Test(whileConditionRegister, whileConditionRegister);

            var childContext = context.CreateChildContext();

            childContext.CompileStatement(statement.Instruction.StatementAsBlock());

            var bodySpan   = childContext.Generator.GetBufferSpan();
            var bodyLength = bodySpan.Length + JmpIntSize; // assume far jmp will be generated

            if (bodyLength <= sbyte.MaxValue)
            {
                codeGen.Je((sbyte)bodyLength);
            }
            else
            {
                codeGen.Je(bodyLength);
            }
            var farJmpGuessPos = codeGen.StreamPosition;

            childContext.CopyToContext(context);

            var offsetToStart = conditionStart - codeGen.StreamPosition;

            if (offsetToStart >= sbyte.MinValue)
            {
                codeGen.Jmp((sbyte)(offsetToStart - JmpSbyteSize));

                // near jmp has been generated, but we assume a far jmp above
                // if this is a near jmp, the other has to be too
                // so it's safe to say, we just need to edit the byte.
                // The new value has to fit, because the jmp becomes even nearer.
                codeGen.GetBufferSpan().Slice((int)farJmpGuessPos - 1, 1)[0] -= (byte)(JmpIntSize - JmpSbyteSize);
            }
            else
            {
                codeGen.Jmp((int)(offsetToStart - JmpIntSize));
            }
        }
Пример #17
0
        public void Compile(
            CodeBlock statement,
            ICompilationContext context
            )
        {
            context.Symbols.PushLocalScope();
            foreach (var subStatement in statement.Statements)
            {
                switch (subStatement)
                {
                case CodeBlock codeBlock:
                    Compile(codeBlock, context);
                    break;

                case Declaration declaration:
                    context.CompileStatement(declaration);
                    break;

                case For @for:
                    context.CompileStatement(@for);
                    break;

                case If @if:
                    context.CompileStatement(@if);
                    break;

                case While @while:
                    context.CompileStatement(@while);
                    break;

                case Return @return:
                    context.CompileStatement(@return);
                    break;

                case IExpression expression:
                    context.CompileExpression(
                        expression,
                        new PreferredRegister(Register64.RAX, XmmRegister.XMM0)
                        );
                    break;

                default:
                    throw new NotImplementedException(
                              $"{nameof(CodeBlockCompiler)}: I do not know how to compile: {subStatement.GetType().Name}"
                              );
                }
            }

            context.Symbols.PopLocalScope();
        }
Пример #18
0
        public void Compile(
            If statement,
            ICompilationContext context
            )
        {
            var preferredRegisterCondition = new PreferredRegister(Register64.RAX);
            var ifConditionResult          = context.CompileExpression(statement.Condition, preferredRegisterCondition);

            ifConditionResult.GenerateMoveTo(preferredRegisterCondition.MakeFor(Constants.BoolType), context.Generator, context.Linking);
            context.Generator.Test(Register8.AL, Register8.AL);

            var ifBody   = context.CreateChildContext();
            var elseBody = context.CreateChildContext();

            if (statement.ElseInstruction != null)
            {
                elseBody.CompileStatement(statement.ElseInstruction.StatementAsBlock());
            }

            ifBody.CompileStatement(statement.Instruction.StatementAsBlock());

            var elseBodySpan = elseBody.Generator.GetBufferSpan();

            if (elseBodySpan.Length > 0)
            {
                if (elseBodySpan.Length <= sbyte.MaxValue)
                {
                    ifBody.Generator.Jmp((sbyte)elseBodySpan.Length);
                }
                else
                {
                    ifBody.Generator.Jmp(elseBodySpan.Length);
                }
            }

            var ifBodySpan = ifBody.Generator.GetBufferSpan();

            if (ifBodySpan.Length <= sbyte.MaxValue)
            {
                context.Generator.Je((sbyte)ifBodySpan.Length);
            }
            else
            {
                context.Generator.Je(ifBodySpan.Length);
            }

            ifBody.CopyToContext(context);
            elseBody.CopyToContext(context);
        }
Пример #19
0
        /// <inheritdoc/>
        public bool TryCompile(IReadOnlyList <MathExpression> arguments, ICompilationContext <object?> context, ITypeHintHandler typeHintHandler, [MaybeNullWhen(false)] out Expression expr)
        {
            // TODO: add logging to contexts
            if (arguments.Count != 1)
            {
                expr = null;
                return(false);
            }

            expr = Expression.Call(Method,
                                   CompilerHelpers.ConvertToType(
                                       typeHintHandler.TransformWithHint(arguments.First(), typeof(double), context),
                                       typeof(double)));
            return(true);
        }
Пример #20
0
 public ExpressionResult Compile(
     AtomicExpression expression,
     PreferredRegister target,
     ICompilationContext context
     )
 {
     return(expression.Token.Kind switch
     {
         TokenKind.Identifier => CompileIdentifier(expression, context.Generator, context.Symbols),
         TokenKind.FloatLiteral => CompileFloatLiteral(expression),
         TokenKind.IntegerLiteral => CompileIntegerLiteral(expression),
         TokenKind.StringLiteral => CompileStringLiteral(expression, context.Generator, target, context.Linking),
         TokenKind.True => CompileTrue(context.Generator, target),
         TokenKind.False => CompileFalse(context.Generator, target),
         _ => throw new NotImplementedException($"Atomic expression type {expression.Token.Kind} not implemented")
     });
Пример #21
0
        public void Compile(Declaration statement, ICompilationContext context)
        {
            context.Symbols.DefineLocal(statement.Identifier.RawText, statement.Type);
            if (statement.InitialValue == null)
            {
                context.Generator.Xor(Register64.RAX, Register64.RAX);
                context.Generator.MovToDereferenced(Register64.RSP, Register64.RAX, context.Symbols.GetLocalOffset(statement.Identifier.RawText));
            }
            else
            {
                var initialValue         = context.CompileExpression(statement.InitialValue, PreferredRegister.DefaultVolatile);
                var initialValueRegister = initialValue.ToRegister(statement.Type, context.Generator, context.Linking);

                context.Symbols.GetLocalReference(statement.Identifier.RawText)
                .GenerateAssign(initialValueRegister, context.Generator, context.Linking);
            }
        }
Пример #22
0
        public void Compile(
            Return statement,
            ICompilationContext context
            )
        {
            if (statement.ReturnValue != null)
            {
                var returnRegisters = new PreferredRegister(Register64.RAX, XmmRegister.XMM0);
                var returnResult    = context.CompileExpression(statement.ReturnValue, returnRegisters);
                var myFunction      = context.Symbols.GetFunctionDeclaration(context.Symbols.CurrentFunctionIdentifier);

                returnResult.GenerateMoveTo(returnRegisters.MakeFor(myFunction.ReturnType), myFunction.ReturnType, context.Generator, context.Linking);
            }

            context.Generator.Jmp(Constants.DummyOffsetInt);
            context.Linking.FixFunctionEpilogueOffset(context.Generator.StreamPosition, context.Symbols.CurrentFunctionIdentifier);
        }
        /// <summary>
        /// Compiles the given expression using the provided context.
        /// </summary>
        /// <param name="expr">the <see cref="MathExpression"/> to compile</param>
        /// <param name="ctx">the context to compile in</param>
        /// <returns>the compiled <see cref="Expression"/></returns>
        public override Expression ApplyTo(MathExpression expr, ICompilationContext <TSettings> ctx)
        {
            try
            {
                if (!IsRootExpression(ctx))
                {
                    return(base.ApplyTo(expr, ctx));
                }

                SetRootExpression(ctx);

                SetTypeHint(ctx, ctx.Settings.ExpectReturn);
                var subexpr = base.ApplyTo(expr, ctx);
                if (subexpr.Type != ctx.Settings.ExpectReturn)
                {
                    subexpr = CompilerHelpers.ConvertToType(subexpr, ctx.Settings.ExpectReturn);
                }

                if (ctx.Settings is IDomainRestrictionSettings domainSettings && !domainSettings.IgnoreDomainRestrictions)
                {
                    var overflowCtor = Helpers.GetConstructor <Action>(() => new OverflowException(""));
                    subexpr = DomainRestrictionSettings.GetDomainRestrictionsFor(ctx)
                              .Select(e =>
                    {
                        SetTypeHint(ctx, typeof(bool));
                        return(x: CompilerHelpers.ConvertToType(base.ApplyTo(e, ctx), typeof(bool)), e);
                    })
                              .Aggregate(subexpr, (start, restrict) =>
                                         Expression.Condition(restrict.x,
                                                              Expression.Throw(Expression.New(overflowCtor, Expression.Constant($"{restrict.e} not in domain")), start.Type),
                                                              start));
                }

                return(subexpr);
            }
            catch (CompilationException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw new CompilationException(expr, e);
            }
        }
Пример #24
0
        /// <summary>
        ///     Evaluates two expressions, and brings them to a common type. Tries to keep the second expression as reference, for
        ///     mor optimal code generation.
        /// </summary>
        /// <param name="first"></param>
        /// <param name="second"></param>
        /// <param name="preferredFirst"></param>
        /// <param name="codeGen"></param>
        /// <param name="storageManager"></param>
        /// <param name="scope"></param>
        /// <param name="linkingInfo"></param>
        /// <param name="context"></param>
        /// <param name="shouldDereferenceForImplicitCast">The reference may be deferenced to cast it to the common type</param>
        /// <returns></returns>
        private static (Register register, ExpressionResult reference, Type type) PrepareBinaryExpression(
            IExpression first,
            IExpression second,
            PreferredRegister preferredFirst,
            ICompilationContext context,
            bool shouldDereferenceForImplicitCast = false
            )
        {
            var firstResult        = context.CompileExpression(first, preferredFirst);
            var isfirstIntegerType = firstResult.ValueType.IsIntegerRegisterType();
            var firstTemp          = context.Storage.Allocate(isfirstIntegerType);

            firstTemp.Store(firstResult, context.Generator, context.Linking);

            var secondResult = context.CompileExpression(second, preferredFirst);
            var type         = firstResult.ValueType;

            if (firstResult.ValueType != secondResult.ValueType)
            {
                if (secondResult.ValueType.CanAssignImplicitly(firstResult.ValueType))
                {
                    type = secondResult.ValueType;
                }
                else if (shouldDereferenceForImplicitCast && firstResult.ValueType.CanAssignImplicitly(secondResult.ValueType))
                {
                    type = firstResult.ValueType;

                    var secondDerefVolatile = secondResult.GetOccupiedOrVolatile(type);
                    secondResult.GenerateMoveTo(secondDerefVolatile, type, context.Generator, context.Linking);
                    secondResult = new ExpressionResult(type, secondDerefVolatile);
                }
                else
                {
                    throw new TypeMismatchException("Any common type", $"{firstResult.ValueType} and {secondResult.ValueType}");
                }
            }

            var preferredRegister = preferredFirst.MakeFor(type);
            var firstRegister     = secondResult.IsOccopied(preferredRegister) ? secondResult.GetUnoccupiedVolatile(type) : preferredRegister;

            firstTemp.AsExpressionResult(firstResult.ValueType).GenerateMoveTo(firstRegister, type, context.Generator, context.Linking);
            context.Storage.Release(firstTemp);
            return(firstRegister, secondResult, type);
        }
        /// <inheritdoc/>
        public override Expression ApplyTo(Syntax.BinaryExpression expr, ICompilationContext <TSettings> ctx)
        {
            var exprType = expr.Type;
            var args     = expr.Arguments.Select(m =>
            {
                var origHint = GetTypeHint(ctx);
                if (exprType.IsComparisonType())
                {
                    SetTypeHint(ctx, null);
                }
                else if (exprType.IsBooleanType())
                {
                    SetTypeHint(ctx, typeof(bool));
                }
                var applied = ApplyTo(m, ctx);
                SetTypeHint(ctx, origHint);
                return(applied);
            }).ToList();
            var boolResType = exprType.IsComparisonType() ? typeof(bool) : GetTypeHint(ctx) ?? args.First().Type;

            try
            {
                return(AggregateBinaryExpr(expr.Type, args, boolResType, ctx.Settings));
            }
            catch
            {
                // ignore
            }

            // if we fail to do it with the base implicitly gotten arguments, attempt to convert all arguments to the same (largest) type
            var allTypes     = args.Select(e => e.Type);
            var convertAllTo = allTypes
                               .OrderByDescending(CompilerHelpers.EstimateTypeSize)
                               .Where(ty => allTypes.All(t => CompilerHelpers.HasConversionPathTo(t, ty)))
                               .First(); // biggest one

            boolResType = GetTypeHint(ctx) ?? convertAllTo;
            // re-compile arguments with new type hint
            SetTypeHint(ctx, convertAllTo);
            args = expr.Arguments.Select(m => CompilerHelpers.ConvertToType(ApplyTo(m, ctx), convertAllTo)).ToList();

            return(AggregateBinaryExpr(expr.Type, args, boolResType, ctx.Settings));
        }
Пример #26
0
        private static ExpressionResult CompileMultiply(
            IExpression left,
            IExpression right,
            PreferredRegister target,
            ICompilationContext context
            )
        {
            var tempRegister = new PreferredRegister(Register64.RAX, target.FloatRegister);

            var(leftReg, rightExpr, type) = PrepareBinaryExpression(
                left,
                right,
                tempRegister,
                context,
                true
                );

            if (type.IsIntegerRegisterType())
            {
                if (type.SizeOf() == 1)
                {
                    throw new NotImplementedException("Multiplications with 8-bit types are not implemented");
                }

                rightExpr.ImulTo(leftReg, context.Generator, context.Linking);
            }
            else if (type == Constants.DoubleType)
            {
                rightExpr.MulsdTo(leftReg, context.Generator, context.Linking);
            }
            else if (type == Constants.FloatType)
            {
                rightExpr.MulssTo(leftReg, context.Generator, context.Linking);
            }
            else
            {
                throw new NotImplementedException(
                          $"{nameof(BinaryOperationCompiler)}: {nameof(CompileMultiply)}: I do not know how to compile this type: {type}"
                          );
            }

            return(new ExpressionResult(type, leftReg));
        }
Пример #27
0
        private static ExpressionResult CompileDivide(
            IExpression left,
            IExpression right,
            PreferredRegister target,
            ICompilationContext context
            )
        {
            var leftRegisterPref = new PreferredRegister(Register64.RAX, target.FloatRegister);

            var(leftReg, rightExpr, type) = PrepareBinaryExpression(
                left,
                right,
                leftRegisterPref,
                context,
                true
                );

            if (type.IsIntegerRegisterType())
            {
                CompileIntegerDivision(context.Generator, context.Linking, type, leftReg, rightExpr);
                return(new ExpressionResult(type, new PreferredRegister(Register64.RAX).MakeFor(type)));
            }

            if (type == Constants.DoubleType)
            {
                rightExpr.DivsdTo(leftReg, context.Generator, context.Linking);
            }
            else if (type == Constants.FloatType)
            {
                rightExpr.DivssTo(leftReg, context.Generator, context.Linking);
            }
            else
            {
                throw new NotImplementedException(
                          $"{nameof(BinaryOperationCompiler)}: {nameof(CompileDivide)}: I do not know how to compile this type: {type}"
                          );
            }

            return(new ExpressionResult(type, leftReg));
        }
Пример #28
0
        public ExpressionResult Compile(
            ArrayAccessExpression expression,
            PreferredRegister target,
            ICompilationContext context
            )
        {
            var arrayTemp = context.Storage.Allocate(true);
            var array     = context.CompileExpression(expression.Array, arrayTemp.IsRegister ? arrayTemp.Register : Register64.RAX);
            var arrayType = array.ValueType;

            arrayTemp.Store(array, context.Generator, context.Linking);

            const Register64 structOffsetRegister = Register64.RCX;
            const Register64 arrayRegister        = Register64.RAX;
            var arrayIndex = context.CompileExpression(expression.Index, new PreferredRegister(structOffsetRegister));

            Constants.LongType.AssertCanAssignImplicitly(arrayIndex.ValueType);

            arrayIndex.GenerateMoveTo(structOffsetRegister, Constants.LongType, context.Generator, context.Linking);
            arrayTemp.AsExpressionResult(arrayType).GenerateMoveTo(arrayRegister, context.Generator, context.Linking);
            context.Storage.Release(arrayTemp);

            if (arrayType == Constants.CstrType)
            {
                return(new ExpressionResult(Constants.SbyteType, arrayRegister, structOffsetRegister, 1));
            }

            var itemType = arrayType.Child;

            if (arrayType.ChildRelation == Type.WrappingType.PointerOf)
            {
                return(new ExpressionResult(itemType, arrayRegister, structOffsetRegister, (byte)itemType.SizeOf()));
            }
            if (arrayType.ChildRelation == Type.WrappingType.ArrayOf)
            {
                return(new ExpressionResult(itemType, arrayRegister, structOffsetRegister, (byte)itemType.SizeOf(), 8));
            }

            throw new TypeMismatchException("Array or pointer", arrayType.ToString());
        }
Пример #29
0
        public Expression Compile(ICompilationContext context, Expression expression)
        {
            var    expressionType = expression.GetType();
            object handler;

            do
            {
                handler = serviceProvider.GetService(
                    typeof(IExpressionCompiler <>).MakeGenericType(expressionType)
                    );
                expressionType = expressionType.GetTypeInfo().BaseType;
            }while (handler == null && expressionType != typeof(Expression));

            if (handler == null)
            {
                throw new InvalidOperationException(
                          $"No compiler registered for expression type {expression.GetType()}"
                          );
            }

            return((handler as IExpressionCompiler).Compile(context, expression));
        }
Пример #30
0
        /// <inheritdoc/>
        public bool TryCompile(IReadOnlyList <MathExpression> arguments, ICompilationContext <object?> ctx, ITypeHintHandler hintHandler, [MaybeNullWhen(false)] out Expression expr)
        {
            if (arguments.Count != 3)
            {
                expr = null;
                return(false);
            }

            var condition = hintHandler.TransformWithHint(arguments.First(), typeof(bool), ctx);

            var        hint = hintHandler.CurrentHint(ctx);
            Expression?thenExpr = null, elseExpr = null;
            Type?      convertAllTo, lastThen, lastElse;

            do
            {
                lastThen = thenExpr?.Type;
                lastElse = elseExpr?.Type;
                thenExpr = hintHandler.TransformWithHint(arguments[1], hint, ctx);
                elseExpr = hintHandler.TransformWithHint(arguments[2], hint, ctx);

                var allTypes = new[] { thenExpr.Type, elseExpr.Type };
                convertAllTo = allTypes
                               .OrderByDescending(CompilerHelpers.EstimateTypeSize)
                               .Where(ty => allTypes.All(t => CompilerHelpers.HasConversionPathTo(t, ty)))
                               .FirstOrDefault(); // biggest one
            }while (thenExpr.Type != elseExpr.Type && thenExpr.Type != convertAllTo &&
                    lastThen != thenExpr.Type && lastElse != elseExpr.Type);

            if (convertAllTo == null)
            {
                throw new ArgumentException("True and False branches of condition do not have a common type to be converted to");
            }

            expr = Expression.Condition(CompilerHelpers.AsBoolean(condition),
                                        CompilerHelpers.ConvertToType(thenExpr, convertAllTo),
                                        CompilerHelpers.ConvertToType(elseExpr, convertAllTo));
            return(true);
        }
Пример #31
0
        private static ExpressionResult CompileAny(
            IExpression left,
            IExpression right,
            Action <ExpressionResult, Register, CodeGen, ILinkingInfo> actionInt,
            Action <ExpressionResult, Register, CodeGen, ILinkingInfo> actionFloat,
            Action <ExpressionResult, Register, CodeGen, ILinkingInfo> actionDouble,
            PreferredRegister target,
            ICompilationContext context
            )
        {
            var(leftReg, rightExpr, type) = PrepareBinaryExpression(
                left,
                right,
                target,
                context,
                true
                );

            if (type.IsIntegerRegisterType())
            {
                actionInt(rightExpr, leftReg, context.Generator, context.Linking);
            }
            else if (type == Constants.DoubleType)
            {
                actionDouble(rightExpr, leftReg, context.Generator, context.Linking);
            }
            else if (type == Constants.FloatType)
            {
                actionFloat(rightExpr, leftReg, context.Generator, context.Linking);
            }
            else
            {
                throw new NotImplementedException(
                          $"{nameof(BinaryOperationCompiler)}: {nameof(CompileAny)}: I do not know how to compile this type: {type}"
                          );
            }

            return(new ExpressionResult(type, leftReg));
        }
Пример #32
0
        private void CompileFunction(FunctionImplementation function, ICompilationContext context)
        {
            foreach (var parameter in function.Declaration.Parameters)
            {
                context.Symbols.DefineLocal(parameter.ParameterIdentifier.RawText, parameter.ParameterType);
            }

            if (function.Declaration.Identifier.RawText == "Main")
            {
                context.Generator.CallDereferenced4(Constants.DummyOffsetInt);
                context.Linking.FixIATEntryOffset(context.Generator.StreamPosition, "kernel32.dll", "GetProcessHeap");
                context.Generator.MovToDereferenced4(Constants.DummyOffsetInt, Register64.RAX);
                context.Linking.FixDataOffset(context.Generator.StreamPosition, Constants.HeapHandleIdentifier);
            }

            context.CompileStatement(function.Body.StatementAsBlock());

            context.Generator.InsertCode(context.Linking, 0, gen => context.Storage.CreatePrologue(gen, function.Declaration));
            context.Linking.ResolveFunctionEpilogueFixes(function.Declaration.Identifier.RawText, context.Generator.StreamPosition);
            context.Storage.CreateEpilogue(context.Generator);
            context.Generator.Ret();
        }
Пример #33
0
 public ExpressionResult Compile(UnaryOperatorExpression expression, PreferredRegister target, ICompilationContext context)
 {
     return(expression.Operator.Operator.Kind switch
     {
         TokenKind.Minus => CompileMinus(expression, target, context),
         TokenKind.AddressOf => CompileAddressOf(expression, target, context),
         TokenKind.Not => CompileNot(expression, target, context),
         TokenKind.Pointer => CompileDereference(expression, target, context),
         _ => throw new NotImplementedException(
             $"{nameof(UnaryOperationCompiler)}: I do not know how to compile {expression.Operator.Operator}"
             )
     });
Пример #34
0
		void IAspViewEngineTestAccess.SetCompilationContext(ICompilationContext context)
		{
			compilationContext = context;
		}
Пример #35
0
		public OnlineCompiler(ICodeProviderAdapterFactory codeProviderAdapterFactory, IPreProcessor preProcessor, ICompilationContext context, AspViewCompilerOptions options) : base(codeProviderAdapterFactory, preProcessor, context, options)
		{
			parameters.GenerateInMemory = true;
		}
Пример #36
0
		public void Initialize(ICompilationContext context, AspViewEngineOptions newOptions)
		{
			options = newOptions;
			compilationContext = context;
			Initialize();
		}