Browse Source

Improve compound literal generation for array-like types

gingerBill 3 years ago
parent
commit
0f3562ef02
2 changed files with 1041 additions and 1172 deletions
  1. 1039 1171
      src/llvm_backend_expr.cpp
  2. 2 1
      src/llvm_backend_general.cpp

+ 1039 - 1171
src/llvm_backend_expr.cpp

@@ -3491,1415 +3491,1283 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
 	return addr;
 }
 
+void lb_build_addr_compound_lit_populate(lbProcedure *p, Slice<Ast *> const &elems, Array<lbCompoundLitElemTempData> *temp_data, Type *compound_type) {
+	Type *bt = base_type(compound_type);
+	Type *et = nullptr;
+	switch (bt->kind) {
+	case Type_Array:           et = bt->Array.elem;           break;
+	case Type_EnumeratedArray: et = bt->EnumeratedArray.elem; break;
+	case Type_Slice:           et = bt->Slice.elem;           break;
+	case Type_BitSet:          et = bt->BitSet.elem;          break;
+	case Type_DynamicArray:    et = bt->DynamicArray.elem;    break;
+	case Type_SimdVector:      et = bt->SimdVector.elem;      break;
+	case Type_Matrix:          et = bt->Matrix.elem;          break;
+	}
+	GB_ASSERT(et != nullptr);
+
+
+	// NOTE(bill): Separate value, gep, store into their own chunks
+	for_array(i, elems) {
+		Ast *elem = elems[i];
+		if (elem->kind == Ast_FieldValue) {
+			ast_node(fv, FieldValue, elem);
+			if (lb_is_elem_const(fv->value, et)) {
+				continue;
+			}
+			if (is_ast_range(fv->field)) {
+				ast_node(ie, BinaryExpr, fv->field);
+				TypeAndValue lo_tav = ie->left->tav;
+				TypeAndValue hi_tav = ie->right->tav;
+				GB_ASSERT(lo_tav.mode == Addressing_Constant);
+				GB_ASSERT(hi_tav.mode == Addressing_Constant);
+
+				TokenKind op = ie->op.kind;
+				i64 lo = exact_value_to_i64(lo_tav.value);
+				i64 hi = exact_value_to_i64(hi_tav.value);
+				if (op != Token_RangeHalf) {
+					hi += 1;
+				}
 
-lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
-	switch (expr->kind) {
-	case_ast_node(i, Implicit, expr);
-		lbAddr v = {};
-		switch (i->kind) {
-		case Token_context:
-			v = lb_find_or_generate_context_ptr(p);
-			break;
-		}
-
-		GB_ASSERT(v.addr.value != nullptr);
-		return v;
-	case_end;
-
-	case_ast_node(i, Ident, expr);
-		if (is_blank_ident(expr)) {
-			lbAddr val = {};
-			return val;
-		}
-		String name = i->token.string;
-		Entity *e = entity_of_node(expr);
-		return lb_build_addr_from_entity(p, e, expr);
-	case_end;
+				lbValue value = lb_emit_conv(p, lb_build_expr(p, fv->value), et);
 
-	case_ast_node(se, SelectorExpr, expr);
-		Ast *sel_node = unparen_expr(se->selector);
-		if (sel_node->kind == Ast_Ident) {
-			String selector = sel_node->Ident.token.string;
-			TypeAndValue tav = type_and_value_of_expr(se->expr);
+				GB_ASSERT((hi-lo) > 0);
 
-			if (tav.mode == Addressing_Invalid) {
-				// NOTE(bill): Imports
-				Entity *imp = entity_of_node(se->expr);
-				if (imp != nullptr) {
-					GB_ASSERT(imp->kind == Entity_ImportName);
+				enum {MAX_ELEMENT_AMOUNT = 32};
+				if ((hi-lo) <= MAX_ELEMENT_AMOUNT) {
+					for (i64 k = lo; k < hi; k++) {
+						lbCompoundLitElemTempData data = {};
+						data.value = value;
+						data.elem_index = k;
+						array_add(temp_data, data);
+					}
+				} else {
+					lbCompoundLitElemTempData data = {};
+					data.value = value;
+					data.elem_index = lo;
+					data.elem_length = hi-lo;
+					array_add(temp_data, data);
 				}
-				return lb_build_addr(p, unparen_expr(se->selector));
+			} else {
+				auto tav = fv->field->tav;
+				GB_ASSERT(tav.mode == Addressing_Constant);
+				i64 index = exact_value_to_i64(tav.value);
+
+				lbValue value = lb_emit_conv(p, lb_build_expr(p, fv->value), et);
+				GB_ASSERT(!is_type_tuple(value.type));
+
+				lbCompoundLitElemTempData data = {};
+				data.value = value;
+				data.expr = fv->value;
+				data.elem_index = cast(i32)index;
+				array_add(temp_data, data);
 			}
 
+		} else {
+			if (lb_is_elem_const(elem, et)) {
+				continue;
+			}
 
-			Type *type = base_type(tav.type);
-			if (tav.mode == Addressing_Type) { // Addressing_Type
-				Selection sel = lookup_field(tav.type, selector, true);
-				if (sel.pseudo_field) {
-					GB_ASSERT(sel.entity->kind == Entity_Procedure);
-					return lb_addr(lb_find_value_from_entity(p->module, sel.entity));
+			lbValue field_expr = lb_build_expr(p, elem);
+			GB_ASSERT(!is_type_tuple(field_expr.type));
+
+			lbValue ev = lb_emit_conv(p, field_expr, et);
+
+			lbCompoundLitElemTempData data = {};
+			data.value = ev;
+			data.elem_index = cast(i32)i;
+			array_add(temp_data, data);
+		}
+	}
+}
+void lb_build_addr_compound_lit_assign_array(lbProcedure *p, Array<lbCompoundLitElemTempData> &temp_data) {
+	for_array(i, temp_data) {
+		auto td = temp_data[i];
+		if (td.value.value != nullptr) {
+			if (td.elem_length > 0) {
+				auto loop_data = lb_loop_start(p, cast(isize)td.elem_length, t_i32);
+				{
+					lbValue dst = temp_data[i].gep;
+					dst = lb_emit_ptr_offset(p, dst, loop_data.idx);
+					lb_emit_store(p, dst, temp_data[i].value);
 				}
-				GB_PANIC("Unreachable %.*s", LIT(selector));
+				lb_loop_end(p, loop_data);
+			} else {
+				lb_emit_store(p, temp_data[i].gep, temp_data[i].value);
 			}
+		}
+	}
+}
 
-			if (se->swizzle_count > 0) {
-				Type *array_type = base_type(type_deref(tav.type));
-				GB_ASSERT(array_type->kind == Type_Array);
-				u8 swizzle_count = se->swizzle_count;
-				u8 swizzle_indices_raw = se->swizzle_indices;
-				u8 swizzle_indices[4] = {};
-				for (u8 i = 0; i < swizzle_count; i++) {
-					u8 index = swizzle_indices_raw>>(i*2) & 3;
-					swizzle_indices[i] = index;
-				}
-				lbValue a = {};
-				if (is_type_pointer(tav.type)) {
-					a = lb_build_expr(p, se->expr);
-				} else {
-					lbAddr addr = lb_build_addr(p, se->expr);
-					a = lb_addr_get_ptr(p, addr);
-				}
 
-				GB_ASSERT(is_type_array(expr->tav.type));
-				return lb_addr_swizzle(a, expr->tav.type, swizzle_count, swizzle_indices);
-			}
+lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
+	ast_node(cl, CompoundLit, expr);
 
-			Selection sel = lookup_field(type, selector, false);
-			GB_ASSERT(sel.entity != nullptr);
-			if (sel.pseudo_field) {
-				GB_ASSERT(sel.entity->kind == Entity_Procedure);
-				Entity *e = entity_of_node(sel_node);
-				return lb_addr(lb_find_value_from_entity(p->module, e));
-			}
+	Type *type = type_of_expr(expr);
+	Type *bt = base_type(type);
 
-			{
-				lbAddr addr = lb_build_addr(p, se->expr);
-				if (addr.kind == lbAddr_Map) {
-					lbValue v = lb_addr_load(p, addr);
-					lbValue a = lb_address_from_load_or_generate_local(p, v);
-					a = lb_emit_deep_field_gep(p, a, sel);
-					return lb_addr(a);
-				} else if (addr.kind == lbAddr_Context) {
-					GB_ASSERT(sel.index.count > 0);
-					if (addr.ctx.sel.index.count >= 0) {
-						sel = selection_combine(addr.ctx.sel, sel);
-					}
-					addr.ctx.sel = sel;
-					addr.kind = lbAddr_Context;
-					return addr;
-				} else if (addr.kind == lbAddr_SoaVariable) {
-					lbValue index = addr.soa.index;
-					i32 first_index = sel.index[0];
-					Selection sub_sel = sel;
-					sub_sel.index.data += 1;
-					sub_sel.index.count -= 1;
+	lbAddr v = lb_add_local_generated(p, type, true);
 
-					lbValue arr = lb_emit_struct_ep(p, addr.addr, first_index);
+	Type *et = nullptr;
+	switch (bt->kind) {
+	case Type_Array:           et = bt->Array.elem;           break;
+	case Type_EnumeratedArray: et = bt->EnumeratedArray.elem; break;
+	case Type_Slice:           et = bt->Slice.elem;           break;
+	case Type_BitSet:          et = bt->BitSet.elem;          break;
+	case Type_SimdVector:      et = bt->SimdVector.elem;      break;
+	case Type_Matrix:          et = bt->Matrix.elem;          break;
+	}
 
-					Type *t = base_type(type_deref(addr.addr.type));
-					GB_ASSERT(is_type_soa_struct(t));
+	String proc_name = {};
+	if (p->entity) {
+		proc_name = p->entity->token.string;
+	}
+	TokenPos pos = ast_token(expr).pos;
 
-					if (addr.soa.index_expr != nullptr && (!lb_is_const(addr.soa.index) || t->Struct.soa_kind != StructSoa_Fixed)) {
-						lbValue len = lb_soa_struct_len(p, addr.addr);
-						lb_emit_bounds_check(p, ast_token(addr.soa.index_expr), addr.soa.index, len);
-					}
+	switch (bt->kind) {
+	default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break;
 
-					lbValue item = {};
+	case Type_Struct: {
+		// TODO(bill): "constant" '#raw_union's are not initialized constantly at the moment.
+		// NOTE(bill): This is due to the layout of the unions when printed to LLVM-IR
+		bool is_raw_union = is_type_raw_union(bt);
+		GB_ASSERT(is_type_struct(bt) || is_raw_union);
+		TypeStruct *st = &bt->Struct;
+		if (cl->elems.count > 0) {
+			lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
+			lbValue comp_lit_ptr = lb_addr_get_ptr(p, v);
 
-					if (t->Struct.soa_kind == StructSoa_Fixed) {
-						item = lb_emit_array_ep(p, arr, index);
-					} else {
-						item = lb_emit_ptr_offset(p, lb_emit_load(p, arr), index);
-					}
-					if (sub_sel.index.count > 0) {
-						item = lb_emit_deep_field_gep(p, item, sub_sel);
-					}
-					return lb_addr(item);
-				} else if (addr.kind == lbAddr_Swizzle) {
-					GB_ASSERT(sel.index.count > 0);
-					// NOTE(bill): just patch the index in place
-					sel.index[0] = addr.swizzle.indices[sel.index[0]];
-				} else if (addr.kind == lbAddr_SwizzleLarge) {
-					GB_ASSERT(sel.index.count > 0);
-					// NOTE(bill): just patch the index in place
-					sel.index[0] = addr.swizzle.indices[sel.index[0]];
+			for_array(field_index, cl->elems) {
+				Ast *elem = cl->elems[field_index];
+
+				lbValue field_expr = {};
+				Entity *field = nullptr;
+				isize index = field_index;
+
+				if (elem->kind == Ast_FieldValue) {
+					ast_node(fv, FieldValue, elem);
+					String name = fv->field->Ident.token.string;
+					Selection sel = lookup_field(bt, name, false);
+					index = sel.index[0];
+					elem = fv->value;
+					TypeAndValue tav = type_and_value_of_expr(elem);
+				} else {
+					TypeAndValue tav = type_and_value_of_expr(elem);
+					Selection sel = lookup_field_from_index(bt, st->fields[field_index]->Variable.field_index);
+					index = sel.index[0];
 				}
 
-				lbValue a = lb_addr_get_ptr(p, addr);
-				a = lb_emit_deep_field_gep(p, a, sel);
-				return lb_addr(a);
-			}
-		} else {
-			GB_PANIC("Unsupported selector expression");
-		}
-	case_end;
+				field = st->fields[index];
+				Type *ft = field->type;
+				if (!is_raw_union && !is_type_typeid(ft) && lb_is_elem_const(elem, ft)) {
+					continue;
+				}
 
-	case_ast_node(se, SelectorCallExpr, expr);
-		lbValue e = lb_build_expr(p, expr);
-		return lb_addr(lb_address_from_load_or_generate_local(p, e));
-	case_end;
+				field_expr = lb_build_expr(p, elem);
 
-	case_ast_node(ta, TypeAssertion, expr);
-		TokenPos pos = ast_token(expr).pos;
-		lbValue e = lb_build_expr(p, ta->expr);
-		Type *t = type_deref(e.type);
-		if (is_type_union(t)) {
-			Type *type = type_of_expr(expr);
-			lbAddr v = lb_add_local_generated(p, type, false);
-			lb_addr_store(p, v, lb_emit_union_cast(p, lb_build_expr(p, ta->expr), type, pos));
-			return v;
-		} else if (is_type_any(t)) {
-			Type *type = type_of_expr(expr);
-			return lb_emit_any_cast_addr(p, lb_build_expr(p, ta->expr), type, pos);
-		} else {
-			GB_PANIC("TODO(bill): type assertion %s", type_to_string(e.type));
+				lbValue gep = {};
+				if (is_raw_union) {
+					gep = lb_emit_conv(p, comp_lit_ptr, alloc_type_pointer(ft));
+				} else {
+					gep = lb_emit_struct_ep(p, comp_lit_ptr, cast(i32)index);
+				}
+
+				Type *fet = field_expr.type;
+				GB_ASSERT(fet->kind != Type_Tuple);
+
+				// HACK TODO(bill): THIS IS A MASSIVE HACK!!!!
+				if (is_type_union(ft) && !are_types_identical(fet, ft) && !is_type_untyped(fet)) {
+					GB_ASSERT_MSG(union_variant_index(ft, fet) > 0, "%s", type_to_string(fet));
+
+					lb_emit_store_union_variant(p, gep, field_expr, fet);
+				} else {
+					lbValue fv = lb_emit_conv(p, field_expr, ft);
+					lb_emit_store(p, gep, fv);
+				}
+			}
 		}
-	case_end;
+		break;
+	}
 
-	case_ast_node(ue, UnaryExpr, expr);
-		switch (ue->op.kind) {
-		case Token_And: {
-			lbValue ptr = lb_build_expr(p, expr);
-			return lb_addr(lb_address_from_load_or_generate_local(p, ptr));
+	case Type_Map: {
+		if (cl->elems.count == 0) {
+			break;
 		}
-		default:
-			GB_PANIC("Invalid unary expression for lb_build_addr");
+		GB_ASSERT(!build_context.no_dynamic_literals);
+		{
+			auto args = array_make<lbValue>(permanent_allocator(), 3);
+			args[0] = lb_gen_map_header(p, v.addr, type);
+			args[1] = lb_const_int(p->module, t_int, 2*cl->elems.count);
+			args[2] = lb_emit_source_code_location(p, proc_name, pos);
+			lb_emit_runtime_call(p, "__dynamic_map_reserve", args);
 		}
-	case_end;
-	case_ast_node(be, BinaryExpr, expr);
-		lbValue v = lb_build_expr(p, expr);
-		Type *t = v.type;
-		if (is_type_pointer(t)) {
-			return lb_addr(v);
+		for_array(field_index, cl->elems) {
+			Ast *elem = cl->elems[field_index];
+			ast_node(fv, FieldValue, elem);
+
+			lbValue key   = lb_build_expr(p, fv->field);
+			lbValue value = lb_build_expr(p, fv->value);
+			lb_insert_dynamic_map_key_and_value(p, v, type, key, value, elem);
 		}
-		return lb_addr(lb_address_from_load_or_generate_local(p, v));
-	case_end;
+		break;
+	}
 
-	case_ast_node(ie, IndexExpr, expr);
-		Type *t = base_type(type_of_expr(ie->expr));
+	case Type_Array: {
+		if (cl->elems.count > 0) {
+			lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
 
-		bool deref = is_type_pointer(t);
-		t = base_type(type_deref(t));
-		if (is_type_soa_struct(t)) {			
-			// SOA STRUCTURES!!!!
-			lbValue val = lb_build_addr_ptr(p, ie->expr);
-			if (deref) {
-				val = lb_emit_load(p, val);
+			auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
+
+			lb_build_addr_compound_lit_populate(p, cl->elems, &temp_data, type);
+
+			lbValue dst_ptr = lb_addr_get_ptr(p, v);
+			for_array(i, temp_data) {
+				i32 index = cast(i32)(temp_data[i].elem_index);
+				temp_data[i].gep = lb_emit_array_epi(p, dst_ptr, index);
 			}
 
-			lbValue index = lb_build_expr(p, ie->index);
-			return lb_addr_soa_variable(val, index, ie->index);
+			lb_build_addr_compound_lit_assign_array(p, temp_data);
 		}
+		break;
+	}
+	case Type_EnumeratedArray: {
+		if (cl->elems.count > 0) {
+			lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
 
-		if (ie->expr->tav.mode == Addressing_SoaVariable) {
-			// SOA Structures for slices/dynamic arrays
-			GB_ASSERT(is_type_pointer(type_of_expr(ie->expr)));
-
-			lbValue field = lb_build_expr(p, ie->expr);
-			lbValue index = lb_build_expr(p, ie->index);
+			auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
 
+			lb_build_addr_compound_lit_populate(p, cl->elems, &temp_data, type);
 
-			if (!build_context.no_bounds_check) {
-				// TODO HACK(bill): Clean up this hack to get the length for bounds checking
-				// GB_ASSERT(LLVMIsALoadInst(field.value));
+			lbValue dst_ptr = lb_addr_get_ptr(p, v);
+			i64 index_offset = exact_value_to_i64(*bt->EnumeratedArray.min_value);
+			for_array(i, temp_data) {
+				i32 index = cast(i32)(temp_data[i].elem_index - index_offset);
+				temp_data[i].gep = lb_emit_array_epi(p, dst_ptr, index);
+			}
 
-				// lbValue a = {};
-				// a.value = LLVMGetOperand(field.value, 0);
-				// a.type = alloc_type_pointer(field.type);
+			lb_build_addr_compound_lit_assign_array(p, temp_data);
+		}
+		break;
+	}
+	case Type_Slice: {
+		if (cl->elems.count > 0) {
+			lbValue slice = lb_const_value(p->module, type, exact_value_compound(expr));
 
-				// irInstr *b = &a->Instr;
-				// GB_ASSERT(b->kind == irInstr_StructElementPtr);
-				// lbValue base_struct = b->StructElementPtr.address;
+			lbValue data = lb_slice_elem(p, slice);
 
-				// GB_ASSERT(is_type_soa_struct(type_deref(ir_type(base_struct))));
-				// lbValue len = ir_soa_struct_len(p, base_struct);
-				// lb_emit_bounds_check(p, ast_token(ie->index), index, len);
-			}
-			lbValue val = lb_emit_ptr_offset(p, field, index);
-			return lb_addr(val);
-		}
+			auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
 
-		GB_ASSERT_MSG(is_type_indexable(t), "%s %s", type_to_string(t), expr_to_string(expr));
+			lb_build_addr_compound_lit_populate(p, cl->elems, &temp_data, type);
 
-		if (is_type_map(t)) {
-			lbAddr map_addr = lb_build_addr(p, ie->expr);
-			lbValue map_val = lb_addr_load(p, map_addr);
-			if (deref) {
-				map_val = lb_emit_load(p, map_val);
+			for_array(i, temp_data) {
+				temp_data[i].gep = lb_emit_ptr_offset(p, data, lb_const_int(p->module, t_int, temp_data[i].elem_index));
 			}
 
-			lbValue key = lb_build_expr(p, ie->index);
-			key = lb_emit_conv(p, key, t->Map.key);
+			lb_build_addr_compound_lit_assign_array(p, temp_data);
 
-			Type *result_type = type_of_expr(expr);
-			lbValue map_ptr = lb_address_from_load_or_generate_local(p, map_val);
-			return lb_addr_map(map_ptr, key, t, result_type);
-		}
+			{
+				lbValue count = {};
+				count.type = t_int;
 
-		switch (t->kind) {
-		case Type_Array: {
-			lbValue array = {};
-			array = lb_build_addr_ptr(p, ie->expr);
-			if (deref) {
-				array = lb_emit_load(p, array);
+				if (lb_is_const(slice)) {
+					unsigned indices[1] = {1};
+					count.value = LLVMConstExtractValue(slice.value, indices, gb_count_of(indices));
+				} else {
+					count.value = LLVMBuildExtractValue(p->builder, slice.value, 1, "");
+				}
+				lb_fill_slice(p, v, data, count);
 			}
-			lbValue index = lb_build_expr(p, ie->index);
-			index = lb_emit_conv(p, index, t_int);
-			lbValue elem = lb_emit_array_ep(p, array, index);
+		}
+		break;
+	}
 
-			auto index_tv = type_and_value_of_expr(ie->index);
-			if (index_tv.mode != Addressing_Constant) {
-				lbValue len = lb_const_int(p->module, t_int, t->Array.count);
-				lb_emit_bounds_check(p, ast_token(ie->index), index, len);
-			}
-			return lb_addr(elem);
+	case Type_DynamicArray: {
+		if (cl->elems.count == 0) {
+			break;
 		}
+		GB_ASSERT(!build_context.no_dynamic_literals);
 
-		case Type_EnumeratedArray: {
-			lbValue array = {};
-			array = lb_build_addr_ptr(p, ie->expr);
-			if (deref) {
-				array = lb_emit_load(p, array);
-			}
+		Type *et = bt->DynamicArray.elem;
+		lbValue size  = lb_const_int(p->module, t_int, type_size_of(et));
+		lbValue align = lb_const_int(p->module, t_int, type_align_of(et));
 
-			Type *index_type = t->EnumeratedArray.index;
+		i64 item_count = gb_max(cl->max_count, cl->elems.count);
+		{
 
-			auto index_tv = type_and_value_of_expr(ie->index);
+			auto args = array_make<lbValue>(permanent_allocator(), 5);
+			args[0] = lb_emit_conv(p, lb_addr_get_ptr(p, v), t_rawptr);
+			args[1] = size;
+			args[2] = align;
+			args[3] = lb_const_int(p->module, t_int, item_count);
+			args[4] = lb_emit_source_code_location(p, proc_name, pos);
+			lb_emit_runtime_call(p, "__dynamic_array_reserve", args);
+		}
 
-			lbValue index = {};
-			if (compare_exact_values(Token_NotEq, *t->EnumeratedArray.min_value, exact_value_i64(0))) {
-				if (index_tv.mode == Addressing_Constant) {
-					ExactValue idx = exact_value_sub(index_tv.value, *t->EnumeratedArray.min_value);
-					index = lb_const_value(p->module, index_type, idx);
-				} else {
-					index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
-					index = lb_emit_arith(p, Token_Sub, index, lb_const_value(p->module, index_type, *t->EnumeratedArray.min_value), index_type);
-				}
-			} else {
-				index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
-			}
+		lbValue items = lb_generate_local_array(p, et, item_count);
 
-			lbValue elem = lb_emit_array_ep(p, array, index);
+		auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
+		lb_build_addr_compound_lit_populate(p, cl->elems, &temp_data, type);
 
-			if (index_tv.mode != Addressing_Constant) {
-				lbValue len = lb_const_int(p->module, t_int, t->EnumeratedArray.count);
-				lb_emit_bounds_check(p, ast_token(ie->index), index, len);
-			}
-			return lb_addr(elem);
+		for_array(i, temp_data) {
+			temp_data[i].gep = lb_emit_array_epi(p, items, temp_data[i].elem_index);
 		}
+		lb_build_addr_compound_lit_assign_array(p, temp_data);
 
-		case Type_Slice: {
-			lbValue slice = {};
-			slice = lb_build_expr(p, ie->expr);
-			if (deref) {
-				slice = lb_emit_load(p, slice);
-			}
-			lbValue elem = lb_slice_elem(p, slice);
-			lbValue index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
-			lbValue len = lb_slice_len(p, slice);
-			lb_emit_bounds_check(p, ast_token(ie->index), index, len);
-			lbValue v = lb_emit_ptr_offset(p, elem, index);
-			return lb_addr(v);
+		{
+			auto args = array_make<lbValue>(permanent_allocator(), 6);
+			args[0] = lb_emit_conv(p, v.addr, t_rawptr);
+			args[1] = size;
+			args[2] = align;
+			args[3] = lb_emit_conv(p, items, t_rawptr);
+			args[4] = lb_const_int(p->module, t_int, item_count);
+			args[5] = lb_emit_source_code_location(p, proc_name, pos);
+			lb_emit_runtime_call(p, "__dynamic_array_append", args);
 		}
+		break;
+	}
 
-		case Type_MultiPointer: {
-			lbValue multi_ptr = {};
-			multi_ptr = lb_build_expr(p, ie->expr);
-			if (deref) {
-				multi_ptr = lb_emit_load(p, multi_ptr);
-			}
-			lbValue index = lb_build_expr(p, ie->index);
-			lbValue v = {};
+	case Type_Basic: {
+		GB_ASSERT(is_type_any(bt));
+		if (cl->elems.count > 0) {
+			lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
+			String field_names[2] = {
+				str_lit("data"),
+				str_lit("id"),
+			};
+			Type *field_types[2] = {
+				t_rawptr,
+				t_typeid,
+			};
 
-			LLVMValueRef indices[1] = {index.value};
-			v.value = LLVMBuildGEP2(p->builder, lb_type(p->module, t->MultiPointer.elem), multi_ptr.value, indices, 1, "foo");
-			v.type = alloc_type_pointer(t->MultiPointer.elem);
-			return lb_addr(v);
-		}
+			for_array(field_index, cl->elems) {
+				Ast *elem = cl->elems[field_index];
 
-		case Type_RelativeSlice: {
-			lbAddr slice_addr = {};
-			if (deref) {
-				slice_addr = lb_addr(lb_build_expr(p, ie->expr));
-			} else {
-				slice_addr = lb_build_addr(p, ie->expr);
-			}
-			lbValue slice = lb_addr_load(p, slice_addr);
+				lbValue field_expr = {};
+				isize index = field_index;
 
-			lbValue elem = lb_slice_elem(p, slice);
-			lbValue index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
-			lbValue len = lb_slice_len(p, slice);
-			lb_emit_bounds_check(p, ast_token(ie->index), index, len);
-			lbValue v = lb_emit_ptr_offset(p, elem, index);
-			return lb_addr(v);
-		}
+				if (elem->kind == Ast_FieldValue) {
+					ast_node(fv, FieldValue, elem);
+					Selection sel = lookup_field(bt, fv->field->Ident.token.string, false);
+					index = sel.index[0];
+					elem = fv->value;
+				} else {
+					TypeAndValue tav = type_and_value_of_expr(elem);
+					Selection sel = lookup_field(bt, field_names[field_index], false);
+					index = sel.index[0];
+				}
 
-		case Type_DynamicArray: {
-			lbValue dynamic_array = {};
-			dynamic_array = lb_build_expr(p, ie->expr);
-			if (deref) {
-				dynamic_array = lb_emit_load(p, dynamic_array);
-			}
-			lbValue elem = lb_dynamic_array_elem(p, dynamic_array);
-			lbValue len = lb_dynamic_array_len(p, dynamic_array);
-			lbValue index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
-			lb_emit_bounds_check(p, ast_token(ie->index), index, len);
-			lbValue v = lb_emit_ptr_offset(p, elem, index);
-			return lb_addr(v);
-		}
-		
-		case Type_Matrix: {
-			lbValue matrix = {};
-			matrix = lb_build_addr_ptr(p, ie->expr);
-			if (deref) {
-				matrix = lb_emit_load(p, matrix);
-			}
-			lbValue index = lb_build_expr(p, ie->index);
-			index = lb_emit_conv(p, index, t_int);
-			lbValue elem = lb_emit_matrix_ep(p, matrix, lb_const_int(p->module, t_int, 0), index);
-			elem = lb_emit_conv(p, elem, alloc_type_pointer(type_of_expr(expr)));
+				field_expr = lb_build_expr(p, elem);
 
-			auto index_tv = type_and_value_of_expr(ie->index);
-			if (index_tv.mode != Addressing_Constant) {
-				lbValue len = lb_const_int(p->module, t_int, t->Matrix.column_count);
-				lb_emit_bounds_check(p, ast_token(ie->index), index, len);
+				GB_ASSERT(field_expr.type->kind != Type_Tuple);
+
+				Type *ft = field_types[index];
+				lbValue fv = lb_emit_conv(p, field_expr, ft);
+				lbValue gep = lb_emit_struct_ep(p, lb_addr_get_ptr(p, v), cast(i32)index);
+				lb_emit_store(p, gep, fv);
 			}
-			return lb_addr(elem);
 		}
 
+		break;
+	}
 
-		case Type_Basic: { // Basic_string
-			lbValue str;
-			lbValue elem;
-			lbValue len;
-			lbValue index;
+	case Type_BitSet: {
+		i64 sz = type_size_of(type);
+		if (cl->elems.count > 0 && sz > 0) {
+			lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
 
-			str = lb_build_expr(p, ie->expr);
-			if (deref) {
-				str = lb_emit_load(p, str);
-			}
-			elem = lb_string_elem(p, str);
-			len = lb_string_len(p, str);
+			lbValue lower = lb_const_value(p->module, t_int, exact_value_i64(bt->BitSet.lower));
+			for_array(i, cl->elems) {
+				Ast *elem = cl->elems[i];
+				GB_ASSERT(elem->kind != Ast_FieldValue);
 
-			index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
-			lb_emit_bounds_check(p, ast_token(ie->index), index, len);
+				if (lb_is_elem_const(elem, et)) {
+					continue;
+				}
 
-			return lb_addr(lb_emit_ptr_offset(p, elem, index));
-		}
-		}
-	case_end;
-	
-	case_ast_node(ie, MatrixIndexExpr, expr);
-		Type *t = base_type(type_of_expr(ie->expr));
+				lbValue expr = lb_build_expr(p, elem);
+				GB_ASSERT(expr.type->kind != Type_Tuple);
 
-		bool deref = is_type_pointer(t);
-		t = base_type(type_deref(t));
-		
-		lbValue m = {};
-		m = lb_build_addr_ptr(p, ie->expr);
-		if (deref) {
-			m = lb_emit_load(p, m);
-		}
-		lbValue row_index = lb_build_expr(p, ie->row_index);
-		lbValue column_index = lb_build_expr(p, ie->column_index);
-		row_index = lb_emit_conv(p, row_index, t_int);
-		column_index = lb_emit_conv(p, column_index, t_int);
-		lbValue elem = lb_emit_matrix_ep(p, m, row_index, column_index);
+				Type *it = bit_set_to_int(bt);
+				lbValue one = lb_const_value(p->module, it, exact_value_i64(1));
+				lbValue e = lb_emit_conv(p, expr, it);
+				e = lb_emit_arith(p, Token_Sub, e, lower, it);
+				e = lb_emit_arith(p, Token_Shl, one, e, it);
 
-		auto row_index_tv = type_and_value_of_expr(ie->row_index);
-		auto column_index_tv = type_and_value_of_expr(ie->column_index);
-		if (row_index_tv.mode != Addressing_Constant || column_index_tv.mode != Addressing_Constant) {
-			lbValue row_count = lb_const_int(p->module, t_int, t->Matrix.row_count);
-			lbValue column_count = lb_const_int(p->module, t_int, t->Matrix.column_count);
-			lb_emit_matrix_bounds_check(p, ast_token(ie->row_index), row_index, column_index, row_count, column_count);
+				lbValue old_value = lb_emit_transmute(p, lb_addr_load(p, v), it);
+				lbValue new_value = lb_emit_arith(p, Token_Or, old_value, e, it);
+				new_value = lb_emit_transmute(p, new_value, type);
+				lb_addr_store(p, v, new_value);
+			}
 		}
-		return lb_addr(elem);
-		
-		
-	case_end;
-
-	case_ast_node(se, SliceExpr, expr);
+		break;
+	}
 
-		lbValue low  = lb_const_int(p->module, t_int, 0);
-		lbValue high = {};
+	case Type_Matrix: {
+		if (cl->elems.count > 0) {
+			lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
 
-		if (se->low  != nullptr) {
-			low = lb_correct_endianness(p, lb_build_expr(p, se->low));
-		}
-		if (se->high != nullptr) {
-			high = lb_correct_endianness(p, lb_build_expr(p, se->high));
-		}
+			auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
 
-		bool no_indices = se->low == nullptr && se->high == nullptr;
+			// NOTE(bill): Separate value, gep, store into their own chunks
+			for_array(i, cl->elems) {
+				Ast *elem = cl->elems[i];
 
-		lbAddr addr = lb_build_addr(p, se->expr);
-		lbValue base = lb_addr_load(p, addr);
-		Type *type = base_type(base.type);
+				if (elem->kind == Ast_FieldValue) {
+					ast_node(fv, FieldValue, elem);
+					if (lb_is_elem_const(fv->value, et)) {
+						continue;
+					}
+					if (is_ast_range(fv->field)) {
+						ast_node(ie, BinaryExpr, fv->field);
+						TypeAndValue lo_tav = ie->left->tav;
+						TypeAndValue hi_tav = ie->right->tav;
+						GB_ASSERT(lo_tav.mode == Addressing_Constant);
+						GB_ASSERT(hi_tav.mode == Addressing_Constant);
 
-		if (is_type_pointer(type)) {
-			type = base_type(type_deref(type));
-			addr = lb_addr(base);
-			base = lb_addr_load(p, addr);
-		}
+						TokenKind op = ie->op.kind;
+						i64 lo = exact_value_to_i64(lo_tav.value);
+						i64 hi = exact_value_to_i64(hi_tav.value);
+						if (op != Token_RangeHalf) {
+							hi += 1;
+						}
 
-		switch (type->kind) {
-		case Type_Slice: {
-			Type *slice_type = type;
-			lbValue len = lb_slice_len(p, base);
-			if (high.value == nullptr) high = len;
+						lbValue value = lb_build_expr(p, fv->value);
 
-			if (!no_indices) {
-				lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
-			}
+						for (i64 k = lo; k < hi; k++) {
+							lbCompoundLitElemTempData data = {};
+							data.value = value;
 
-			lbValue elem    = lb_emit_ptr_offset(p, lb_slice_elem(p, base), low);
-			lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
+							data.elem_index = cast(i32)matrix_row_major_index_to_offset(bt, k);
+							array_add(&temp_data, data);
+						}
 
-			lbAddr slice = lb_add_local_generated(p, slice_type, false);
-			lb_fill_slice(p, slice, elem, new_len);
-			return slice;
-		}
+					} else {
+						auto tav = fv->field->tav;
+						GB_ASSERT(tav.mode == Addressing_Constant);
+						i64 index = exact_value_to_i64(tav.value);
 
-		case Type_RelativeSlice:
-			GB_PANIC("TODO(bill): Type_RelativeSlice should be handled above already on the lb_addr_load");
-			break;
+						lbValue value = lb_build_expr(p, fv->value);
+						lbCompoundLitElemTempData data = {};
+						data.value = lb_emit_conv(p, value, et);
+						data.expr = fv->value;
 
-		case Type_DynamicArray: {
-			Type *elem_type = type->DynamicArray.elem;
-			Type *slice_type = alloc_type_slice(elem_type);
+						data.elem_index = cast(i32)matrix_row_major_index_to_offset(bt, index);
+						array_add(&temp_data, data);
+					}
 
-			lbValue len = lb_dynamic_array_len(p, base);
-			if (high.value == nullptr) high = len;
+				} else {
+					if (lb_is_elem_const(elem, et)) {
+						continue;
+					}
+					lbCompoundLitElemTempData data = {};
+					data.expr = elem;
+					data.elem_index = cast(i32)matrix_row_major_index_to_offset(bt, i);
+					array_add(&temp_data, data);
+				}
+			}
 
-			if (!no_indices) {
-				lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
+			for_array(i, temp_data) {
+				temp_data[i].gep = lb_emit_array_epi(p, lb_addr_get_ptr(p, v), temp_data[i].elem_index);
 			}
 
-			lbValue elem    = lb_emit_ptr_offset(p, lb_dynamic_array_elem(p, base), low);
-			lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
+			for_array(i, temp_data) {
+				lbValue field_expr = temp_data[i].value;
+				Ast *expr = temp_data[i].expr;
 
-			lbAddr slice = lb_add_local_generated(p, slice_type, false);
-			lb_fill_slice(p, slice, elem, new_len);
-			return slice;
-		}
+				auto prev_hint = lb_set_copy_elision_hint(p, lb_addr(temp_data[i].gep), expr);
 
-		case Type_MultiPointer: {
-			lbAddr res = lb_add_local_generated(p, type_of_expr(expr), false);
-			if (se->high == nullptr) {
-				lbValue offset = base;
-				LLVMValueRef indices[1] = {low.value};
-				offset.value = LLVMBuildGEP2(p->builder, lb_type(p->module, offset.type->MultiPointer.elem), offset.value, indices, 1, "");
-				lb_addr_store(p, res, offset);
-			} else {
-				low = lb_emit_conv(p, low, t_int);
-				high = lb_emit_conv(p, high, t_int);
-				
-				lb_emit_multi_pointer_slice_bounds_check(p, se->open, low, high);
+				if (field_expr.value == nullptr) {
+					field_expr = lb_build_expr(p, expr);
+				}
+				Type *t = field_expr.type;
+				GB_ASSERT(t->kind != Type_Tuple);
+				lbValue ev = lb_emit_conv(p, field_expr, et);
 
-				LLVMValueRef indices[1] = {low.value};
-				LLVMValueRef ptr = LLVMBuildGEP2(p->builder, lb_type(p->module, base.type->MultiPointer.elem), base.value, indices, 1, "");
-				LLVMValueRef len = LLVMBuildSub(p->builder, high.value, low.value, "");
-				
-				LLVMValueRef gep0 = lb_emit_struct_ep(p, res.addr, 0).value;
-				LLVMValueRef gep1 = lb_emit_struct_ep(p, res.addr, 1).value;
-				LLVMBuildStore(p->builder, ptr, gep0);
-				LLVMBuildStore(p->builder, len, gep1);
+				if (!p->copy_elision_hint.used) {
+					temp_data[i].value = ev;
+				}
+
+				lb_reset_copy_elision_hint(p, prev_hint);
+			}
+
+			for_array(i, temp_data) {
+				if (temp_data[i].value.value != nullptr) {
+					lb_emit_store(p, temp_data[i].gep, temp_data[i].value);
+				}
 			}
-			return res;
 		}
+		break;
+	}
 
-		case Type_Array: {
-			Type *slice_type = alloc_type_slice(type->Array.elem);
-			lbValue len = lb_const_int(p->module, t_int, type->Array.count);
+	case Type_SimdVector: {
+		if (cl->elems.count > 0) {
+			lbValue vector_value = lb_const_value(p->module, type, exact_value_compound(expr));
+			defer (lb_addr_store(p, v, vector_value));
 
-			if (high.value == nullptr) high = len;
+			auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
 
-			bool low_const  = type_and_value_of_expr(se->low).mode  == Addressing_Constant;
-			bool high_const = type_and_value_of_expr(se->high).mode == Addressing_Constant;
+			// NOTE(bill): Separate value, store into their own chunks
+			for_array(i, cl->elems) {
+				Ast *elem = cl->elems[i];
+				if (elem->kind == Ast_FieldValue) {
+					ast_node(fv, FieldValue, elem);
+					if (lb_is_elem_const(fv->value, et)) {
+						continue;
+					}
+					if (is_ast_range(fv->field)) {
+						ast_node(ie, BinaryExpr, fv->field);
+						TypeAndValue lo_tav = ie->left->tav;
+						TypeAndValue hi_tav = ie->right->tav;
+						GB_ASSERT(lo_tav.mode == Addressing_Constant);
+						GB_ASSERT(hi_tav.mode == Addressing_Constant);
 
-			if (!low_const || !high_const) {
-				if (!no_indices) {
-					lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
+						TokenKind op = ie->op.kind;
+						i64 lo = exact_value_to_i64(lo_tav.value);
+						i64 hi = exact_value_to_i64(hi_tav.value);
+						if (op != Token_RangeHalf) {
+							hi += 1;
+						}
+
+						lbValue value = lb_build_expr(p, fv->value);
+
+						for (i64 k = lo; k < hi; k++) {
+							lbCompoundLitElemTempData data = {};
+							data.value = value;
+							data.elem_index = cast(i32)k;
+							array_add(&temp_data, data);
+						}
+
+					} else {
+						auto tav = fv->field->tav;
+						GB_ASSERT(tav.mode == Addressing_Constant);
+						i64 index = exact_value_to_i64(tav.value);
+
+						lbValue value = lb_build_expr(p, fv->value);
+						lbCompoundLitElemTempData data = {};
+						data.value = lb_emit_conv(p, value, et);
+						data.expr = fv->value;
+						data.elem_index = cast(i32)index;
+						array_add(&temp_data, data);
+					}
+
+				} else {
+					if (lb_is_elem_const(elem, et)) {
+						continue;
+					}
+					lbCompoundLitElemTempData data = {};
+					data.expr = elem;
+					data.elem_index = cast(i32)i;
+					array_add(&temp_data, data);
 				}
 			}
-			lbValue elem    = lb_emit_ptr_offset(p, lb_array_elem(p, lb_addr_get_ptr(p, addr)), low);
-			lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
 
-			lbAddr slice = lb_add_local_generated(p, slice_type, false);
-			lb_fill_slice(p, slice, elem, new_len);
-			return slice;
-		}
 
-		case Type_Basic: {
-			GB_ASSERT(type == t_string);
-			lbValue len = lb_string_len(p, base);
-			if (high.value == nullptr) high = len;
+			for_array(i, temp_data) {
+				lbValue field_expr = temp_data[i].value;
+				Ast *expr = temp_data[i].expr;
 
-			if (!no_indices) {
-				lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
+				auto prev_hint = lb_set_copy_elision_hint(p, lb_addr(temp_data[i].gep), expr);
+
+				if (field_expr.value == nullptr) {
+					field_expr = lb_build_expr(p, expr);
+				}
+				Type *t = field_expr.type;
+				GB_ASSERT(t->kind != Type_Tuple);
+				lbValue ev = lb_emit_conv(p, field_expr, et);
+
+				if (!p->copy_elision_hint.used) {
+					temp_data[i].value = ev;
+				}
+
+				lb_reset_copy_elision_hint(p, prev_hint);
 			}
 
-			lbValue elem    = lb_emit_ptr_offset(p, lb_string_elem(p, base), low);
-			lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
 
-			lbAddr str = lb_add_local_generated(p, t_string, false);
-			lb_fill_string(p, str, elem, new_len);
-			return str;
+			// TODO(bill): reduce the need for individual `insertelement` if a `shufflevector`
+			// might be a better option
+
+			for_array(i, temp_data) {
+				if (temp_data[i].value.value != nullptr) {
+					LLVMValueRef index = lb_const_int(p->module, t_u32, temp_data[i].elem_index).value;
+					vector_value.value = LLVMBuildInsertElement(p->builder, vector_value.value, temp_data[i].value.value, index, "");
+				}
+			}
 		}
+		break;
+	}
+	}
 
+	return v;
+}
 
-		case Type_Struct:
-			if (is_type_soa_struct(type)) {
-				lbValue len = lb_soa_struct_len(p, lb_addr_get_ptr(p, addr));
-				if (high.value == nullptr) high = len;
 
-				if (!no_indices) {
-					lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
+lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
+	switch (expr->kind) {
+	case_ast_node(i, Implicit, expr);
+		lbAddr v = {};
+		switch (i->kind) {
+		case Token_context:
+			v = lb_find_or_generate_context_ptr(p);
+			break;
+		}
+
+		GB_ASSERT(v.addr.value != nullptr);
+		return v;
+	case_end;
+
+	case_ast_node(i, Ident, expr);
+		if (is_blank_ident(expr)) {
+			lbAddr val = {};
+			return val;
+		}
+		String name = i->token.string;
+		Entity *e = entity_of_node(expr);
+		return lb_build_addr_from_entity(p, e, expr);
+	case_end;
+
+	case_ast_node(se, SelectorExpr, expr);
+		Ast *sel_node = unparen_expr(se->selector);
+		if (sel_node->kind == Ast_Ident) {
+			String selector = sel_node->Ident.token.string;
+			TypeAndValue tav = type_and_value_of_expr(se->expr);
+
+			if (tav.mode == Addressing_Invalid) {
+				// NOTE(bill): Imports
+				Entity *imp = entity_of_node(se->expr);
+				if (imp != nullptr) {
+					GB_ASSERT(imp->kind == Entity_ImportName);
 				}
-				#if 1
+				return lb_build_addr(p, unparen_expr(se->selector));
+			}
 
-				lbAddr dst = lb_add_local_generated(p, type_of_expr(expr), true);
-				if (type->Struct.soa_kind == StructSoa_Fixed) {
-					i32 field_count = cast(i32)type->Struct.fields.count;
-					for (i32 i = 0; i < field_count; i++) {
-						lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i);
-						lbValue field_src = lb_emit_struct_ep(p, lb_addr_get_ptr(p, addr), i);
-						field_src = lb_emit_array_ep(p, field_src, low);
-						lb_emit_store(p, field_dst, field_src);
-					}
 
-					lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count);
-					lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
-					lb_emit_store(p, len_dst, new_len);
-				} else if (type->Struct.soa_kind == StructSoa_Slice) {
-					if (no_indices) {
-						lb_addr_store(p, dst, base);
-					} else {
-						i32 field_count = cast(i32)type->Struct.fields.count - 1;
-						for (i32 i = 0; i < field_count; i++) {
-							lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i);
-							lbValue field_src = lb_emit_struct_ev(p, base, i);
-							field_src = lb_emit_ptr_offset(p, field_src, low);
-							lb_emit_store(p, field_dst, field_src);
-						}
+			Type *type = base_type(tav.type);
+			if (tav.mode == Addressing_Type) { // Addressing_Type
+				Selection sel = lookup_field(tav.type, selector, true);
+				if (sel.pseudo_field) {
+					GB_ASSERT(sel.entity->kind == Entity_Procedure);
+					return lb_addr(lb_find_value_from_entity(p->module, sel.entity));
+				}
+				GB_PANIC("Unreachable %.*s", LIT(selector));
+			}
 
+			if (se->swizzle_count > 0) {
+				Type *array_type = base_type(type_deref(tav.type));
+				GB_ASSERT(array_type->kind == Type_Array);
+				u8 swizzle_count = se->swizzle_count;
+				u8 swizzle_indices_raw = se->swizzle_indices;
+				u8 swizzle_indices[4] = {};
+				for (u8 i = 0; i < swizzle_count; i++) {
+					u8 index = swizzle_indices_raw>>(i*2) & 3;
+					swizzle_indices[i] = index;
+				}
+				lbValue a = {};
+				if (is_type_pointer(tav.type)) {
+					a = lb_build_expr(p, se->expr);
+				} else {
+					lbAddr addr = lb_build_addr(p, se->expr);
+					a = lb_addr_get_ptr(p, addr);
+				}
 
-						lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count);
-						lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
-						lb_emit_store(p, len_dst, new_len);
+				GB_ASSERT(is_type_array(expr->tav.type));
+				return lb_addr_swizzle(a, expr->tav.type, swizzle_count, swizzle_indices);
+			}
+
+			Selection sel = lookup_field(type, selector, false);
+			GB_ASSERT(sel.entity != nullptr);
+			if (sel.pseudo_field) {
+				GB_ASSERT(sel.entity->kind == Entity_Procedure);
+				Entity *e = entity_of_node(sel_node);
+				return lb_addr(lb_find_value_from_entity(p->module, e));
+			}
+
+			{
+				lbAddr addr = lb_build_addr(p, se->expr);
+				if (addr.kind == lbAddr_Map) {
+					lbValue v = lb_addr_load(p, addr);
+					lbValue a = lb_address_from_load_or_generate_local(p, v);
+					a = lb_emit_deep_field_gep(p, a, sel);
+					return lb_addr(a);
+				} else if (addr.kind == lbAddr_Context) {
+					GB_ASSERT(sel.index.count > 0);
+					if (addr.ctx.sel.index.count >= 0) {
+						sel = selection_combine(addr.ctx.sel, sel);
 					}
-				} else if (type->Struct.soa_kind == StructSoa_Dynamic) {
-					i32 field_count = cast(i32)type->Struct.fields.count - 3;
-					for (i32 i = 0; i < field_count; i++) {
-						lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i);
-						lbValue field_src = lb_emit_struct_ev(p, base, i);
-						field_src = lb_emit_ptr_offset(p, field_src, low);
-						lb_emit_store(p, field_dst, field_src);
+					addr.ctx.sel = sel;
+					addr.kind = lbAddr_Context;
+					return addr;
+				} else if (addr.kind == lbAddr_SoaVariable) {
+					lbValue index = addr.soa.index;
+					i32 first_index = sel.index[0];
+					Selection sub_sel = sel;
+					sub_sel.index.data += 1;
+					sub_sel.index.count -= 1;
+
+					lbValue arr = lb_emit_struct_ep(p, addr.addr, first_index);
+
+					Type *t = base_type(type_deref(addr.addr.type));
+					GB_ASSERT(is_type_soa_struct(t));
+
+					if (addr.soa.index_expr != nullptr && (!lb_is_const(addr.soa.index) || t->Struct.soa_kind != StructSoa_Fixed)) {
+						lbValue len = lb_soa_struct_len(p, addr.addr);
+						lb_emit_bounds_check(p, ast_token(addr.soa.index_expr), addr.soa.index, len);
 					}
 
+					lbValue item = {};
 
-					lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count);
-					lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
-					lb_emit_store(p, len_dst, new_len);
+					if (t->Struct.soa_kind == StructSoa_Fixed) {
+						item = lb_emit_array_ep(p, arr, index);
+					} else {
+						item = lb_emit_ptr_offset(p, lb_emit_load(p, arr), index);
+					}
+					if (sub_sel.index.count > 0) {
+						item = lb_emit_deep_field_gep(p, item, sub_sel);
+					}
+					return lb_addr(item);
+				} else if (addr.kind == lbAddr_Swizzle) {
+					GB_ASSERT(sel.index.count > 0);
+					// NOTE(bill): just patch the index in place
+					sel.index[0] = addr.swizzle.indices[sel.index[0]];
+				} else if (addr.kind == lbAddr_SwizzleLarge) {
+					GB_ASSERT(sel.index.count > 0);
+					// NOTE(bill): just patch the index in place
+					sel.index[0] = addr.swizzle.indices[sel.index[0]];
 				}
 
-				return dst;
-				#endif
+				lbValue a = lb_addr_get_ptr(p, addr);
+				a = lb_emit_deep_field_gep(p, a, sel);
+				return lb_addr(a);
 			}
-			break;
-
+		} else {
+			GB_PANIC("Unsupported selector expression");
 		}
+	case_end;
 
-		GB_PANIC("Unknown slicable type");
+	case_ast_node(se, SelectorCallExpr, expr);
+		lbValue e = lb_build_expr(p, expr);
+		return lb_addr(lb_address_from_load_or_generate_local(p, e));
 	case_end;
 
-	case_ast_node(de, DerefExpr, expr);
-		Type *t = type_of_expr(de->expr);
-		if (is_type_relative_pointer(t)) {
-			lbAddr addr = lb_build_addr(p, de->expr);
-			addr.relative.deref = true;
-			return addr;
-		} else if (is_type_soa_pointer(t)) {
-			lbValue value = lb_build_expr(p, de->expr);
-			lbValue ptr = lb_emit_struct_ev(p, value, 0);
-			lbValue idx = lb_emit_struct_ev(p, value, 1);
-			return lb_addr_soa_variable(ptr, idx, nullptr);
+	case_ast_node(ta, TypeAssertion, expr);
+		TokenPos pos = ast_token(expr).pos;
+		lbValue e = lb_build_expr(p, ta->expr);
+		Type *t = type_deref(e.type);
+		if (is_type_union(t)) {
+			Type *type = type_of_expr(expr);
+			lbAddr v = lb_add_local_generated(p, type, false);
+			lb_addr_store(p, v, lb_emit_union_cast(p, lb_build_expr(p, ta->expr), type, pos));
+			return v;
+		} else if (is_type_any(t)) {
+			Type *type = type_of_expr(expr);
+			return lb_emit_any_cast_addr(p, lb_build_expr(p, ta->expr), type, pos);
+		} else {
+			GB_PANIC("TODO(bill): type assertion %s", type_to_string(e.type));
 		}
-		lbValue addr = lb_build_expr(p, de->expr);
-		return lb_addr(addr);
 	case_end;
 
-	case_ast_node(ce, CallExpr, expr);
-		BuiltinProcId builtin_id = BuiltinProc_Invalid;
-		if (ce->proc->tav.mode == Addressing_Builtin) {
-			Entity *e = entity_of_node(ce->proc);
-			if (e != nullptr) {
-				builtin_id = cast(BuiltinProcId)e->Builtin.id;
-			} else {
-				builtin_id = BuiltinProc_DIRECTIVE;
-			}
+	case_ast_node(ue, UnaryExpr, expr);
+		switch (ue->op.kind) {
+		case Token_And: {
+			lbValue ptr = lb_build_expr(p, expr);
+			return lb_addr(lb_address_from_load_or_generate_local(p, ptr));
 		}
-		auto const &tv = expr->tav;
-		if (builtin_id == BuiltinProc_swizzle &&
-		    is_type_array(tv.type)) {
-		    	// NOTE(bill, 2021-08-09): `swizzle` has some bizarre semantics so it needs to be
-		    	// specialized here for to be addressable
-			return lb_build_array_swizzle_addr(p, ce, tv);
+		default:
+			GB_PANIC("Invalid unary expression for lb_build_addr");
 		}
-
-		// NOTE(bill): This is make sure you never need to have an 'array_ev'
-		lbValue e = lb_build_expr(p, expr);
-	#if 1
-		return lb_addr(lb_address_from_load_or_generate_local(p, e));
-	#else
-		lbAddr v = lb_add_local_generated(p, e.type, false);
-		lb_addr_store(p, v, e);
-		return v;
-	#endif
+	case_end;
+	case_ast_node(be, BinaryExpr, expr);
+		lbValue v = lb_build_expr(p, expr);
+		Type *t = v.type;
+		if (is_type_pointer(t)) {
+			return lb_addr(v);
+		}
+		return lb_addr(lb_address_from_load_or_generate_local(p, v));
 	case_end;
 
-	case_ast_node(cl, CompoundLit, expr);
-		Type *type = type_of_expr(expr);
-		Type *bt = base_type(type);
+	case_ast_node(ie, IndexExpr, expr);
+		Type *t = base_type(type_of_expr(ie->expr));
 
-		lbAddr v = lb_add_local_generated(p, type, true);
+		bool deref = is_type_pointer(t);
+		t = base_type(type_deref(t));
+		if (is_type_soa_struct(t)) {
+			// SOA STRUCTURES!!!!
+			lbValue val = lb_build_addr_ptr(p, ie->expr);
+			if (deref) {
+				val = lb_emit_load(p, val);
+			}
 
-		Type *et = nullptr;
-		switch (bt->kind) {
-		case Type_Array:           et = bt->Array.elem;           break;
-		case Type_EnumeratedArray: et = bt->EnumeratedArray.elem; break;
-		case Type_Slice:           et = bt->Slice.elem;           break;
-		case Type_BitSet:          et = bt->BitSet.elem;          break;
-		case Type_SimdVector:      et = bt->SimdVector.elem;      break;
-		case Type_Matrix:          et = bt->Matrix.elem;          break;
+			lbValue index = lb_build_expr(p, ie->index);
+			return lb_addr_soa_variable(val, index, ie->index);
 		}
 
-		String proc_name = {};
-		if (p->entity) {
-			proc_name = p->entity->token.string;
-		}
-		TokenPos pos = ast_token(expr).pos;
+		if (ie->expr->tav.mode == Addressing_SoaVariable) {
+			// SOA Structures for slices/dynamic arrays
+			GB_ASSERT(is_type_pointer(type_of_expr(ie->expr)));
 
-		switch (bt->kind) {
-		default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break;
-
-		case Type_Struct: {
-			// TODO(bill): "constant" '#raw_union's are not initialized constantly at the moment.
-			// NOTE(bill): This is due to the layout of the unions when printed to LLVM-IR
-			bool is_raw_union = is_type_raw_union(bt);
-			GB_ASSERT(is_type_struct(bt) || is_raw_union);
-			TypeStruct *st = &bt->Struct;
-			if (cl->elems.count > 0) {
-				lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
-				lbValue comp_lit_ptr = lb_addr_get_ptr(p, v);
-
-				for_array(field_index, cl->elems) {
-					Ast *elem = cl->elems[field_index];
-
-					lbValue field_expr = {};
-					Entity *field = nullptr;
-					isize index = field_index;
-
-					if (elem->kind == Ast_FieldValue) {
-						ast_node(fv, FieldValue, elem);
-						String name = fv->field->Ident.token.string;
-						Selection sel = lookup_field(bt, name, false);
-						index = sel.index[0];
-						elem = fv->value;
-						TypeAndValue tav = type_and_value_of_expr(elem);
-					} else {
-						TypeAndValue tav = type_and_value_of_expr(elem);
-						Selection sel = lookup_field_from_index(bt, st->fields[field_index]->Variable.field_index);
-						index = sel.index[0];
-					}
+			lbValue field = lb_build_expr(p, ie->expr);
+			lbValue index = lb_build_expr(p, ie->index);
 
-					field = st->fields[index];
-					Type *ft = field->type;
-					if (!is_raw_union && !is_type_typeid(ft) && lb_is_elem_const(elem, ft)) {
-						continue;
-					}
 
-					field_expr = lb_build_expr(p, elem);
+			if (!build_context.no_bounds_check) {
+				// TODO HACK(bill): Clean up this hack to get the length for bounds checking
+				// GB_ASSERT(LLVMIsALoadInst(field.value));
+
+				// lbValue a = {};
+				// a.value = LLVMGetOperand(field.value, 0);
+				// a.type = alloc_type_pointer(field.type);
+
+				// irInstr *b = &a->Instr;
+				// GB_ASSERT(b->kind == irInstr_StructElementPtr);
+				// lbValue base_struct = b->StructElementPtr.address;
+
+				// GB_ASSERT(is_type_soa_struct(type_deref(ir_type(base_struct))));
+				// lbValue len = ir_soa_struct_len(p, base_struct);
+				// lb_emit_bounds_check(p, ast_token(ie->index), index, len);
+			}
+			lbValue val = lb_emit_ptr_offset(p, field, index);
+			return lb_addr(val);
+		}
 
-					lbValue gep = {};
-					if (is_raw_union) {
-						gep = lb_emit_conv(p, comp_lit_ptr, alloc_type_pointer(ft));
-					} else {
-						gep = lb_emit_struct_ep(p, comp_lit_ptr, cast(i32)index);
-					}
+		GB_ASSERT_MSG(is_type_indexable(t), "%s %s", type_to_string(t), expr_to_string(expr));
 
-					Type *fet = field_expr.type;
-					GB_ASSERT(fet->kind != Type_Tuple);
+		if (is_type_map(t)) {
+			lbAddr map_addr = lb_build_addr(p, ie->expr);
+			lbValue map_val = lb_addr_load(p, map_addr);
+			if (deref) {
+				map_val = lb_emit_load(p, map_val);
+			}
 
-					// HACK TODO(bill): THIS IS A MASSIVE HACK!!!!
-					if (is_type_union(ft) && !are_types_identical(fet, ft) && !is_type_untyped(fet)) {
-						GB_ASSERT_MSG(union_variant_index(ft, fet) > 0, "%s", type_to_string(fet));
+			lbValue key = lb_build_expr(p, ie->index);
+			key = lb_emit_conv(p, key, t->Map.key);
 
-						lb_emit_store_union_variant(p, gep, field_expr, fet);
-					} else {
-						lbValue fv = lb_emit_conv(p, field_expr, ft);
-						lb_emit_store(p, gep, fv);
-					}
-				}
-			}
-			break;
+			Type *result_type = type_of_expr(expr);
+			lbValue map_ptr = lb_address_from_load_or_generate_local(p, map_val);
+			return lb_addr_map(map_ptr, key, t, result_type);
 		}
 
-		case Type_Map: {
-			if (cl->elems.count == 0) {
-				break;
-			}
-			{
-				auto args = array_make<lbValue>(permanent_allocator(), 3);
-				args[0] = lb_gen_map_header(p, v.addr, type);
-				args[1] = lb_const_int(p->module, t_int, 2*cl->elems.count);
-				args[2] = lb_emit_source_code_location(p, proc_name, pos);
-				lb_emit_runtime_call(p, "__dynamic_map_reserve", args);
+		switch (t->kind) {
+		case Type_Array: {
+			lbValue array = {};
+			array = lb_build_addr_ptr(p, ie->expr);
+			if (deref) {
+				array = lb_emit_load(p, array);
 			}
-			for_array(field_index, cl->elems) {
-				Ast *elem = cl->elems[field_index];
-				ast_node(fv, FieldValue, elem);
+			lbValue index = lb_build_expr(p, ie->index);
+			index = lb_emit_conv(p, index, t_int);
+			lbValue elem = lb_emit_array_ep(p, array, index);
 
-				lbValue key   = lb_build_expr(p, fv->field);
-				lbValue value = lb_build_expr(p, fv->value);
-				lb_insert_dynamic_map_key_and_value(p, v, type, key, value, elem);
+			auto index_tv = type_and_value_of_expr(ie->index);
+			if (index_tv.mode != Addressing_Constant) {
+				lbValue len = lb_const_int(p->module, t_int, t->Array.count);
+				lb_emit_bounds_check(p, ast_token(ie->index), index, len);
 			}
-			break;
+			return lb_addr(elem);
 		}
 
-		case Type_Array: {
-			if (cl->elems.count > 0) {
-				lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
-
-				auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
-
-				// NOTE(bill): Separate value, gep, store into their own chunks
-				for_array(i, cl->elems) {
-					Ast *elem = cl->elems[i];
-					if (elem->kind == Ast_FieldValue) {
-						ast_node(fv, FieldValue, elem);
-						if (lb_is_elem_const(fv->value, et)) {
-							continue;
-						}
-						if (is_ast_range(fv->field)) {
-							ast_node(ie, BinaryExpr, fv->field);
-							TypeAndValue lo_tav = ie->left->tav;
-							TypeAndValue hi_tav = ie->right->tav;
-							GB_ASSERT(lo_tav.mode == Addressing_Constant);
-							GB_ASSERT(hi_tav.mode == Addressing_Constant);
-
-							TokenKind op = ie->op.kind;
-							i64 lo = exact_value_to_i64(lo_tav.value);
-							i64 hi = exact_value_to_i64(hi_tav.value);
-							if (op != Token_RangeHalf) {
-								hi += 1;
-							}
-
-							lbValue value = lb_build_expr(p, fv->value);
-
-							for (i64 k = lo; k < hi; k++) {
-								lbCompoundLitElemTempData data = {};
-								data.value = value;
-								data.elem_index = cast(i32)k;
-								array_add(&temp_data, data);
-							}
-
-						} else {
-							auto tav = fv->field->tav;
-							GB_ASSERT(tav.mode == Addressing_Constant);
-							i64 index = exact_value_to_i64(tav.value);
+		case Type_EnumeratedArray: {
+			lbValue array = {};
+			array = lb_build_addr_ptr(p, ie->expr);
+			if (deref) {
+				array = lb_emit_load(p, array);
+			}
 
-							lbValue value = lb_build_expr(p, fv->value);
-							lbCompoundLitElemTempData data = {};
-							data.value = lb_emit_conv(p, value, et);
-							data.expr = fv->value;
-							data.elem_index = cast(i32)index;
-							array_add(&temp_data, data);
-						}
+			Type *index_type = t->EnumeratedArray.index;
 
-					} else {
-						if (lb_is_elem_const(elem, et)) {
-							continue;
-						}
-						lbCompoundLitElemTempData data = {};
-						data.expr = elem;
-						data.elem_index = cast(i32)i;
-						array_add(&temp_data, data);
-					}
-				}
+			auto index_tv = type_and_value_of_expr(ie->index);
 
-				for_array(i, temp_data) {
-					temp_data[i].gep = lb_emit_array_epi(p, lb_addr_get_ptr(p, v), temp_data[i].elem_index);
+			lbValue index = {};
+			if (compare_exact_values(Token_NotEq, *t->EnumeratedArray.min_value, exact_value_i64(0))) {
+				if (index_tv.mode == Addressing_Constant) {
+					ExactValue idx = exact_value_sub(index_tv.value, *t->EnumeratedArray.min_value);
+					index = lb_const_value(p->module, index_type, idx);
+				} else {
+					index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
+					index = lb_emit_arith(p, Token_Sub, index, lb_const_value(p->module, index_type, *t->EnumeratedArray.min_value), index_type);
 				}
+			} else {
+				index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
+			}
 
-				for_array(i, temp_data) {
-					lbValue field_expr = temp_data[i].value;
-					Ast *expr = temp_data[i].expr;
+			lbValue elem = lb_emit_array_ep(p, array, index);
 
-					auto prev_hint = lb_set_copy_elision_hint(p, lb_addr(temp_data[i].gep), expr);
+			if (index_tv.mode != Addressing_Constant) {
+				lbValue len = lb_const_int(p->module, t_int, t->EnumeratedArray.count);
+				lb_emit_bounds_check(p, ast_token(ie->index), index, len);
+			}
+			return lb_addr(elem);
+		}
 
-					if (field_expr.value == nullptr) {
-						field_expr = lb_build_expr(p, expr);
-					}
-					Type *t = field_expr.type;
-					GB_ASSERT(t->kind != Type_Tuple);
-					lbValue ev = lb_emit_conv(p, field_expr, et);
+		case Type_Slice: {
+			lbValue slice = {};
+			slice = lb_build_expr(p, ie->expr);
+			if (deref) {
+				slice = lb_emit_load(p, slice);
+			}
+			lbValue elem = lb_slice_elem(p, slice);
+			lbValue index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
+			lbValue len = lb_slice_len(p, slice);
+			lb_emit_bounds_check(p, ast_token(ie->index), index, len);
+			lbValue v = lb_emit_ptr_offset(p, elem, index);
+			return lb_addr(v);
+		}
 
-					if (!p->copy_elision_hint.used) {
-						temp_data[i].value = ev;
-					}
+		case Type_MultiPointer: {
+			lbValue multi_ptr = {};
+			multi_ptr = lb_build_expr(p, ie->expr);
+			if (deref) {
+				multi_ptr = lb_emit_load(p, multi_ptr);
+			}
+			lbValue index = lb_build_expr(p, ie->index);
+			lbValue v = {};
 
-					lb_reset_copy_elision_hint(p, prev_hint);
-				}
+			LLVMValueRef indices[1] = {index.value};
+			v.value = LLVMBuildGEP2(p->builder, lb_type(p->module, t->MultiPointer.elem), multi_ptr.value, indices, 1, "foo");
+			v.type = alloc_type_pointer(t->MultiPointer.elem);
+			return lb_addr(v);
+		}
 
-				for_array(i, temp_data) {
-					if (temp_data[i].value.value != nullptr) {
-						lb_emit_store(p, temp_data[i].gep, temp_data[i].value);
-					}
-				}
+		case Type_RelativeSlice: {
+			lbAddr slice_addr = {};
+			if (deref) {
+				slice_addr = lb_addr(lb_build_expr(p, ie->expr));
+			} else {
+				slice_addr = lb_build_addr(p, ie->expr);
 			}
-			break;
-		}
-		case Type_EnumeratedArray: {
-			if (cl->elems.count > 0) {
-				lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
-
-				auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
-
-				// NOTE(bill): Separate value, gep, store into their own chunks
-				for_array(i, cl->elems) {
-					Ast *elem = cl->elems[i];
-					if (elem->kind == Ast_FieldValue) {
-						ast_node(fv, FieldValue, elem);
-						if (lb_is_elem_const(fv->value, et)) {
-							continue;
-						}
-						if (is_ast_range(fv->field)) {
-							ast_node(ie, BinaryExpr, fv->field);
-							TypeAndValue lo_tav = ie->left->tav;
-							TypeAndValue hi_tav = ie->right->tav;
-							GB_ASSERT(lo_tav.mode == Addressing_Constant);
-							GB_ASSERT(hi_tav.mode == Addressing_Constant);
-
-							TokenKind op = ie->op.kind;
-							i64 lo = exact_value_to_i64(lo_tav.value);
-							i64 hi = exact_value_to_i64(hi_tav.value);
-							if (op != Token_RangeHalf) {
-								hi += 1;
-							}
-
-							lbValue value = lb_build_expr(p, fv->value);
-
-							for (i64 k = lo; k < hi; k++) {
-								lbCompoundLitElemTempData data = {};
-								data.value = value;
-								data.elem_index = cast(i32)k;
-								array_add(&temp_data, data);
-							}
+			lbValue slice = lb_addr_load(p, slice_addr);
 
-						} else {
-							auto tav = fv->field->tav;
-							GB_ASSERT(tav.mode == Addressing_Constant);
-							i64 index = exact_value_to_i64(tav.value);
+			lbValue elem = lb_slice_elem(p, slice);
+			lbValue index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
+			lbValue len = lb_slice_len(p, slice);
+			lb_emit_bounds_check(p, ast_token(ie->index), index, len);
+			lbValue v = lb_emit_ptr_offset(p, elem, index);
+			return lb_addr(v);
+		}
 
-							lbValue value = lb_build_expr(p, fv->value);
-							lbCompoundLitElemTempData data = {};
-							data.value = lb_emit_conv(p, value, et);
-							data.expr = fv->value;
-							data.elem_index = cast(i32)index;
-							array_add(&temp_data, data);
-						}
+		case Type_DynamicArray: {
+			lbValue dynamic_array = {};
+			dynamic_array = lb_build_expr(p, ie->expr);
+			if (deref) {
+				dynamic_array = lb_emit_load(p, dynamic_array);
+			}
+			lbValue elem = lb_dynamic_array_elem(p, dynamic_array);
+			lbValue len = lb_dynamic_array_len(p, dynamic_array);
+			lbValue index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
+			lb_emit_bounds_check(p, ast_token(ie->index), index, len);
+			lbValue v = lb_emit_ptr_offset(p, elem, index);
+			return lb_addr(v);
+		}
 
-					} else {
-						if (lb_is_elem_const(elem, et)) {
-							continue;
-						}
-						lbCompoundLitElemTempData data = {};
-						data.expr = elem;
-						data.elem_index = cast(i32)i;
-						array_add(&temp_data, data);
-					}
-				}
+		case Type_Matrix: {
+			lbValue matrix = {};
+			matrix = lb_build_addr_ptr(p, ie->expr);
+			if (deref) {
+				matrix = lb_emit_load(p, matrix);
+			}
+			lbValue index = lb_build_expr(p, ie->index);
+			index = lb_emit_conv(p, index, t_int);
+			lbValue elem = lb_emit_matrix_ep(p, matrix, lb_const_int(p->module, t_int, 0), index);
+			elem = lb_emit_conv(p, elem, alloc_type_pointer(type_of_expr(expr)));
 
+			auto index_tv = type_and_value_of_expr(ie->index);
+			if (index_tv.mode != Addressing_Constant) {
+				lbValue len = lb_const_int(p->module, t_int, t->Matrix.column_count);
+				lb_emit_bounds_check(p, ast_token(ie->index), index, len);
+			}
+			return lb_addr(elem);
+		}
 
-				i32 index_offset = cast(i32)exact_value_to_i64(*bt->EnumeratedArray.min_value);
 
-				for_array(i, temp_data) {
-					i32 index = temp_data[i].elem_index - index_offset;
-					temp_data[i].gep = lb_emit_array_epi(p, lb_addr_get_ptr(p, v), index);
-				}
+		case Type_Basic: { // Basic_string
+			lbValue str;
+			lbValue elem;
+			lbValue len;
+			lbValue index;
 
-				for_array(i, temp_data) {
-					lbValue field_expr = temp_data[i].value;
-					Ast *expr = temp_data[i].expr;
+			str = lb_build_expr(p, ie->expr);
+			if (deref) {
+				str = lb_emit_load(p, str);
+			}
+			elem = lb_string_elem(p, str);
+			len = lb_string_len(p, str);
 
-					auto prev_hint = lb_set_copy_elision_hint(p, lb_addr(temp_data[i].gep), expr);
+			index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int);
+			lb_emit_bounds_check(p, ast_token(ie->index), index, len);
 
-					if (field_expr.value == nullptr) {
-						field_expr = lb_build_expr(p, expr);
-					}
-					Type *t = field_expr.type;
-					GB_ASSERT(t->kind != Type_Tuple);
-					lbValue ev = lb_emit_conv(p, field_expr, et);
+			return lb_addr(lb_emit_ptr_offset(p, elem, index));
+		}
+		}
+	case_end;
 
-					if (!p->copy_elision_hint.used) {
-						temp_data[i].value = ev;
-					}
+	case_ast_node(ie, MatrixIndexExpr, expr);
+		Type *t = base_type(type_of_expr(ie->expr));
 
-					lb_reset_copy_elision_hint(p, prev_hint);
-				}
+		bool deref = is_type_pointer(t);
+		t = base_type(type_deref(t));
 
-				for_array(i, temp_data) {
-					if (temp_data[i].value.value != nullptr) {
-						lb_emit_store(p, temp_data[i].gep, temp_data[i].value);
-					}
-				}
-			}
-			break;
+		lbValue m = {};
+		m = lb_build_addr_ptr(p, ie->expr);
+		if (deref) {
+			m = lb_emit_load(p, m);
 		}
-		case Type_Slice: {
-			if (cl->elems.count > 0) {
-				lbValue slice = lb_const_value(p->module, type, exact_value_compound(expr));
-
-				lbValue data = lb_slice_elem(p, slice);
+		lbValue row_index = lb_build_expr(p, ie->row_index);
+		lbValue column_index = lb_build_expr(p, ie->column_index);
+		row_index = lb_emit_conv(p, row_index, t_int);
+		column_index = lb_emit_conv(p, column_index, t_int);
+		lbValue elem = lb_emit_matrix_ep(p, m, row_index, column_index);
 
-				auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
+		auto row_index_tv = type_and_value_of_expr(ie->row_index);
+		auto column_index_tv = type_and_value_of_expr(ie->column_index);
+		if (row_index_tv.mode != Addressing_Constant || column_index_tv.mode != Addressing_Constant) {
+			lbValue row_count = lb_const_int(p->module, t_int, t->Matrix.row_count);
+			lbValue column_count = lb_const_int(p->module, t_int, t->Matrix.column_count);
+			lb_emit_matrix_bounds_check(p, ast_token(ie->row_index), row_index, column_index, row_count, column_count);
+		}
+		return lb_addr(elem);
 
-				for_array(i, cl->elems) {
-					Ast *elem = cl->elems[i];
-					if (elem->kind == Ast_FieldValue) {
-						ast_node(fv, FieldValue, elem);
 
-						if (lb_is_elem_const(fv->value, et)) {
-							continue;
-						}
+	case_end;
 
-						if (is_ast_range(fv->field)) {
-							ast_node(ie, BinaryExpr, fv->field);
-							TypeAndValue lo_tav = ie->left->tav;
-							TypeAndValue hi_tav = ie->right->tav;
-							GB_ASSERT(lo_tav.mode == Addressing_Constant);
-							GB_ASSERT(hi_tav.mode == Addressing_Constant);
-
-							TokenKind op = ie->op.kind;
-							i64 lo = exact_value_to_i64(lo_tav.value);
-							i64 hi = exact_value_to_i64(hi_tav.value);
-							if (op != Token_RangeHalf) {
-								hi += 1;
-							}
-
-							lbValue value = lb_emit_conv(p, lb_build_expr(p, fv->value), et);
-
-							for (i64 k = lo; k < hi; k++) {
-								lbCompoundLitElemTempData data = {};
-								data.value = value;
-								data.elem_index = cast(i32)k;
-								array_add(&temp_data, data);
-							}
+	case_ast_node(se, SliceExpr, expr);
 
-						} else {
-							GB_ASSERT(fv->field->tav.mode == Addressing_Constant);
-							i64 index = exact_value_to_i64(fv->field->tav.value);
+		lbValue low  = lb_const_int(p->module, t_int, 0);
+		lbValue high = {};
 
-							lbValue field_expr = lb_build_expr(p, fv->value);
-							GB_ASSERT(!is_type_tuple(field_expr.type));
+		if (se->low  != nullptr) {
+			low = lb_correct_endianness(p, lb_build_expr(p, se->low));
+		}
+		if (se->high != nullptr) {
+			high = lb_correct_endianness(p, lb_build_expr(p, se->high));
+		}
 
-							lbValue ev = lb_emit_conv(p, field_expr, et);
+		bool no_indices = se->low == nullptr && se->high == nullptr;
 
-							lbCompoundLitElemTempData data = {};
-							data.value = ev;
-							data.elem_index = cast(i32)index;
-							array_add(&temp_data, data);
-						}
-					} else {
-						if (lb_is_elem_const(elem, et)) {
-							continue;
-						}
-						lbValue field_expr = lb_build_expr(p, elem);
-						GB_ASSERT(!is_type_tuple(field_expr.type));
+		lbAddr addr = lb_build_addr(p, se->expr);
+		lbValue base = lb_addr_load(p, addr);
+		Type *type = base_type(base.type);
 
-						lbValue ev = lb_emit_conv(p, field_expr, et);
+		if (is_type_pointer(type)) {
+			type = base_type(type_deref(type));
+			addr = lb_addr(base);
+			base = lb_addr_load(p, addr);
+		}
 
-						lbCompoundLitElemTempData data = {};
-						data.value = ev;
-						data.elem_index = cast(i32)i;
-						array_add(&temp_data, data);
-					}
-				}
+		switch (type->kind) {
+		case Type_Slice: {
+			Type *slice_type = type;
+			lbValue len = lb_slice_len(p, base);
+			if (high.value == nullptr) high = len;
 
-				for_array(i, temp_data) {
-					temp_data[i].gep = lb_emit_ptr_offset(p, data, lb_const_int(p->module, t_int, temp_data[i].elem_index));
-				}
+			if (!no_indices) {
+				lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
+			}
 
-				for_array(i, temp_data) {
-					lb_emit_store(p, temp_data[i].gep, temp_data[i].value);
-				}
+			lbValue elem    = lb_emit_ptr_offset(p, lb_slice_elem(p, base), low);
+			lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
 
-				{
-					lbValue count = {};
-					count.type = t_int;
+			lbAddr slice = lb_add_local_generated(p, slice_type, false);
+			lb_fill_slice(p, slice, elem, new_len);
+			return slice;
+		}
 
-					if (lb_is_const(slice)) {
-						unsigned indices[1] = {1};
-						count.value = LLVMConstExtractValue(slice.value, indices, gb_count_of(indices));
-					} else {
-						count.value = LLVMBuildExtractValue(p->builder, slice.value, 1, "");
-					}
-					lb_fill_slice(p, v, data, count);
-				}
-			}
+		case Type_RelativeSlice:
+			GB_PANIC("TODO(bill): Type_RelativeSlice should be handled above already on the lb_addr_load");
 			break;
-		}
 
 		case Type_DynamicArray: {
-			if (cl->elems.count == 0) {
-				break;
-			}
-			Type *et = bt->DynamicArray.elem;
-			lbValue size  = lb_const_int(p->module, t_int, type_size_of(et));
-			lbValue align = lb_const_int(p->module, t_int, type_align_of(et));
+			Type *elem_type = type->DynamicArray.elem;
+			Type *slice_type = alloc_type_slice(elem_type);
 
-			i64 item_count = gb_max(cl->max_count, cl->elems.count);
-			{
+			lbValue len = lb_dynamic_array_len(p, base);
+			if (high.value == nullptr) high = len;
 
-				auto args = array_make<lbValue>(permanent_allocator(), 5);
-				args[0] = lb_emit_conv(p, lb_addr_get_ptr(p, v), t_rawptr);
-				args[1] = size;
-				args[2] = align;
-				args[3] = lb_const_int(p->module, t_int, 2*item_count); // TODO(bill): Is this too much waste?
-				args[4] = lb_emit_source_code_location(p, proc_name, pos);
-				lb_emit_runtime_call(p, "__dynamic_array_reserve", args);
+			if (!no_indices) {
+				lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
 			}
 
-			lbValue items = lb_generate_local_array(p, et, item_count);
-			// lbValue items = lb_generate_global_array(p->module, et, item_count, str_lit("dacl$"), cast(i64)cast(intptr)expr);
-
-			for_array(i, cl->elems) {
-				Ast *elem = cl->elems[i];
-				if (elem->kind == Ast_FieldValue) {
-					ast_node(fv, FieldValue, elem);
-					if (is_ast_range(fv->field)) {
-						ast_node(ie, BinaryExpr, fv->field);
-						TypeAndValue lo_tav = ie->left->tav;
-						TypeAndValue hi_tav = ie->right->tav;
-						GB_ASSERT(lo_tav.mode == Addressing_Constant);
-						GB_ASSERT(hi_tav.mode == Addressing_Constant);
-
-						TokenKind op = ie->op.kind;
-						i64 lo = exact_value_to_i64(lo_tav.value);
-						i64 hi = exact_value_to_i64(hi_tav.value);
-						if (op != Token_RangeHalf) {
-							hi += 1;
-						}
+			lbValue elem    = lb_emit_ptr_offset(p, lb_dynamic_array_elem(p, base), low);
+			lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
 
-						lbValue value = lb_emit_conv(p, lb_build_expr(p, fv->value), et);
+			lbAddr slice = lb_add_local_generated(p, slice_type, false);
+			lb_fill_slice(p, slice, elem, new_len);
+			return slice;
+		}
 
-						for (i64 k = lo; k < hi; k++) {
-							lbValue ep = lb_emit_array_epi(p, items, cast(i32)k);
-							lb_emit_store(p, ep, value);
-						}
-					} else {
-						GB_ASSERT(fv->field->tav.mode == Addressing_Constant);
+		case Type_MultiPointer: {
+			lbAddr res = lb_add_local_generated(p, type_of_expr(expr), false);
+			if (se->high == nullptr) {
+				lbValue offset = base;
+				LLVMValueRef indices[1] = {low.value};
+				offset.value = LLVMBuildGEP2(p->builder, lb_type(p->module, offset.type->MultiPointer.elem), offset.value, indices, 1, "");
+				lb_addr_store(p, res, offset);
+			} else {
+				low = lb_emit_conv(p, low, t_int);
+				high = lb_emit_conv(p, high, t_int);
 
-						i64 field_index = exact_value_to_i64(fv->field->tav.value);
+				lb_emit_multi_pointer_slice_bounds_check(p, se->open, low, high);
 
-						lbValue ev = lb_build_expr(p, fv->value);
-						lbValue value = lb_emit_conv(p, ev, et);
-						lbValue ep = lb_emit_array_epi(p, items, cast(i32)field_index);
-						lb_emit_store(p, ep, value);
-					}
-				} else {
-					lbValue value = lb_emit_conv(p, lb_build_expr(p, elem), et);
-					lbValue ep = lb_emit_array_epi(p, items, cast(i32)i);
-					lb_emit_store(p, ep, value);
-				}
-			}
+				LLVMValueRef indices[1] = {low.value};
+				LLVMValueRef ptr = LLVMBuildGEP2(p->builder, lb_type(p->module, base.type->MultiPointer.elem), base.value, indices, 1, "");
+				LLVMValueRef len = LLVMBuildSub(p->builder, high.value, low.value, "");
 
-			{
-				auto args = array_make<lbValue>(permanent_allocator(), 6);
-				args[0] = lb_emit_conv(p, v.addr, t_rawptr);
-				args[1] = size;
-				args[2] = align;
-				args[3] = lb_emit_conv(p, items, t_rawptr);
-				args[4] = lb_const_int(p->module, t_int, item_count);
-				args[5] = lb_emit_source_code_location(p, proc_name, pos);
-				lb_emit_runtime_call(p, "__dynamic_array_append", args);
+				LLVMValueRef gep0 = lb_emit_struct_ep(p, res.addr, 0).value;
+				LLVMValueRef gep1 = lb_emit_struct_ep(p, res.addr, 1).value;
+				LLVMBuildStore(p->builder, ptr, gep0);
+				LLVMBuildStore(p->builder, len, gep1);
 			}
-			break;
+			return res;
 		}
 
-		case Type_Basic: {
-			GB_ASSERT(is_type_any(bt));
-			if (cl->elems.count > 0) {
-				lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
-				String field_names[2] = {
-					str_lit("data"),
-					str_lit("id"),
-				};
-				Type *field_types[2] = {
-					t_rawptr,
-					t_typeid,
-				};
-
-				for_array(field_index, cl->elems) {
-					Ast *elem = cl->elems[field_index];
-
-					lbValue field_expr = {};
-					isize index = field_index;
-
-					if (elem->kind == Ast_FieldValue) {
-						ast_node(fv, FieldValue, elem);
-						Selection sel = lookup_field(bt, fv->field->Ident.token.string, false);
-						index = sel.index[0];
-						elem = fv->value;
-					} else {
-						TypeAndValue tav = type_and_value_of_expr(elem);
-						Selection sel = lookup_field(bt, field_names[field_index], false);
-						index = sel.index[0];
-					}
+		case Type_Array: {
+			Type *slice_type = alloc_type_slice(type->Array.elem);
+			lbValue len = lb_const_int(p->module, t_int, type->Array.count);
 
-					field_expr = lb_build_expr(p, elem);
+			if (high.value == nullptr) high = len;
 
-					GB_ASSERT(field_expr.type->kind != Type_Tuple);
+			bool low_const  = type_and_value_of_expr(se->low).mode  == Addressing_Constant;
+			bool high_const = type_and_value_of_expr(se->high).mode == Addressing_Constant;
 
-					Type *ft = field_types[index];
-					lbValue fv = lb_emit_conv(p, field_expr, ft);
-					lbValue gep = lb_emit_struct_ep(p, lb_addr_get_ptr(p, v), cast(i32)index);
-					lb_emit_store(p, gep, fv);
+			if (!low_const || !high_const) {
+				if (!no_indices) {
+					lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
 				}
 			}
+			lbValue elem    = lb_emit_ptr_offset(p, lb_array_elem(p, lb_addr_get_ptr(p, addr)), low);
+			lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
 
-			break;
+			lbAddr slice = lb_add_local_generated(p, slice_type, false);
+			lb_fill_slice(p, slice, elem, new_len);
+			return slice;
 		}
 
-		case Type_BitSet: {
-			i64 sz = type_size_of(type);
-			if (cl->elems.count > 0 && sz > 0) {
-				lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
-
-				lbValue lower = lb_const_value(p->module, t_int, exact_value_i64(bt->BitSet.lower));
-				for_array(i, cl->elems) {
-					Ast *elem = cl->elems[i];
-					GB_ASSERT(elem->kind != Ast_FieldValue);
-
-					if (lb_is_elem_const(elem, et)) {
-						continue;
-					}
+		case Type_Basic: {
+			GB_ASSERT(type == t_string);
+			lbValue len = lb_string_len(p, base);
+			if (high.value == nullptr) high = len;
 
-					lbValue expr = lb_build_expr(p, elem);
-					GB_ASSERT(expr.type->kind != Type_Tuple);
+			if (!no_indices) {
+				lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
+			}
 
-					Type *it = bit_set_to_int(bt);
-					lbValue one = lb_const_value(p->module, it, exact_value_i64(1));
-					lbValue e = lb_emit_conv(p, expr, it);
-					e = lb_emit_arith(p, Token_Sub, e, lower, it);
-					e = lb_emit_arith(p, Token_Shl, one, e, it);
+			lbValue elem    = lb_emit_ptr_offset(p, lb_string_elem(p, base), low);
+			lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
 
-					lbValue old_value = lb_emit_transmute(p, lb_addr_load(p, v), it);
-					lbValue new_value = lb_emit_arith(p, Token_Or, old_value, e, it);
-					new_value = lb_emit_transmute(p, new_value, type);
-					lb_addr_store(p, v, new_value);
-				}
-			}
-			break;
+			lbAddr str = lb_add_local_generated(p, t_string, false);
+			lb_fill_string(p, str, elem, new_len);
+			return str;
 		}
-		
-		case Type_Matrix: {
-			if (cl->elems.count > 0) {
-				lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
-
-				auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
-
-				// NOTE(bill): Separate value, gep, store into their own chunks
-				for_array(i, cl->elems) {
-					Ast *elem = cl->elems[i];
-					
-					if (elem->kind == Ast_FieldValue) {
-						ast_node(fv, FieldValue, elem);
-						if (lb_is_elem_const(fv->value, et)) {
-							continue;
-						}
-						if (is_ast_range(fv->field)) {
-							ast_node(ie, BinaryExpr, fv->field);
-							TypeAndValue lo_tav = ie->left->tav;
-							TypeAndValue hi_tav = ie->right->tav;
-							GB_ASSERT(lo_tav.mode == Addressing_Constant);
-							GB_ASSERT(hi_tav.mode == Addressing_Constant);
-
-							TokenKind op = ie->op.kind;
-							i64 lo = exact_value_to_i64(lo_tav.value);
-							i64 hi = exact_value_to_i64(hi_tav.value);
-							if (op != Token_RangeHalf) {
-								hi += 1;
-							}
-
-							lbValue value = lb_build_expr(p, fv->value);
-
-							for (i64 k = lo; k < hi; k++) {
-								lbCompoundLitElemTempData data = {};
-								data.value = value;
-								
-								data.elem_index = cast(i32)matrix_row_major_index_to_offset(bt, k);
-								array_add(&temp_data, data);
-							}
 
-						} else {
-							auto tav = fv->field->tav;
-							GB_ASSERT(tav.mode == Addressing_Constant);
-							i64 index = exact_value_to_i64(tav.value);
 
-							lbValue value = lb_build_expr(p, fv->value);
-							lbCompoundLitElemTempData data = {};
-							data.value = lb_emit_conv(p, value, et);
-							data.expr = fv->value;
-							
-							data.elem_index = cast(i32)matrix_row_major_index_to_offset(bt, index);
-							array_add(&temp_data, data);
-						}
+		case Type_Struct:
+			if (is_type_soa_struct(type)) {
+				lbValue len = lb_soa_struct_len(p, lb_addr_get_ptr(p, addr));
+				if (high.value == nullptr) high = len;
 
-					} else {
-						if (lb_is_elem_const(elem, et)) {
-							continue;
-						}
-						lbCompoundLitElemTempData data = {};
-						data.expr = elem;
-						data.elem_index = cast(i32)matrix_row_major_index_to_offset(bt, i);
-						array_add(&temp_data, data);
-					}
+				if (!no_indices) {
+					lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr);
 				}
+				#if 1
 
-				for_array(i, temp_data) {
-					temp_data[i].gep = lb_emit_array_epi(p, lb_addr_get_ptr(p, v), temp_data[i].elem_index);
-				}
+				lbAddr dst = lb_add_local_generated(p, type_of_expr(expr), true);
+				if (type->Struct.soa_kind == StructSoa_Fixed) {
+					i32 field_count = cast(i32)type->Struct.fields.count;
+					for (i32 i = 0; i < field_count; i++) {
+						lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i);
+						lbValue field_src = lb_emit_struct_ep(p, lb_addr_get_ptr(p, addr), i);
+						field_src = lb_emit_array_ep(p, field_src, low);
+						lb_emit_store(p, field_dst, field_src);
+					}
 
-				for_array(i, temp_data) {
-					lbValue field_expr = temp_data[i].value;
-					Ast *expr = temp_data[i].expr;
+					lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count);
+					lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
+					lb_emit_store(p, len_dst, new_len);
+				} else if (type->Struct.soa_kind == StructSoa_Slice) {
+					if (no_indices) {
+						lb_addr_store(p, dst, base);
+					} else {
+						i32 field_count = cast(i32)type->Struct.fields.count - 1;
+						for (i32 i = 0; i < field_count; i++) {
+							lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i);
+							lbValue field_src = lb_emit_struct_ev(p, base, i);
+							field_src = lb_emit_ptr_offset(p, field_src, low);
+							lb_emit_store(p, field_dst, field_src);
+						}
 
-					auto prev_hint = lb_set_copy_elision_hint(p, lb_addr(temp_data[i].gep), expr);
 
-					if (field_expr.value == nullptr) {
-						field_expr = lb_build_expr(p, expr);
+						lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count);
+						lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
+						lb_emit_store(p, len_dst, new_len);
 					}
-					Type *t = field_expr.type;
-					GB_ASSERT(t->kind != Type_Tuple);
-					lbValue ev = lb_emit_conv(p, field_expr, et);
-
-					if (!p->copy_elision_hint.used) {
-						temp_data[i].value = ev;
+				} else if (type->Struct.soa_kind == StructSoa_Dynamic) {
+					i32 field_count = cast(i32)type->Struct.fields.count - 3;
+					for (i32 i = 0; i < field_count; i++) {
+						lbValue field_dst = lb_emit_struct_ep(p, dst.addr, i);
+						lbValue field_src = lb_emit_struct_ev(p, base, i);
+						field_src = lb_emit_ptr_offset(p, field_src, low);
+						lb_emit_store(p, field_dst, field_src);
 					}
 
-					lb_reset_copy_elision_hint(p, prev_hint);
-				}
 
-				for_array(i, temp_data) {
-					if (temp_data[i].value.value != nullptr) {
-						lb_emit_store(p, temp_data[i].gep, temp_data[i].value);
-					}
+					lbValue len_dst = lb_emit_struct_ep(p, dst.addr, field_count);
+					lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int);
+					lb_emit_store(p, len_dst, new_len);
 				}
+
+				return dst;
+				#endif
 			}
 			break;
-		}
-		
-		case Type_SimdVector: {
-			if (cl->elems.count > 0) {
-				lbValue vector_value = lb_const_value(p->module, type, exact_value_compound(expr));
-				defer (lb_addr_store(p, v, vector_value));
-
-				auto temp_data = array_make<lbCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
-
-				// NOTE(bill): Separate value, store into their own chunks
-				for_array(i, cl->elems) {
-					Ast *elem = cl->elems[i];
-					if (elem->kind == Ast_FieldValue) {
-						ast_node(fv, FieldValue, elem);
-						if (lb_is_elem_const(fv->value, et)) {
-							continue;
-						}
-						if (is_ast_range(fv->field)) {
-							ast_node(ie, BinaryExpr, fv->field);
-							TypeAndValue lo_tav = ie->left->tav;
-							TypeAndValue hi_tav = ie->right->tav;
-							GB_ASSERT(lo_tav.mode == Addressing_Constant);
-							GB_ASSERT(hi_tav.mode == Addressing_Constant);
-
-							TokenKind op = ie->op.kind;
-							i64 lo = exact_value_to_i64(lo_tav.value);
-							i64 hi = exact_value_to_i64(hi_tav.value);
-							if (op != Token_RangeHalf) {
-								hi += 1;
-							}
-
-							lbValue value = lb_build_expr(p, fv->value);
-
-							for (i64 k = lo; k < hi; k++) {
-								lbCompoundLitElemTempData data = {};
-								data.value = value;
-								data.elem_index = cast(i32)k;
-								array_add(&temp_data, data);
-							}
-
-						} else {
-							auto tav = fv->field->tav;
-							GB_ASSERT(tav.mode == Addressing_Constant);
-							i64 index = exact_value_to_i64(tav.value);
-
-							lbValue value = lb_build_expr(p, fv->value);
-							lbCompoundLitElemTempData data = {};
-							data.value = lb_emit_conv(p, value, et);
-							data.expr = fv->value;
-							data.elem_index = cast(i32)index;
-							array_add(&temp_data, data);
-						}
-
-					} else {
-						if (lb_is_elem_const(elem, et)) {
-							continue;
-						}
-						lbCompoundLitElemTempData data = {};
-						data.expr = elem;
-						data.elem_index = cast(i32)i;
-						array_add(&temp_data, data);
-					}
-				}
-
-
-				for_array(i, temp_data) {
-					lbValue field_expr = temp_data[i].value;
-					Ast *expr = temp_data[i].expr;
-
-					auto prev_hint = lb_set_copy_elision_hint(p, lb_addr(temp_data[i].gep), expr);
-
-					if (field_expr.value == nullptr) {
-						field_expr = lb_build_expr(p, expr);
-					}
-					Type *t = field_expr.type;
-					GB_ASSERT(t->kind != Type_Tuple);
-					lbValue ev = lb_emit_conv(p, field_expr, et);
-
-					if (!p->copy_elision_hint.used) {
-						temp_data[i].value = ev;
-					}
 
-					lb_reset_copy_elision_hint(p, prev_hint);
-				}
+		}
 
+		GB_PANIC("Unknown slicable type");
+	case_end;
 
-				// TODO(bill): reduce the need for individual `insertelement` if a `shufflevector`
-				// might be a better option
+	case_ast_node(de, DerefExpr, expr);
+		Type *t = type_of_expr(de->expr);
+		if (is_type_relative_pointer(t)) {
+			lbAddr addr = lb_build_addr(p, de->expr);
+			addr.relative.deref = true;
+			return addr;
+		} else if (is_type_soa_pointer(t)) {
+			lbValue value = lb_build_expr(p, de->expr);
+			lbValue ptr = lb_emit_struct_ev(p, value, 0);
+			lbValue idx = lb_emit_struct_ev(p, value, 1);
+			return lb_addr_soa_variable(ptr, idx, nullptr);
+		}
+		lbValue addr = lb_build_expr(p, de->expr);
+		return lb_addr(addr);
+	case_end;
 
-				for_array(i, temp_data) {
-					if (temp_data[i].value.value != nullptr) {
-						LLVMValueRef index = lb_const_int(p->module, t_u32, temp_data[i].elem_index).value;
-						vector_value.value = LLVMBuildInsertElement(p->builder, vector_value.value, temp_data[i].value.value, index, "");
-					}
-				}
+	case_ast_node(ce, CallExpr, expr);
+		BuiltinProcId builtin_id = BuiltinProc_Invalid;
+		if (ce->proc->tav.mode == Addressing_Builtin) {
+			Entity *e = entity_of_node(ce->proc);
+			if (e != nullptr) {
+				builtin_id = cast(BuiltinProcId)e->Builtin.id;
+			} else {
+				builtin_id = BuiltinProc_DIRECTIVE;
 			}
-			break;
 		}
+		auto const &tv = expr->tav;
+		if (builtin_id == BuiltinProc_swizzle &&
+		    is_type_array(tv.type)) {
+		    	// NOTE(bill, 2021-08-09): `swizzle` has some bizarre semantics so it needs to be
+		    	// specialized here for to be addressable
+			return lb_build_array_swizzle_addr(p, ce, tv);
 		}
 
+		// NOTE(bill): This is make sure you never need to have an 'array_ev'
+		lbValue e = lb_build_expr(p, expr);
+	#if 1
+		return lb_addr(lb_address_from_load_or_generate_local(p, e));
+	#else
+		lbAddr v = lb_add_local_generated(p, e.type, false);
+		lb_addr_store(p, v, e);
 		return v;
+	#endif
+	case_end;
+
+	case_ast_node(cl, CompoundLit, expr);
+		return lb_build_addr_compound_lit(p, expr);
 	case_end;
 
 	case_ast_node(tc, TypeCast, expr);

+ 2 - 1
src/llvm_backend_general.cpp

@@ -175,7 +175,8 @@ struct lbLoopData {
 struct lbCompoundLitElemTempData {
 	Ast *   expr;
 	lbValue value;
-	i32     elem_index;
+	i64     elem_index;
+	i64     elem_length;
 	lbValue gep;
 };