Browse Source

Support by-reference semantics in `for value_ref, i in &some_array` and `for key, value_ref in &some_map`

gingerBill 5 years ago
parent
commit
796331fea6
2 changed files with 28 additions and 9 deletions
  1. 24 9
      src/llvm_backend.cpp
  2. 4 0
      src/llvm_backend.hpp

+ 24 - 9
src/llvm_backend.cpp

@@ -2526,17 +2526,12 @@ void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs) {
 	}
 
 
-	lbAddr val0_addr = {};
-	lbAddr val1_addr = {};
-	if (val0_type) val0_addr = lb_build_addr(p, rs->val0);
-	if (val1_type) val1_addr = lb_build_addr(p, rs->val1);
-
 	if (is_map) {
-		if (val0_type) lb_addr_store(p, val0_addr, key);
-		if (val1_type) lb_addr_store(p, val1_addr, val);
+		if (val0_type) lb_store_range_stmt_val(p, rs->val0, key);
+		if (val1_type) lb_store_range_stmt_val(p, rs->val1, val);
 	} else {
-		if (val0_type) lb_addr_store(p, val0_addr, val);
-		if (val1_type) lb_addr_store(p, val1_addr, key);
+		if (val0_type) lb_store_range_stmt_val(p, rs->val0, val);
+		if (val1_type) lb_store_range_stmt_val(p, rs->val1, key);
 	}
 
 	lb_push_target_list(p, rs->label, done, loop, nullptr);
@@ -2835,6 +2830,26 @@ void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value) {
 	}
 }
 
+lbAddr lb_store_range_stmt_val(lbProcedure *p, Ast *stmt_val, lbValue value) {
+	Entity *e = entity_of_node(stmt_val);
+	if (e == nullptr) {
+		return {};
+	}
+
+	if ((e->flags & EntityFlag_Value) == 0) {
+		if (LLVMIsALoadInst(value.value)) {
+			lbValue ptr = lb_address_from_load_or_generate_local(p, value);
+			lb_add_entity(p->module, e, ptr);
+			return lb_addr(ptr);
+		}
+	}
+
+	// by value
+	lbAddr addr = lb_add_local(p, e->type, e, false);
+	lb_addr_store(p, addr, value);
+	return addr;
+}
+
 void lb_type_case_body(lbProcedure *p, Ast *label, Ast *clause, lbBlock *body, lbBlock *done) {
 	ast_node(cc, CaseClause, clause);
 

+ 4 - 0
src/llvm_backend.hpp

@@ -330,6 +330,10 @@ lbValue lb_gen_map_key(lbProcedure *p, lbValue key, Type *key_type);
 void    lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbAddr addr, Type *map_type, lbValue map_key, lbValue map_value);
 
 
+void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value);
+lbAddr lb_store_range_stmt_val(lbProcedure *p, Ast *stmt_val, lbValue value);
+
+
 #define LB_STARTUP_RUNTIME_PROC_NAME   "__$startup_runtime"
 #define LB_STARTUP_CONTEXT_PROC_NAME   "__$startup_context"
 #define LB_STARTUP_TYPE_INFO_PROC_NAME "__$startup_type_info"