2
0
Эх сурвалжийг харах

Also allow #no_bounds_check on an expression #499

gingerBill 5 жил өмнө
parent
commit
4ba579bc25
7 өөрчлөгдсөн 105 нэмэгдсэн , 56 устгасан
  1. 19 1
      src/check_expr.cpp
  2. 12 13
      src/check_stmt.cpp
  3. 5 5
      src/checker.cpp
  4. 1 1
      src/checker.hpp
  5. 44 26
      src/ir.cpp
  6. 19 5
      src/parser.cpp
  7. 5 5
      src/parser.hpp

+ 19 - 1
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;

+ 12 - 13
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;
 }
 
 

+ 5 - 5
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);

+ 1 - 1
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;
 

+ 44 - 26
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<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

+ 19 - 5
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;

+ 5 - 5
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;