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

View File

@@ -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;

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

View File

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

View File

@@ -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;

View File

@@ -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<Ast *> 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

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

View File

@@ -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;