Also allow #no_bounds_check on an expression #499

This commit is contained in:
gingerBill
2019-12-15 11:41:21 +00:00
parent 58d4d424c6
commit 4ba579bc25
7 changed files with 105 additions and 56 deletions
+19 -1
View File
@@ -3052,7 +3052,7 @@ bool check_index_value(CheckerContext *c, bool open_range, Ast *index_value, i64
} }
if (operand.mode == Addressing_Constant && 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; BigInt i = exact_value_to_integer(operand.value).value_integer;
if (i.neg) { if (i.neg) {
gbString expr_str = expr_to_string(operand.expr); 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) { 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; ExprKind kind = Expr_Stmt;
o->mode = Addressing_Invalid; o->mode = Addressing_Invalid;
+12 -13
View File
@@ -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_internal(CheckerContext *ctx, Ast *node, u32 flags);
void check_stmt(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) { if (node->state_flags != 0) {
u32 in = node->stmt_state_flags; u32 in = node->state_flags;
u32 out = ctx->stmt_state_flags; u32 out = ctx->state_flags;
if (in & StmtStateFlag_no_bounds_check) { if (in & StateFlag_no_bounds_check) {
out |= StmtStateFlag_no_bounds_check; out |= StateFlag_no_bounds_check;
out &= ~StmtStateFlag_bounds_check; out &= ~StateFlag_bounds_check;
} else { } else if (in & StateFlag_bounds_check) {
// if (in & StmtStateFlag_bounds_check) { out |= StateFlag_bounds_check;
out |= StmtStateFlag_bounds_check; out &= ~StateFlag_no_bounds_check;
out &= ~StmtStateFlag_no_bounds_check;
} }
ctx->stmt_state_flags = out; ctx->state_flags = out;
} }
check_stmt_internal(ctx, node, flags); check_stmt_internal(ctx, node, flags);
ctx->stmt_state_flags = prev_stmt_state_flags; ctx->state_flags = prev_state_flags;
} }
+5 -5
View File
@@ -332,7 +332,7 @@ void check_open_scope(CheckerContext *c, Ast *node) {
break; break;
} }
c->scope = scope; c->scope = scope;
c->stmt_state_flags |= StmtStateFlag_bounds_check; c->state_flags |= StateFlag_bounds_check;
} }
void check_close_scope(CheckerContext *c) { 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; bool no_bounds_check = (pi.tags & ProcTag_no_bounds_check) != 0;
if (bounds_check) { if (bounds_check) {
ctx.stmt_state_flags |= StmtStateFlag_bounds_check; ctx.state_flags |= StateFlag_bounds_check;
ctx.stmt_state_flags &= ~StmtStateFlag_no_bounds_check; ctx.state_flags &= ~StateFlag_no_bounds_check;
} else if (no_bounds_check) { } else if (no_bounds_check) {
ctx.stmt_state_flags |= StmtStateFlag_no_bounds_check; ctx.state_flags |= StateFlag_no_bounds_check;
ctx.stmt_state_flags &= ~StmtStateFlag_bounds_check; ctx.state_flags &= ~StateFlag_bounds_check;
} }
check_proc_body(&ctx, pi.token, pi.decl, pi.type, pi.body); check_proc_body(&ctx, pi.token, pi.decl, pi.type, pi.body);
+1 -1
View File
@@ -265,7 +265,7 @@ struct CheckerContext {
Scope * scope; Scope * scope;
DeclInfo * decl; DeclInfo * decl;
u32 stmt_state_flags; u32 state_flags;
bool in_defer; // TODO(bill): Actually handle correctly bool in_defer; // TODO(bill): Actually handle correctly
Type * type_hint; Type * type_hint;
+44 -26
View File
@@ -12,7 +12,7 @@ struct irModule {
gbAllocator tmp_allocator; gbAllocator tmp_allocator;
bool generate_debug_info; bool generate_debug_info;
u64 stmt_state_flags; u64 state_flags;
// String source_filename; // String source_filename;
String layout; String layout;
@@ -5968,7 +5968,7 @@ void ir_emit_bounds_check(irProcedure *proc, Token token, irValue *index, irValu
if (build_context.no_bounds_check) { if (build_context.no_bounds_check) {
return; return;
} }
if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { if ((proc->module->state_flags & StateFlag_no_bounds_check) != 0) {
return; return;
} }
@@ -5995,7 +5995,7 @@ void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, ir
if (build_context.no_bounds_check) { if (build_context.no_bounds_check) {
return; return;
} }
if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { if ((proc->module->state_flags & StateFlag_no_bounds_check) != 0) {
return; return;
} }
@@ -6034,7 +6034,7 @@ void ir_emit_dynamic_array_bounds_check(irProcedure *proc, Token token, irValue
if (build_context.no_bounds_check) { if (build_context.no_bounds_check) {
return; return;
} }
if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { if ((proc->module->state_flags & StateFlag_no_bounds_check) != 0) {
return; 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_internal(irProcedure *proc, Ast *expr);
irValue *ir_build_expr(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); irValue *v = ir_build_expr_internal(proc, expr);
return v; return v;
} }
@@ -8857,28 +8875,28 @@ void ir_build_stmt_list(irProcedure *proc, Array<Ast *> stmts) {
void ir_build_stmt_internal(irProcedure *proc, Ast *node); void ir_build_stmt_internal(irProcedure *proc, Ast *node);
void ir_build_stmt(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) { if (node->state_flags != 0) {
u64 in = node->stmt_state_flags; u64 in = node->state_flags;
u64 out = proc->module->stmt_state_flags; u64 out = proc->module->state_flags;
if (in & StmtStateFlag_bounds_check) { if (in & StateFlag_bounds_check) {
out |= StmtStateFlag_bounds_check; out |= StateFlag_bounds_check;
out &= ~StmtStateFlag_no_bounds_check; out &= ~StateFlag_no_bounds_check;
} else if (in & StmtStateFlag_no_bounds_check) { } else if (in & StateFlag_no_bounds_check) {
out |= StmtStateFlag_no_bounds_check; out |= StateFlag_no_bounds_check;
out &= ~StmtStateFlag_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_push_debug_location(proc->module, node, proc->debug_scope);
ir_build_stmt_internal(proc, node); ir_build_stmt_internal(proc, node);
ir_pop_debug_location(proc->module); ir_pop_debug_location(proc->module);
proc->module->stmt_state_flags = prev_stmt_state_flags;
} }
void ir_build_when_stmt(irProcedure *proc, AstWhenStmt *ws) { void ir_build_when_stmt(irProcedure *proc, AstWhenStmt *ws) {
@@ -10483,19 +10501,19 @@ void ir_build_proc(irValue *value, irProcedure *parent) {
proc->parent = parent; proc->parent = parent;
if (proc->body != nullptr) { 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) { if (proc->tags != 0) {
u64 in = proc->tags; u64 in = proc->tags;
u64 out = proc->module->stmt_state_flags; u64 out = proc->module->state_flags;
if (in & ProcTag_bounds_check) { if (in & ProcTag_bounds_check) {
out |= StmtStateFlag_bounds_check; out |= StateFlag_bounds_check;
out &= ~StmtStateFlag_no_bounds_check; out &= ~StateFlag_no_bounds_check;
} else if (in & ProcTag_no_bounds_check) { } else if (in & ProcTag_no_bounds_check) {
out |= StmtStateFlag_no_bounds_check; out |= StateFlag_no_bounds_check;
out &= ~StmtStateFlag_bounds_check; out &= ~StateFlag_bounds_check;
} }
proc->module->stmt_state_flags = out; proc->module->state_flags = out;
} }
ir_begin_procedure_body(proc); ir_begin_procedure_body(proc);
@@ -10503,7 +10521,7 @@ void ir_build_proc(irValue *value, irProcedure *parent) {
ir_build_stmt(proc, proc->body); ir_build_stmt(proc, proc->body);
ir_end_procedure_body(proc); 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(). // 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()); map_init(&m->constant_value_to_global, heap_allocator());
// Default states // Default states
m->stmt_state_flags = 0; m->state_flags = 0;
m->stmt_state_flags |= StmtStateFlag_bounds_check; m->state_flags |= StateFlag_bounds_check;
{ {
// Add type info data // Add type info data
+19 -5
View File
@@ -1727,7 +1727,7 @@ Ast *parse_operand(AstFile *f, bool lhs) {
syntax_error(operand, "#no_deferred can only be applied to procedure calls"); syntax_error(operand, "#no_deferred can only be applied to procedure calls");
operand = ast_bad_expr(f, token, f->curr_token); 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") { } */ else if (name.string == "file") {
return ast_basic_directive(f, token, name.string); return ast_basic_directive(f, token, name.string);
} else if (name.string == "line") { 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; break;
} }
return original_type; 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 { } else {
operand = ast_tag_expr(f, token, name, parse_expr(f, false)); operand = ast_tag_expr(f, token, name, parse_expr(f, false));
} }
@@ -4025,15 +4039,15 @@ Ast *parse_stmt(AstFile *f) {
if (tag == "bounds_check") { if (tag == "bounds_check") {
s = parse_stmt(f); s = parse_stmt(f);
s->stmt_state_flags |= StmtStateFlag_bounds_check; s->state_flags |= StateFlag_bounds_check;
if ((s->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { if ((s->state_flags & StateFlag_no_bounds_check) != 0) {
syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together"); syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together");
} }
return s; return s;
} else if (tag == "no_bounds_check") { } else if (tag == "no_bounds_check") {
s = parse_stmt(f); s = parse_stmt(f);
s->stmt_state_flags |= StmtStateFlag_no_bounds_check; s->state_flags |= StateFlag_no_bounds_check;
if ((s->stmt_state_flags & StmtStateFlag_bounds_check) != 0) { if ((s->state_flags & StateFlag_bounds_check) != 0) {
syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together"); syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together");
} }
return s; return s;
+5 -5
View File
@@ -184,11 +184,11 @@ enum ProcCallingConvention {
ProcCC_ForeignBlockDefault = -1, ProcCC_ForeignBlockDefault = -1,
}; };
enum StmtStateFlag { enum StateFlag {
StmtStateFlag_bounds_check = 1<<0, StateFlag_bounds_check = 1<<0,
StmtStateFlag_no_bounds_check = 1<<1, StateFlag_no_bounds_check = 1<<1,
StmtStateFlag_no_deferred = 1<<5, StateFlag_no_deferred = 1<<5,
}; };
enum ViralStateFlag { enum ViralStateFlag {
@@ -573,7 +573,7 @@ isize const ast_variant_sizes[] = {
struct Ast { struct Ast {
AstKind kind; AstKind kind;
u32 stmt_state_flags; u32 state_flags;
u32 viral_state_flags; u32 viral_state_flags;
bool been_handled; bool been_handled;
AstFile * file; AstFile * file;