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