From 4ba579bc25ab2bbde370231d090588c237552c76 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 15 Dec 2019 11:41:21 +0000 Subject: [PATCH] Also allow #no_bounds_check on an expression #499 --- src/check_expr.cpp | 20 ++++++++++++- src/check_stmt.cpp | 25 ++++++++--------- src/checker.cpp | 10 +++---- src/checker.hpp | 2 +- src/ir.cpp | 70 +++++++++++++++++++++++++++++----------------- src/parser.cpp | 24 ++++++++++++---- src/parser.hpp | 10 +++---- 7 files changed, 105 insertions(+), 56 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 6e6db24d1..0ee604283 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3052,7 +3052,7 @@ bool check_index_value(CheckerContext *c, bool open_range, Ast *index_value, i64 } if (operand.mode == Addressing_Constant && - (c->stmt_state_flags & StmtStateFlag_no_bounds_check) == 0) { + (c->state_flags & StateFlag_no_bounds_check) == 0) { BigInt i = exact_value_to_integer(operand.value).value_integer; if (i.neg) { gbString expr_str = expr_to_string(operand.expr); @@ -6974,6 +6974,24 @@ bool check_range(CheckerContext *c, Ast *node, Operand *x, Operand *y, ExactValu ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { + u32 prev_state_flags = c->state_flags; + defer (c->state_flags = prev_state_flags); + if (node->state_flags != 0) { + u32 in = node->state_flags; + u32 out = c->state_flags; + + if (in & StateFlag_no_bounds_check) { + out |= StateFlag_no_bounds_check; + out &= ~StateFlag_bounds_check; + } else if (in & StateFlag_bounds_check) { + out |= StateFlag_bounds_check; + out &= ~StateFlag_no_bounds_check; + } + + c->state_flags = out; + } + + ExprKind kind = Expr_Stmt; o->mode = Addressing_Invalid; diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index a2c158638..7d5648018 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -335,27 +335,26 @@ Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs) void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags); void check_stmt(CheckerContext *ctx, Ast *node, u32 flags) { - u32 prev_stmt_state_flags = ctx->stmt_state_flags; + u32 prev_state_flags = ctx->state_flags; - if (node->stmt_state_flags != 0) { - u32 in = node->stmt_state_flags; - u32 out = ctx->stmt_state_flags; + if (node->state_flags != 0) { + u32 in = node->state_flags; + u32 out = ctx->state_flags; - if (in & StmtStateFlag_no_bounds_check) { - out |= StmtStateFlag_no_bounds_check; - out &= ~StmtStateFlag_bounds_check; - } else { - // if (in & StmtStateFlag_bounds_check) { - out |= StmtStateFlag_bounds_check; - out &= ~StmtStateFlag_no_bounds_check; + if (in & StateFlag_no_bounds_check) { + out |= StateFlag_no_bounds_check; + out &= ~StateFlag_bounds_check; + } else if (in & StateFlag_bounds_check) { + out |= StateFlag_bounds_check; + out &= ~StateFlag_no_bounds_check; } - ctx->stmt_state_flags = out; + ctx->state_flags = out; } check_stmt_internal(ctx, node, flags); - ctx->stmt_state_flags = prev_stmt_state_flags; + ctx->state_flags = prev_state_flags; } diff --git a/src/checker.cpp b/src/checker.cpp index cce2aac35..675857cf4 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -332,7 +332,7 @@ void check_open_scope(CheckerContext *c, Ast *node) { break; } c->scope = scope; - c->stmt_state_flags |= StmtStateFlag_bounds_check; + c->state_flags |= StateFlag_bounds_check; } void check_close_scope(CheckerContext *c) { @@ -3766,11 +3766,11 @@ void check_proc_info(Checker *c, ProcInfo pi) { bool no_bounds_check = (pi.tags & ProcTag_no_bounds_check) != 0; if (bounds_check) { - ctx.stmt_state_flags |= StmtStateFlag_bounds_check; - ctx.stmt_state_flags &= ~StmtStateFlag_no_bounds_check; + ctx.state_flags |= StateFlag_bounds_check; + ctx.state_flags &= ~StateFlag_no_bounds_check; } else if (no_bounds_check) { - ctx.stmt_state_flags |= StmtStateFlag_no_bounds_check; - ctx.stmt_state_flags &= ~StmtStateFlag_bounds_check; + ctx.state_flags |= StateFlag_no_bounds_check; + ctx.state_flags &= ~StateFlag_bounds_check; } check_proc_body(&ctx, pi.token, pi.decl, pi.type, pi.body); diff --git a/src/checker.hpp b/src/checker.hpp index c5d6f71cd..da206a867 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -265,7 +265,7 @@ struct CheckerContext { Scope * scope; DeclInfo * decl; - u32 stmt_state_flags; + u32 state_flags; bool in_defer; // TODO(bill): Actually handle correctly Type * type_hint; diff --git a/src/ir.cpp b/src/ir.cpp index 19fa94485..790ac5f67 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -12,7 +12,7 @@ struct irModule { gbAllocator tmp_allocator; bool generate_debug_info; - u64 stmt_state_flags; + u64 state_flags; // String source_filename; String layout; @@ -5968,7 +5968,7 @@ void ir_emit_bounds_check(irProcedure *proc, Token token, irValue *index, irValu if (build_context.no_bounds_check) { return; } - if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { + if ((proc->module->state_flags & StateFlag_no_bounds_check) != 0) { return; } @@ -5995,7 +5995,7 @@ void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, ir if (build_context.no_bounds_check) { return; } - if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { + if ((proc->module->state_flags & StateFlag_no_bounds_check) != 0) { return; } @@ -6034,7 +6034,7 @@ void ir_emit_dynamic_array_bounds_check(irProcedure *proc, Token token, irValue if (build_context.no_bounds_check) { return; } - if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { + if ((proc->module->state_flags & StateFlag_no_bounds_check) != 0) { return; } @@ -6905,6 +6905,24 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr); irValue *ir_build_expr(irProcedure *proc, Ast *expr) { + u64 prev_state_flags = proc->module->state_flags; + defer (proc->module->state_flags = prev_state_flags); + + if (expr->state_flags != 0) { + u64 in = expr->state_flags; + u64 out = proc->module->state_flags; + + if (in & StateFlag_bounds_check) { + out |= StateFlag_bounds_check; + out &= ~StateFlag_no_bounds_check; + } else if (in & StateFlag_no_bounds_check) { + out |= StateFlag_no_bounds_check; + out &= ~StateFlag_bounds_check; + } + + proc->module->state_flags = out; + } + irValue *v = ir_build_expr_internal(proc, expr); return v; } @@ -8857,28 +8875,28 @@ void ir_build_stmt_list(irProcedure *proc, Array stmts) { void ir_build_stmt_internal(irProcedure *proc, Ast *node); void ir_build_stmt(irProcedure *proc, Ast *node) { - u64 prev_stmt_state_flags = proc->module->stmt_state_flags; + u64 prev_state_flags = proc->module->state_flags; + defer (proc->module->state_flags = prev_state_flags); - if (node->stmt_state_flags != 0) { - u64 in = node->stmt_state_flags; - u64 out = proc->module->stmt_state_flags; + if (node->state_flags != 0) { + u64 in = node->state_flags; + u64 out = proc->module->state_flags; - if (in & StmtStateFlag_bounds_check) { - out |= StmtStateFlag_bounds_check; - out &= ~StmtStateFlag_no_bounds_check; - } else if (in & StmtStateFlag_no_bounds_check) { - out |= StmtStateFlag_no_bounds_check; - out &= ~StmtStateFlag_bounds_check; + if (in & StateFlag_bounds_check) { + out |= StateFlag_bounds_check; + out &= ~StateFlag_no_bounds_check; + } else if (in & StateFlag_no_bounds_check) { + out |= StateFlag_no_bounds_check; + out &= ~StateFlag_bounds_check; } - proc->module->stmt_state_flags = out; + proc->module->state_flags = out; } ir_push_debug_location(proc->module, node, proc->debug_scope); ir_build_stmt_internal(proc, node); ir_pop_debug_location(proc->module); - proc->module->stmt_state_flags = prev_stmt_state_flags; } void ir_build_when_stmt(irProcedure *proc, AstWhenStmt *ws) { @@ -10483,19 +10501,19 @@ void ir_build_proc(irValue *value, irProcedure *parent) { proc->parent = parent; if (proc->body != nullptr) { - u64 prev_stmt_state_flags = proc->module->stmt_state_flags; + u64 prev_state_flags = proc->module->state_flags; if (proc->tags != 0) { u64 in = proc->tags; - u64 out = proc->module->stmt_state_flags; + u64 out = proc->module->state_flags; if (in & ProcTag_bounds_check) { - out |= StmtStateFlag_bounds_check; - out &= ~StmtStateFlag_no_bounds_check; + out |= StateFlag_bounds_check; + out &= ~StateFlag_no_bounds_check; } else if (in & ProcTag_no_bounds_check) { - out |= StmtStateFlag_no_bounds_check; - out &= ~StmtStateFlag_bounds_check; + out |= StateFlag_no_bounds_check; + out &= ~StateFlag_bounds_check; } - proc->module->stmt_state_flags = out; + proc->module->state_flags = out; } ir_begin_procedure_body(proc); @@ -10503,7 +10521,7 @@ void ir_build_proc(irValue *value, irProcedure *parent) { ir_build_stmt(proc, proc->body); ir_end_procedure_body(proc); - proc->module->stmt_state_flags = prev_stmt_state_flags; + proc->module->state_flags = prev_state_flags; } // NOTE(lachsinc): For now we pop the debug location inside ir_end_procedure_body(). @@ -10592,8 +10610,8 @@ void ir_init_module(irModule *m, Checker *c) { map_init(&m->constant_value_to_global, heap_allocator()); // Default states - m->stmt_state_flags = 0; - m->stmt_state_flags |= StmtStateFlag_bounds_check; + m->state_flags = 0; + m->state_flags |= StateFlag_bounds_check; { // Add type info data diff --git a/src/parser.cpp b/src/parser.cpp index 65b20ab83..fa321937e 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1727,7 +1727,7 @@ Ast *parse_operand(AstFile *f, bool lhs) { syntax_error(operand, "#no_deferred can only be applied to procedure calls"); operand = ast_bad_expr(f, token, f->curr_token); } - operand->stmt_state_flags |= StmtStateFlag_no_deferred; + operand->state_flags |= StateFlag_no_deferred; } */ else if (name.string == "file") { return ast_basic_directive(f, token, name.string); } else if (name.string == "line") { return ast_basic_directive(f, token, name.string); @@ -1757,6 +1757,20 @@ Ast *parse_operand(AstFile *f, bool lhs) { break; } return original_type; + } else if (name.string == "bounds_check") { + Ast *operand = parse_expr(f, lhs); + operand->state_flags |= StateFlag_bounds_check; + if ((operand->state_flags & StateFlag_no_bounds_check) != 0) { + syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together"); + } + return operand; + } else if (name.string == "no_bounds_check") { + Ast *operand = parse_expr(f, lhs); + operand->state_flags |= StateFlag_no_bounds_check; + if ((operand->state_flags & StateFlag_bounds_check) != 0) { + syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together"); + } + return operand; } else { operand = ast_tag_expr(f, token, name, parse_expr(f, false)); } @@ -4025,15 +4039,15 @@ Ast *parse_stmt(AstFile *f) { if (tag == "bounds_check") { s = parse_stmt(f); - s->stmt_state_flags |= StmtStateFlag_bounds_check; - if ((s->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { + s->state_flags |= StateFlag_bounds_check; + if ((s->state_flags & StateFlag_no_bounds_check) != 0) { syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together"); } return s; } else if (tag == "no_bounds_check") { s = parse_stmt(f); - s->stmt_state_flags |= StmtStateFlag_no_bounds_check; - if ((s->stmt_state_flags & StmtStateFlag_bounds_check) != 0) { + s->state_flags |= StateFlag_no_bounds_check; + if ((s->state_flags & StateFlag_bounds_check) != 0) { syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together"); } return s; diff --git a/src/parser.hpp b/src/parser.hpp index c8f1a683c..7101e0247 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -184,11 +184,11 @@ enum ProcCallingConvention { ProcCC_ForeignBlockDefault = -1, }; -enum StmtStateFlag { - StmtStateFlag_bounds_check = 1<<0, - StmtStateFlag_no_bounds_check = 1<<1, +enum StateFlag { + StateFlag_bounds_check = 1<<0, + StateFlag_no_bounds_check = 1<<1, - StmtStateFlag_no_deferred = 1<<5, + StateFlag_no_deferred = 1<<5, }; enum ViralStateFlag { @@ -573,7 +573,7 @@ isize const ast_variant_sizes[] = { struct Ast { AstKind kind; - u32 stmt_state_flags; + u32 state_flags; u32 viral_state_flags; bool been_handled; AstFile * file;