Browse Source

LLVM C backend: Obey directives on blocks, procedures, and expressions

e.g: #no_bounds_check / #bounds_check
Tetralux 5 years ago
parent
commit
96ed948590
2 changed files with 61 additions and 1 deletions
  1. 59 1
      src/llvm_backend.cpp
  2. 2 0
      src/llvm_backend.hpp

+ 59 - 1
src/llvm_backend.cpp

@@ -149,6 +149,9 @@ void lb_emit_bounds_check(lbProcedure *p, Token token, lbValue index, lbValue le
 	if (build_context.no_bounds_check) {
 		return;
 	}
+	if ((p->module->state_flags & StateFlag_no_bounds_check) != 0) {
+		return;
+	}
 
 	index = lb_emit_conv(p, index, t_int);
 	len = lb_emit_conv(p, len, t_int);
@@ -171,6 +174,9 @@ void lb_emit_slice_bounds_check(lbProcedure *p, Token token, lbValue low, lbValu
 	if (build_context.no_bounds_check) {
 		return;
 	}
+	if ((p->module->state_flags & StateFlag_no_bounds_check) != 0) {
+		return;
+	}
 
 	lbValue file = lb_find_or_add_entity_string(p->module, token.pos.file);
 	lbValue line = lb_const_int(p->module, t_int, token.pos.line);
@@ -2294,6 +2300,19 @@ void lb_begin_procedure_body(lbProcedure *p) {
 		}
 	}
 
+	if (p->tags != 0) {
+		u64 in = p->tags;
+		u64 out = p->module->state_flags;
+		if (in & ProcTag_bounds_check) {
+			out |= StateFlag_bounds_check;
+			out &= ~StateFlag_no_bounds_check;
+		} else if (in & ProcTag_no_bounds_check) {
+			out |= StateFlag_no_bounds_check;
+			out &= ~StateFlag_bounds_check;
+		}
+		p->module->state_flags = out;
+	}
+
 	p->builder = LLVMCreateBuilder();
 
 	p->decl_block  = lb_create_block(p, "decls", true);
@@ -2457,7 +2476,7 @@ void lb_end_procedure_body(lbProcedure *p) {
 	}
 
 	p->curr_block = nullptr;
-
+	p->module->state_flags = 0;
 }
 void lb_end_procedure(lbProcedure *p) {
 	LLVMDisposeBuilder(p->builder);
@@ -3829,6 +3848,24 @@ lbValue lb_emit_logical_binary_expr(lbProcedure *p, TokenKind op, Ast *left, Ast
 
 
 void lb_build_stmt(lbProcedure *p, Ast *node) {
+	u64 prev_state_flags = p->module->state_flags;
+	defer (p->module->state_flags = prev_state_flags);
+
+	if (node->state_flags != 0) {
+		u64 in = node->state_flags;
+		u64 out = p->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;
+		}
+
+		p->module->state_flags = out;
+	}
+
 	switch (node->kind) {
 	case_ast_node(bs, EmptyStmt, node);
 	case_end;
@@ -8849,6 +8886,24 @@ lbValue lb_emit_any_cast(lbProcedure *p, lbValue value, Type *type, TokenPos pos
 lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
 	lbModule *m = p->module;
 
+	u64 prev_state_flags = p->module->state_flags;
+	defer (p->module->state_flags = prev_state_flags);
+
+	if (expr->state_flags != 0) {
+		u64 in = expr->state_flags;
+		u64 out = p->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;
+		}
+
+		p->module->state_flags = out;
+	}
+
 	expr = unparen_expr(expr);
 
 	TypeAndValue tv = type_and_value_of_expr(expr);
@@ -10538,6 +10593,9 @@ void lb_init_module(lbModule *m, Checker *c) {
 	m->mod = LLVMModuleCreateWithNameInContext("odin_module", m->ctx);
 	m->debug_builder = LLVMCreateDIBuilder(m->mod);
 
+	m->state_flags = 0;
+	m->state_flags |= StateFlag_bounds_check;
+
 	gb_mutex_init(&m->mutex);
 	gbAllocator a = heap_allocator();
 	map_init(&m->types, a);

+ 2 - 0
src/llvm_backend.hpp

@@ -64,6 +64,8 @@ struct lbModule {
 	LLVMModuleRef mod;
 	LLVMContextRef ctx;
 
+	u64 state_flags;
+
 	CheckerInfo *info;
 
 	gbMutex mutex;