示例#1
0
        public int Finish()
        {
            // Assuming current block is last block
            CurrentBlock.PositionBuilderAtEnd(Builder);
            if (!CurrentBlock.HasTerminator())
            {
                if (Self.ReturnType != InstanceTypes.Void)
                {
                    // TODO: fix your sh*tty error system (and error generator too)
                    // ALSO: possibly add (and improve) super konsole lib
                    NamespaceContext.Context.AddError(new GamaError("Function did not return a value, did you meant to use void return type? Expected {0} got nothing.", Self.ReturnType.Name));
                    return(-1);
                }
                // If self is void, no need to worry, just BuildRetVoid()
                Builder.BuildRetVoid();
            }

            Builder.Dispose();

            // Run optimizations of self
            // new Optimizers.AllocToEntry().Visit(this);
            // new Optimizers.ControlFlowEliminator().Visit(this);
            // new Optimizers.DeadBlockEliminator().Visit(this);

            return(0);
        }
示例#2
0
        public override bool VisitStmtVarDefBase([NotNull] GamaParser.StmtVarDefBaseContext context)
        {
            var name = context.Symbol().GetText();
            var val  = Top.FindValue(name);

            // Duplicate variable definition (parent frames can have same variable, it will be overriden in current frame)
            if (val != null)
            {
                NamespaceContext.Context.AddError(new ErrorDuplicateVariable(context));
                return(false);
            }
            val = VisitExpression(context.expr());
            if (val == null)
            {
                return(false);
            }

            /* LLVM */
            CurrentBlock.PositionBuilderAtEnd(Builder);
            var alloc = Builder.BuildAlloca(val.Type.UnderlyingType, name);

            Builder.BuildStore(val.Value, alloc);

            Top.AddValue(name, new GamaValueRef(val.Type, alloc, true));

            return(true);
        }
示例#3
0
        public override bool VisitStmtReturnValue([NotNull] GamaParser.StmtReturnValueContext context)
        {
            if (Self.ReturnType == InstanceTypes.Void)
            {
                NamespaceContext.Context.AddError(new ErrorVoidReturnsValue(context));
                return(false);
            }

            var val = VisitExpression(Self.ReturnType, context.expr());

            if (val == null)
            {
                return(false);
            }

            if (Self.ReturnType != val.Type)
            {
                NamespaceContext.Context.AddError(new ErrorTypeMismatch(context.expr()));
                return(false);
            }

            /* LLVM */
            CurrentBlock.PositionBuilderAtEnd(Builder);
            Builder.BuildRet(val.Value);

            return(true);
        }
示例#4
0
        public override bool VisitStmtAssign([NotNull] GamaParser.StmtAssignContext context)
        {
            ExpressionCompiler.PushLoad(false);
            var lhs = VisitExpression(context.expr(0));

            ExpressionCompiler.PopLoad();

            if (lhs == null)
            {
                return(false);
            }

            if (!lhs.IsModifiableLValue)
            {
                NamespaceContext.Context.AddError(new ErrorAssignToNonModLValue(context.expr(0)));
                return(false);
            }

            var value = VisitExpression(lhs.Type, context.expr(1));

            if (value == null)
            {
                NamespaceContext.Context.AddError(new ErrorTypeMismatch(context.expr(1)));
                return(false);
            }

            /* LLVM */
            CurrentBlock.PositionBuilderAtEnd(Builder);
            Builder.BuildStore(value.Value, lhs.Value);
            return(true);
        }
示例#5
0
        public override bool VisitStmtWhileBase([NotNull] GamaParser.StmtWhileBaseContext context)
        {
            var wlecontrol = Self.AddBlock("while.if");
            var wleblock   = Self.AddBlock("while.loop");
            var wleend     = Self.AddBlock("while.end");

            CurrentBlock.PositionBuilderAtEnd(Builder);
            Builder.BuildBr(wlecontrol.Block);

            SetBlock(wlecontrol);
            CurrentBlock.PositionBuilderAtEnd(Builder);
            var expr = VisitExpression(context.expr());

            if (expr == null)
            {
                return(false);
            }

            if (expr.Type != InstanceTypes.Bool)
            {
                NamespaceContext.Context.AddError(new ErrorTypeMismatch(context.expr()));
                return(false);
            }
            Builder.BuildCondBr(expr.Value, wleblock.Block, wleend.Block);

            SetBlock(wleblock);
            Push();
            {
                Visit(context.block());
            }
            if (!wleblock.HasTerminator())
            {
                wleblock.PositionBuilderAtEnd(Builder);
                Builder.BuildBr(wlecontrol.Block);
            }
            if (CurrentBlock != wleblock) /* Block nesting */
            {
                CurrentBlock.PositionBuilderAtEnd(Builder);
                Builder.BuildBr(wlecontrol.Block);
            }
            Pop();
            if (wleend != CurrentBlock)
            {
                if (!CurrentBlock.HasTerminator())
                {
                    CurrentBlock.PositionBuilderAtEnd(Builder);
                    Builder.BuildBr(wleend.Block);
                }
            }
            SetBlock(wleend);

            return(true);
        }
示例#6
0
        public override bool VisitStmtReturnVoid([NotNull] GamaParser.StmtReturnVoidContext context)
        {
            if (Self.ReturnType != InstanceTypes.Void)
            {
                NamespaceContext.Context.AddError(new GamaError("Function tried to return void despite it being a {1} function", Self.ReturnType.Name));
                return(false);
            }

            /* LLVM */
            CurrentBlock.PositionBuilderAtEnd(Builder);
            Builder.BuildRetVoid();

            return(true);
        }
示例#7
0
        public override bool VisitStmtIfElseIfElse([NotNull] GamaParser.StmtIfElseIfElseContext context)
        {
            var exprctx = context.expr();

            /* lmao */
            for (int i = 0; i < exprctx.Length; i++)
            {
                var e   = exprctx[i];
                var val = VisitExpression(e);
                if (val == null)
                {
                    return(false);
                }

                if (val.Type != InstanceTypes.Bool)
                {
                    NamespaceContext.Context.AddError(new ErrorTypeMismatch(e));
                    return(false);
                }

                CurrentBlock.PositionBuilderAtEnd(Builder);

                var iftrue = Self.AddBlock("if.true");
                var ifend  = Self.AddBlock("if.end");

                Builder.BuildCondBr(val.Value, iftrue.Block, ifend.Block);

                SetBlock(iftrue);
                Push();
                {
                    Visit(context.block(i));
                }
                if (!iftrue.HasTerminator())
                {
                    iftrue.PositionBuilderAtEnd(Builder);
                    Builder.BuildBr(ifend.Block);
                }
                if (CurrentBlock != iftrue) /* Block nesting */
                {
                    CurrentBlock.PositionBuilderAtEnd(Builder);
                    Builder.BuildBr(ifend.Block);
                }
                Pop();
                SetBlock(ifend);
            }

            // TODO:

            return(true);
        }
示例#8
0
        public override bool VisitStmtVarDefNull([NotNull] GamaParser.StmtVarDefNullContext context)
        {
            var name = context.Symbol().GetText();
            var val  = Top.FindValue(name);

            if (val != null)
            {
                NamespaceContext.Context.AddError(new ErrorDuplicateVariable(context));
                return(false);
            }
            var ty = NamespaceContext.FindTypeRefGlobal(context.typeName());

            if (ty == null)
            {
                NamespaceContext.Context.AddError(new ErrorTypeNotFound(context.typeName()));
                return(false);
            }
            if (ty == InstanceTypes.Void)
            {
                NamespaceContext.Context.AddError(new ErrorVariableVoid(context.typeName()));
                return(false);
            }

            /* LLVM */
            CurrentBlock.PositionBuilderAtEnd(Builder);
            if (ty is GamaFunction) // Functionals are not allocated directly, instead a pointer is allocateds
            {
                var ptr   = new GamaPointer(ty);
                var alloc = Builder.BuildAlloca(ptr.UnderlyingType, name);
                Builder.BuildStore(LLVMValueRef.CreateConstPointerNull(ptr.UnderlyingType), alloc);

                Top.AddValue(name, new GamaValueRef(ty, alloc, true));
            }
            else
            {
                var alloc = Builder.BuildAlloca(ty.UnderlyingType, name);
                // TODO: maybe add an option to not null initialize these variable definitions
                // Possible speed boost
                Builder.BuildStore(LLVMValueRef.CreateConstNull(ty.UnderlyingType), alloc);

                Top.AddValue(name, new GamaValueRef(ty, alloc, true));
            }

            return(true);
        }
示例#9
0
        public override bool VisitStmtIfBase([NotNull] GamaParser.StmtIfBaseContext context)
        {
            var expr = VisitExpression(context.expr());

            if (expr == null)
            {
                return(false);
            }

            if (expr.Type != InstanceTypes.Bool)
            {
                NamespaceContext.Context.AddError(new ErrorTypeMismatch(context.expr()));
                return(false);
            }

            /* LLVM */
            CurrentBlock.PositionBuilderAtEnd(Builder);

            var iftrue = Self.AddBlock("if.true");
            var ifend  = Self.AddBlock("if.end");

            Builder.BuildCondBr(expr.Value, iftrue.Block, ifend.Block);

            // Compile true block
            SetBlock(iftrue);
            Push();
            {
                Visit(context.block());
            }
            if (!iftrue.HasTerminator())
            {
                iftrue.PositionBuilderAtEnd(Builder);
                Builder.BuildBr(ifend.Block);
            }
            if (CurrentBlock != iftrue) /* Block nesting */
            {
                CurrentBlock.PositionBuilderAtEnd(Builder);
                Builder.BuildBr(ifend.Block);
            }
            Pop();
            SetBlock(ifend);

            return(true);
        }
示例#10
0
        public override bool VisitStmtVarDefFull([NotNull] GamaParser.StmtVarDefFullContext context)
        {
            var name = context.Symbol().GetText();
            var val  = Top.FindValue(name);

            if (val != null)
            {
                NamespaceContext.Context.AddError(new ErrorDuplicateVariable(context));
                return(false);
            }
            var ty = NamespaceContext.FindTypeRefGlobal(context.typeName());

            if (ty == null)
            {
                NamespaceContext.Context.AddError(new ErrorTypeNotFound(context.typeName()));
                return(false);
            }
            if (ty == InstanceTypes.Void)
            {
                NamespaceContext.Context.AddError(new ErrorVariableVoid(context.typeName()));
                return(false);
            }
            val = VisitExpression(ty, context.expr());
            if (val == null)
            {
                return(false);
            }
            // If expression compiler returns a function then it's impossible for a type mismatch to happen
            // Expression compiler checks for type mismatches when evaluating function pointers
            // Alsp no need to check if 'ty' is a GamaFunction either, expressiom compiler already did that
            if (val.Type is GamaFunction valtyfn)
            {
                var tyfn = new GamaPointer(ty as GamaFunction);
                /* LLVM */
                CurrentBlock.PositionBuilderAtEnd(Builder);
                var alloc = Builder.BuildAlloca(tyfn.UnderlyingType, name);
                Builder.BuildStore(val.Value, alloc);

                Top.AddValue(name, new GamaValueRef(ty, alloc, true));
                return(true);
            }

            // If not function, there might be a mismatch. Check it and error if it mismatches
            if (val.Type != ty)
            {
                NamespaceContext.Context.AddError(new ErrorTypeMismatch(context.expr()));
                return(false);
            }

            /* LLVM */
            // One block above to avoid dumb C# error message saying 'alloc' is already defined (SOMEHOW)
            {
                CurrentBlock.PositionBuilderAtEnd(Builder);
                var alloc = Builder.BuildAlloca(ty.UnderlyingType, name);
                Builder.BuildStore(val.Value, alloc);

                Top.AddValue(name, new GamaValueRef(ty, alloc, true));
            }

            return(true);
        }