Browse Source

Add extra checks for multiple assignments when emitting stores

gingerBill 2 years ago
parent
commit
ccf4b48865
3 changed files with 22 additions and 5 deletions
  1. 1 0
      src/llvm_backend.hpp
  2. 7 5
      src/llvm_backend_general.cpp
  3. 14 0
      src/llvm_backend_stmt.cpp

+ 1 - 0
src/llvm_backend.hpp

@@ -324,6 +324,7 @@ struct lbProcedure {
 	lbBlock *        curr_block;
 	lbBlock *        curr_block;
 	lbTargetList *   target_list;
 	lbTargetList *   target_list;
 	PtrMap<Entity *, lbValue> direct_parameters;
 	PtrMap<Entity *, lbValue> direct_parameters;
+	bool             in_multi_assignment;
 
 
 	Ast *curr_stmt;
 	Ast *curr_stmt;
 
 

+ 7 - 5
src/llvm_backend_general.cpp

@@ -937,7 +937,7 @@ gb_internal void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) {
 
 
 	enum {MAX_STORE_SIZE = 64};
 	enum {MAX_STORE_SIZE = 64};
 
 
-	if (lb_sizeof(LLVMTypeOf(value.value)) > MAX_STORE_SIZE) {
+	if (!p->in_multi_assignment && lb_sizeof(LLVMTypeOf(value.value)) > MAX_STORE_SIZE) {
 		if (LLVMIsALoadInst(value.value)) {
 		if (LLVMIsALoadInst(value.value)) {
 			LLVMValueRef dst_ptr = ptr.value;
 			LLVMValueRef dst_ptr = ptr.value;
 			LLVMValueRef src_ptr_original = LLVMGetOperand(value.value, 0);
 			LLVMValueRef src_ptr_original = LLVMGetOperand(value.value, 0);
@@ -964,15 +964,16 @@ gb_internal void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) {
 		}
 		}
 	}
 	}
 
 
+	LLVMValueRef instr = nullptr;
 	if (lb_is_type_proc_recursive(a)) {
 	if (lb_is_type_proc_recursive(a)) {
 		// NOTE(bill, 2020-11-11): Because of certain LLVM rules, a procedure value may be
 		// NOTE(bill, 2020-11-11): Because of certain LLVM rules, a procedure value may be
 		// stored as regular pointer with no procedure information
 		// stored as regular pointer with no procedure information
 
 
  		LLVMTypeRef rawptr_type = lb_type(p->module, t_rawptr);
  		LLVMTypeRef rawptr_type = lb_type(p->module, t_rawptr);
  		LLVMTypeRef rawptr_ptr_type = LLVMPointerType(rawptr_type, 0);
  		LLVMTypeRef rawptr_ptr_type = LLVMPointerType(rawptr_type, 0);
-		LLVMBuildStore(p->builder,
-		               LLVMBuildPointerCast(p->builder, value.value, rawptr_type, ""),
-		               LLVMBuildPointerCast(p->builder, ptr.value, rawptr_ptr_type, ""));
+		instr = LLVMBuildStore(p->builder,
+		                       LLVMBuildPointerCast(p->builder, value.value, rawptr_type, ""),
+		                       LLVMBuildPointerCast(p->builder, ptr.value, rawptr_ptr_type, ""));
 	} else {
 	} else {
 		Type *ca = core_type(a);
 		Type *ca = core_type(a);
 		if (ca->kind == Type_Basic || ca->kind == Type_Proc) {
 		if (ca->kind == Type_Basic || ca->kind == Type_Proc) {
@@ -981,8 +982,9 @@ gb_internal void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) {
 			GB_ASSERT_MSG(are_types_identical(a, value.type), "%s != %s", type_to_string(a), type_to_string(value.type));
 			GB_ASSERT_MSG(are_types_identical(a, value.type), "%s != %s", type_to_string(a), type_to_string(value.type));
 		}
 		}
 
 
-		LLVMBuildStore(p->builder, value.value, ptr.value);
+		instr = LLVMBuildStore(p->builder, value.value, ptr.value);
 	}
 	}
+	LLVMSetVolatile(instr, p->in_multi_assignment);
 }
 }
 
 
 gb_internal LLVMTypeRef llvm_addr_type(lbModule *module, lbValue addr_val) {
 gb_internal LLVMTypeRef llvm_addr_type(lbModule *module, lbValue addr_val) {

+ 14 - 0
src/llvm_backend_stmt.cpp

@@ -1555,12 +1555,25 @@ gb_internal void lb_build_assignment(lbProcedure *p, Array<lbAddr> &lvals, Slice
 		lb_append_tuple_values(p, &inits, init);
 		lb_append_tuple_values(p, &inits, init);
 	}
 	}
 
 
+	bool prev_in_assignment = p->in_multi_assignment;
+
+	isize lval_count = 0;
+	for (lbAddr const &lval : lvals) {
+		if (lval.addr.value != nullptr) {
+			// check if it is not a blank identifier
+			lval_count += 1;
+		}
+	}
+	p->in_multi_assignment = lval_count > 1;
+
 	GB_ASSERT(lvals.count == inits.count);
 	GB_ASSERT(lvals.count == inits.count);
 	for_array(i, inits) {
 	for_array(i, inits) {
 		lbAddr lval = lvals[i];
 		lbAddr lval = lvals[i];
 		lbValue init = inits[i];
 		lbValue init = inits[i];
 		lb_addr_store(p, lval, init);
 		lb_addr_store(p, lval, init);
 	}
 	}
+
+	p->in_multi_assignment = prev_in_assignment;
 }
 }
 
 
 gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
 gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
@@ -2047,6 +2060,7 @@ gb_internal void lb_build_assign_stmt(lbProcedure *p, AstAssignStmt *as) {
 		lb_build_assignment(p, lvals, as->rhs);
 		lb_build_assignment(p, lvals, as->rhs);
 		return;
 		return;
 	}
 	}
+
 	GB_ASSERT(as->lhs.count == 1);
 	GB_ASSERT(as->lhs.count == 1);
 	GB_ASSERT(as->rhs.count == 1);
 	GB_ASSERT(as->rhs.count == 1);
 	// NOTE(bill): Only 1 += 1 is allowed, no tuples
 	// NOTE(bill): Only 1 += 1 is allowed, no tuples