Browse Source

Support `using` on intermediate soa field value from a for-in statement

gingerBill 4 years ago
parent
commit
5faf859a56
2 changed files with 17 additions and 3 deletions
  1. 4 1
      src/check_stmt.cpp
  2. 13 2
      src/llvm_backend.cpp

+ 4 - 1
src/check_stmt.cpp

@@ -558,8 +558,11 @@ bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, Ast *expr, b
 		bool is_ptr = is_type_pointer(e->type);
 		bool is_ptr = is_type_pointer(e->type);
 		Type *t = base_type(type_deref(e->type));
 		Type *t = base_type(type_deref(e->type));
 		if (t->kind == Type_Struct) {
 		if (t->kind == Type_Struct) {
-			// TODO(bill): Make it work for unions too
 			Scope *found = scope_of_node(t->Struct.node);
 			Scope *found = scope_of_node(t->Struct.node);
+			if (found == nullptr) {
+				found = t->Struct.scope;
+			}
+			GB_ASSERT(found != nullptr);
 			for_array(i, found->elements.entries) {
 			for_array(i, found->elements.entries) {
 				Entity *f = found->elements.entries[i].value;
 				Entity *f = found->elements.entries[i].value;
 				if (f->kind == Entity_Variable) {
 				if (f->kind == Entity_Variable) {

+ 13 - 2
src/llvm_backend.cpp

@@ -162,6 +162,11 @@ lbValue lb_addr_get_ptr(lbProcedure *p, lbAddr const &addr) {
 		return final_ptr;
 		return final_ptr;
 	}
 	}
 
 
+	case lbAddr_SoaVariable: {
+		// TODO(bill): FIX THIS HACK
+		return lb_address_from_load(p, lb_addr_load(p, addr));
+	}
+
 	case lbAddr_Context:
 	case lbAddr_Context:
 		GB_PANIC("lbAddr_Context should be handled elsewhere");
 		GB_PANIC("lbAddr_Context should be handled elsewhere");
 	}
 	}
@@ -10780,15 +10785,21 @@ lbValue lb_get_using_variable(lbProcedure *p, Entity *e) {
 	Selection sel = lookup_field(parent->type, name, false);
 	Selection sel = lookup_field(parent->type, name, false);
 	GB_ASSERT(sel.entity != nullptr);
 	GB_ASSERT(sel.entity != nullptr);
 	lbValue *pv = map_get(&p->module->values, hash_entity(parent));
 	lbValue *pv = map_get(&p->module->values, hash_entity(parent));
+
 	lbValue v = {};
 	lbValue v = {};
-	if (pv != nullptr) {
+
+	if (pv == nullptr && parent->flags & EntityFlag_SoaPtrField) {
+		// NOTE(bill): using SOA value (probably from for-in statement)
+		lbAddr parent_addr = lb_get_soa_variable_addr(p, parent);
+		v = lb_addr_get_ptr(p, parent_addr);
+	} else if (pv != nullptr) {
 		v = *pv;
 		v = *pv;
 	} else {
 	} else {
 		GB_ASSERT_MSG(e->using_expr != nullptr, "%.*s", LIT(name));
 		GB_ASSERT_MSG(e->using_expr != nullptr, "%.*s", LIT(name));
 		v = lb_build_addr_ptr(p, e->using_expr);
 		v = lb_build_addr_ptr(p, e->using_expr);
 	}
 	}
 	GB_ASSERT(v.value != nullptr);
 	GB_ASSERT(v.value != nullptr);
-	GB_ASSERT(parent->type == type_deref(v.type));
+	GB_ASSERT_MSG(parent->type == type_deref(v.type), "%s %s", type_to_string(parent->type), type_to_string(v.type));
 	lbValue ptr = lb_emit_deep_field_gep(p, v, sel);
 	lbValue ptr = lb_emit_deep_field_gep(p, v, sel);
 	lb_add_debug_local_variable(p, ptr.value, e->type, e->token);
 	lb_add_debug_local_variable(p, ptr.value, e->type, e->token);
 	return ptr;
 	return ptr;