Browse Source

Const Aggregate Literals for IR; Module path fix

Ginger Bill 9 years ago
parent
commit
17ab23f1f0
9 changed files with 305 additions and 142 deletions
  1. 1 9
      code/demo.odin
  2. 5 8
      core/os.odin
  3. 6 2
      src/checker/expr.cpp
  4. 1 0
      src/codegen/codegen.cpp
  5. 111 45
      src/codegen/print_llvm.cpp
  6. 152 66
      src/codegen/ssa.cpp
  7. 27 6
      src/common.cpp
  8. 1 2
      src/main.cpp
  9. 1 4
      src/parser.cpp

+ 1 - 9
code/demo.odin

@@ -2,16 +2,8 @@
 #import "utf8.odin"
 #import "hash.odin"
 #import "mem.odin"
-
-
+#import "game.odin"
 
 main :: proc() {
-	Vec3 :: struct {
-		x, y: i16
-		z: int
-	}
 
-	z := 123
-	v := Vec3{x = 4, y = 5, z = z}
-	fmt.println(v)
 }

+ 5 - 8
core/os.odin

@@ -43,19 +43,16 @@ File_Standard :: type enum {
 	COUNT,
 }
 
-__std_files := __set_file_standards();
+__std_files := [..]File{
+	File{handle = win32.GetStdHandle(win32.STD_INPUT_HANDLE)},
+	File{handle = win32.GetStdHandle(win32.STD_OUTPUT_HANDLE)},
+	File{handle = win32.GetStdHandle(win32.STD_ERROR_HANDLE)},
+}
 
 stdin  := ^__std_files[File_Standard.INPUT]
 stdout := ^__std_files[File_Standard.OUTPUT]
 stderr := ^__std_files[File_Standard.ERROR]
 
-__set_file_standards :: proc() -> [File_Standard.COUNT as int]File {
-	return [File_Standard.COUNT as int]File{
-		File{handle = win32.GetStdHandle(win32.STD_INPUT_HANDLE)},
-		File{handle = win32.GetStdHandle(win32.STD_OUTPUT_HANDLE)},
-		File{handle = win32.GetStdHandle(win32.STD_ERROR_HANDLE)},
-	}
-}
 
 
 read_entire_file :: proc(name: string) -> (string, bool) {

+ 6 - 2
src/checker/expr.cpp

@@ -3372,7 +3372,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 
 		} break;
 
-		// case Type_Slice:
+		case Type_Slice:
 		case Type_Array:
 		case Type_Vector:
 		{
@@ -3392,7 +3392,11 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 
 			i64 max = 0;
 			isize index = 0;
-			for (; index < gb_array_count(cl->elems); index++) {
+			isize elem_count = 0;
+			if (cl->elems != NULL) {
+				elem_count = gb_array_count(cl->elems);
+			}
+			for (; index < elem_count; index++) {
 				AstNode *e = cl->elems[index];
 				if (e->kind == AstNode_FieldValue) {
 					error(ast_node_token(e),

+ 1 - 0
src/codegen/codegen.cpp

@@ -278,6 +278,7 @@ void ssa_gen_tree(ssaGen *s) {
 		}
 
 		{ // NOTE(bill): Setup type_info data
+			// TODO(bill): Try and make a lot of this constant aggregate literals in LLVM IR
 			ssaValue *type_info_data = NULL;
 			ssaValue *type_info_member_data = NULL;
 

+ 111 - 45
src/codegen/print_llvm.cpp

@@ -263,7 +263,32 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
 	}
 }
 
-void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type_hint);
+void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Type *type);
+
+void ssa_print_compound_element(ssaFileBuffer *f, ssaModule *m, ExactValue v, Type *elem_type) {
+	if (v.kind == ExactValue_Invalid) {
+		ssa_fprintf(f, "zeroinitializer");
+	} else if (v.kind == ExactValue_String) {
+		// HACK NOTE(bill): This is a hack but it works because strings are created at the very end
+		// of the .ll file
+		ssaValue *str_array = ssa_add_global_string_array(m, v.value_string);
+
+		ssa_fprintf(f, "{i8* getelementptr inbounds (");
+		ssa_print_type(f, m, str_array->Global.entity->type);
+		ssa_fprintf(f, ", ");
+		ssa_print_type(f, m, str_array->Global.entity->type);
+		ssa_fprintf(f, "* ");
+		ssa_print_encoded_global(f, str_array->Global.entity->token.string, false);
+		ssa_fprintf(f, ", ");
+		ssa_print_type(f, m, t_int);
+		ssa_fprintf(f, " 0, i32 0), ");
+		ssa_print_type(f, m, t_int);
+		ssa_fprintf(f, " %lld}", cast(i64)v.value_string.len);
+
+	} else {
+		ssa_print_exact_value(f, m, v, elem_type);
+	}
+}
 
 void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Type *type) {
 	type = base_type(type);
@@ -324,14 +349,19 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
 		break;
 
 	case ExactValue_Compound: {
-		// ssa_fprintf(f, "%s", (value.value_bool ? "true" : "false"));
 		type = base_type(type);
 		if (is_type_array(type)) {
+			ast_node(cl, CompoundLit, value.value_compound);
+			isize elem_count = cl->elems != NULL ? gb_array_count(cl->elems) : 0;
+			if (elem_count == 0) {
+				ssa_fprintf(f, "zeroinitializer");
+				break;
+			}
+
 			ssa_fprintf(f, "[");
 			Type *elem_type = type->Array.elem;
-			ast_node(cl, CompoundLit, value.value_compound);
 
-			for (isize i = 0; i < type->Array.count; i++) {
+			for (isize i = 0; i < elem_count; i++) {
 				if (i > 0) {
 					ssa_fprintf(f, ", ");
 				}
@@ -340,10 +370,55 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
 
 				TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems[i]);
 				GB_ASSERT(tav != NULL);
-				ssa_print_exact_value(f, m, tav->value, elem_type);
+				ssa_print_compound_element(f, m, tav->value, elem_type);
+			}
+			for (isize i = elem_count; i < type->Array.count; i++) {
+				if (i >= elem_count) {
+					ssa_fprintf(f, ", ");
+				}
+				ssa_print_type(f, m, elem_type);
+				ssa_fprintf(f, " zeroinitializer");
 			}
 
 			ssa_fprintf(f, "]");
+		} else if (is_type_vector(type)) {
+			ast_node(cl, CompoundLit, value.value_compound);
+			isize elem_count = cl->elems != NULL ? gb_array_count(cl->elems) : 0;
+			if (elem_count == 0) {
+				ssa_fprintf(f, "zeroinitializer");
+				break;
+			}
+
+			ssa_fprintf(f, "<");
+			Type *elem_type = type->Vector.elem;
+
+			if (elem_count == 1 && type->Vector.count > 1) {
+				TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems[0]);
+				GB_ASSERT(tav != NULL);
+
+				for (isize i = 0; i < type->Vector.count; i++) {
+					if (i > 0) {
+						ssa_fprintf(f, ", ");
+					}
+					ssa_print_type(f, m, elem_type);
+					ssa_fprintf(f, " ");
+					ssa_print_compound_element(f, m, tav->value, elem_type);
+				}
+			} else {
+				for (isize i = 0; i < elem_count; i++) {
+					if (i > 0) {
+						ssa_fprintf(f, ", ");
+					}
+					ssa_print_type(f, m, elem_type);
+					ssa_fprintf(f, " ");
+
+					TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems[i]);
+					GB_ASSERT(tav != NULL);
+					ssa_print_compound_element(f, m, tav->value, elem_type);
+				}
+			}
+
+			ssa_fprintf(f, ">");
 		} else if (is_type_struct(type)) {
 			gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
 			defer (gb_temp_arena_memory_end(tmp));
@@ -361,7 +436,7 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
 
 
 			if (cl->elems[0]->kind == AstNode_FieldValue) {
-				isize elem_count = gb_array_count(cl->elems);
+				isize elem_count = cl->elems != NULL ? gb_array_count(cl->elems) : 0;
 				for (isize i = 0; i < elem_count; i++) {
 					ast_node(fv, FieldValue, cl->elems[i]);
 					String name = fv->field->Ident.string;
@@ -401,30 +476,7 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
 
 				ssa_print_type(f, m, elem_type);
 				ssa_fprintf(f, " ");
-
-				ExactValue v = values[i];
-				if (v.kind == ExactValue_Invalid) {
-					ssa_fprintf(f, "zeroinitializer");
-				} else if (v.kind == ExactValue_String) {
-					// HACK NOTE(bill): This is a hack but it works because strings are created at the very end
-					// of the .ll file
-					ssaValue *str_array = ssa_add_global_string_array(m, v.value_string);
-
-					ssa_fprintf(f, "{i8* getelementptr inbounds (");
-					ssa_print_type(f, m, str_array->Global.entity->type);
-					ssa_fprintf(f, ", ");
-					ssa_print_type(f, m, str_array->Global.entity->type);
-					ssa_fprintf(f, "* ");
-					ssa_print_encoded_global(f, str_array->Global.entity->token.string, false);
-					ssa_fprintf(f, ", ");
-					ssa_print_type(f, m, t_int);
-					ssa_fprintf(f, " 0, i32 0), ");
-					ssa_print_type(f, m, t_int);
-					ssa_fprintf(f, " %lld}", cast(i64)v.value_string.len);
-
-				} else {
-					ssa_print_exact_value(f, m, v, elem_type);
-				}
+				ssa_print_compound_element(f, m, values[i], elem_type);
 			}
 
 
@@ -455,9 +507,37 @@ void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type
 		return;
 	}
 	switch (value->kind) {
+	default: GB_PANIC("Unknown ssaValue kind"); break;
+
 	case ssaValue_Constant:
 		ssa_print_exact_value(f, m, value->Constant.value, type_hint);
 		break;
+
+	case ssaValue_ConstantSlice: {
+		auto *cs = &value->ConstantSlice;
+		if (cs->backing_array == NULL || cs->count == 0) {
+			ssa_fprintf(f, "zeroinitializer");
+		} else {
+			Type *at = base_type(type_deref(ssa_type(cs->backing_array)));
+			Type *et = at->Array.elem;
+			ssa_fprintf(f, "{");
+			ssa_print_type(f, m, et);
+			ssa_fprintf(f, "* getelementptr inbounds (");
+			ssa_print_type(f, m, at);
+			ssa_fprintf(f, ", ");
+			ssa_print_type(f, m, at);
+			ssa_fprintf(f, "* ");
+			ssa_print_value(f, m, cs->backing_array, at);
+			ssa_fprintf(f, ", ");
+			ssa_print_type(f, m, t_int);
+			ssa_fprintf(f, " 0, i32 0), ");
+			ssa_print_type(f, m, t_int);
+			ssa_fprintf(f, " %lld, ", cs->count);
+			ssa_print_type(f, m, t_int);
+			ssa_fprintf(f, " %lld}", cs->count);
+		}
+	} break;
+
 	case ssaValue_TypeName:
 		ssa_print_encoded_local(f, value->TypeName.name);
 		break;
@@ -467,21 +547,7 @@ void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type
 		if (scope != NULL) {
 			in_global_scope = scope->is_global || scope->is_init;
 		}
-		// if (type_hint != NULL && is_type_string(type_hint)) {
-		// 	ssa_fprintf(f, "{i8* getelementptr inbounds (");
-		// 	ssa_print_type(f, m, value->Global.entity->type);
-		// 	ssa_fprintf(f, ", ");
-		// 	ssa_print_type(f, m, value->Global.entity->type);
-		// 	ssa_fprintf(f, "* ");
-		// 	ssa_print_encoded_global(f, value->Global.entity->token.string, in_global_scope);
-		// 	ssa_fprintf(f, ", ");
-		// 	ssa_print_type(f, m, t_int);
-		// 	ssa_fprintf(f, " 0, i32 0), ");
-		// 	ssa_print_type(f, m, t_int);
-		// 	ssa_fprintf(f, " %lld}", 0);
-		// } else {
-			ssa_print_encoded_global(f, value->Global.entity->token.string, in_global_scope);
-		// }
+		ssa_print_encoded_global(f, value->Global.entity->token.string, in_global_scope);
 	} break;
 	case ssaValue_Param:
 		ssa_print_encoded_local(f, value->Param.entity->token.string);

+ 152 - 66
src/codegen/ssa.cpp

@@ -62,9 +62,9 @@ struct ssaModule {
 	Map<String>         type_names; // Key: Type *
 	Map<ssaDebugInfo *> debug_info; // Key: Unique pointer
 	i32                 global_string_index;
+	i32                 global_array_index; // For ConstantSlice
 
 	gbArray(ssaValue *) procs; // NOTE(bill): Procedures to generate
-	gbArray(ssaValue *) const_compound_lits;
 };
 
 
@@ -144,6 +144,7 @@ struct ssaProcedure {
 	SSA_INSTR_KIND(Load), \
 	SSA_INSTR_KIND(GetElementPtr), \
 	SSA_INSTR_KIND(ExtractValue), \
+	SSA_INSTR_KIND(InsertValue), \
 	SSA_INSTR_KIND(Conv), \
 	SSA_INSTR_KIND(Br), \
 	SSA_INSTR_KIND(Ret), \
@@ -238,6 +239,11 @@ struct ssaInstr {
 			Type *    elem_type;
 			i32       index;
 		} ExtractValue;
+		struct {
+			ssaValue *value;
+			ssaValue *elem;
+			ssaValue *index;
+		} InsertValue;
 		struct {
 			ssaConvKind kind;
 			ssaValue *value;
@@ -291,7 +297,7 @@ enum ssaValueKind {
 	ssaValue_Invalid,
 
 	ssaValue_Constant,
-	ssaValue_ConstantArray,
+	ssaValue_ConstantSlice,
 	ssaValue_TypeName,
 	ssaValue_Global,
 	ssaValue_Param,
@@ -314,8 +320,9 @@ struct ssaValue {
 		} Constant;
 		struct {
 			Type *type;
-			gbArray(ssaValue *) values;
-		} ConstantArray;
+			ssaValue *backing_array;
+			i64 count;
+		} ConstantSlice;
 		struct {
 			String name;
 			Type * type;
@@ -415,7 +422,6 @@ void ssa_init_module(ssaModule *m, Checker *c) {
 	map_init(&m->debug_info, gb_heap_allocator());
 	map_init(&m->type_names, gb_heap_allocator());
 	gb_array_init(m->procs,  gb_heap_allocator());
-	gb_array_init(m->const_compound_lits, gb_heap_allocator());
 
 	// Default states
 	m->stmt_state_flags = 0;
@@ -480,7 +486,6 @@ void ssa_destroy_module(ssaModule *m) {
 	map_destroy(&m->type_names);
 	map_destroy(&m->debug_info);
 	gb_array_free(m->procs);
-	gb_array_free(m->const_compound_lits);
 	gb_arena_free(&m->arena);
 }
 
@@ -498,6 +503,8 @@ Type *ssa_type(ssaInstr *instr) {
 		return instr->GetElementPtr.result_type;
 	case ssaInstr_ExtractValue:
 		return instr->ExtractValue.result_type;
+	case ssaInstr_InsertValue:
+		return ssa_type(instr->InsertValue.value);
 	case ssaInstr_BinaryOp:
 		return instr->BinaryOp.type;
 	case ssaInstr_Conv:
@@ -531,6 +538,8 @@ Type *ssa_type(ssaValue *value) {
 	switch (value->kind) {
 	case ssaValue_Constant:
 		return value->Constant.type;
+	case ssaValue_ConstantSlice:
+		return value->ConstantSlice.type;
 	case ssaValue_TypeName:
 		return value->TypeName.type;
 	case ssaValue_Global:
@@ -697,6 +706,15 @@ ssaValue *ssa_make_instr_extract_value(ssaProcedure *p, ssaValue *address, i32 i
 	// GB_ASSERT(et->kind == Type_Struct || et->kind == Type_Array || et->kind == Type_Tuple);
 	return v;
 }
+ssaValue *ssa_make_instr_insert_value(ssaProcedure *p, ssaValue *value, ssaValue *elem, ssaValue *index) {
+	Type *t = ssa_type(value);
+	GB_ASSERT(is_type_array(t) || is_type_struct(t));
+	ssaValue *v = ssa_alloc_instr(p, ssaInstr_InsertValue);
+	v->Instr.InsertValue.value = value;
+	v->Instr.InsertValue.elem   = elem;
+	v->Instr.InsertValue.index  = index;
+	return v;
+}
 
 
 ssaValue *ssa_make_instr_binary_op(ssaProcedure *p, Token op, ssaValue *left, ssaValue *right, Type *type) {
@@ -803,6 +821,15 @@ ssaValue *ssa_make_value_constant(gbAllocator a, Type *type, ExactValue value) {
 	return v;
 }
 
+
+ssaValue *ssa_make_value_constant_slice(gbAllocator a, Type *type, ssaValue *backing_array, i64 count) {
+	ssaValue *v = ssa_alloc_value(a, ssaValue_ConstantSlice);
+	v->ConstantSlice.type = type;
+	v->ConstantSlice.backing_array = backing_array;
+	v->ConstantSlice.count = count;
+	return v;
+}
+
 ssaValue *ssa_make_const_int(gbAllocator a, i64 i) {
 	return ssa_make_value_constant(a, t_int, make_exact_value_integer(i));
 }
@@ -817,13 +844,39 @@ ssaValue *ssa_make_const_bool(gbAllocator a, b32 b) {
 }
 
 ssaValue *ssa_add_module_constant(ssaModule *m, Type *type, ExactValue value) {
-	ssaValue *v = ssa_make_value_constant(m->allocator, type, value);
+	if (is_type_slice(type)) {
+		ast_node(cl, CompoundLit, value.value_compound);
+		gbAllocator a = m->allocator;
+
+		isize count = 0;
+		if (cl->elems) {
+			count = gb_array_count(cl->elems);
+		}
+		if (count > 0) {
+			Type *elem = base_type(type)->Slice.elem;
+			Type *t = make_type_array(a, elem, count);
+			ssaValue *backing_array = ssa_add_module_constant(m, t, value);
 
-	if (!is_type_constant_type(type)) {
-		gb_array_append(m->const_compound_lits, v);
+
+			isize max_len = 7+8+1;
+			u8 *str = cast(u8 *)gb_alloc_array(a, u8, max_len);
+			isize len = gb_snprintf(cast(char *)str, max_len, "__csba$%x", m->global_array_index);
+			m->global_array_index++;
+
+			String name = make_string(str, len-1);
+
+			Entity *e = make_entity_constant(a, NULL, make_token_ident(name), t, value);
+			ssaValue *g = ssa_make_value_global(a, e, backing_array);
+			ssa_module_add_value(m, e, g);
+			map_set(&m->members, hash_string(name), g);
+
+			return ssa_make_value_constant_slice(a, type, g, count);
+		} else {
+			return ssa_make_value_constant_slice(a, type, NULL, 0);
+		}
 	}
 
-	return v;
+	return ssa_make_value_constant(m->allocator, type, value);
 }
 
 
@@ -1547,7 +1600,7 @@ ssaValue *ssa_add_local_slice(ssaProcedure *proc, Type *slice_type, ssaValue *ba
 ssaValue *ssa_add_global_string_array(ssaModule *m, String string) {
 	gbAllocator a = m->allocator;
 
-	isize max_len = 4+8+1;
+	isize max_len = 6+8+1;
 	u8 *str = cast(u8 *)gb_alloc_array(a, u8, max_len);
 	isize len = gb_snprintf(cast(char *)str, max_len, "__str$%x", m->global_string_index);
 	m->global_string_index++;
@@ -2119,33 +2172,45 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 		case Type_Slice:  et = bt->Slice.elem;  break;
 		}
 
+		auto is_elem_const = [](ssaModule *m, AstNode *elem) -> b32 {
+			if (elem->kind == AstNode_FieldValue) {
+				elem = elem->FieldValue.value;
+			}
+			TypeAndValue *tav = type_and_value_of_expression(m->info, elem);
+			GB_ASSERT(tav != NULL);
+			return tav->value.kind != ExactValue_Invalid;
+		};
+
 		switch (bt->kind) {
 		default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break;
 
 		case Type_Vector: {
+			ssaValue *result = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr));
+			if (cl->elems != NULL) {
+				for (isize index = 0; index < gb_array_count(cl->elems); index++) {
+					AstNode *elem = cl->elems[index];
+					if (is_elem_const(proc->module, elem)) {
+						continue;
+					}
+					ssaValue *field_elem = ssa_build_expr(proc, elem);
+					Type *t = ssa_type(field_elem);
+					GB_ASSERT(t->kind != Type_Tuple);
+					ssaValue *ev = ssa_emit_conv(proc, field_elem, et);
+					ssaValue *i = ssa_make_const_int(proc->module->allocator, index);
+					result = ssa_emit(proc, ssa_make_instr_insert_element(proc, result, ev, i));
+				}
 
-			ssaValue *result = ssa_emit_load(proc, v);
-			for (isize index = 0; index < gb_array_count(cl->elems); index++) {
-				AstNode *elem = cl->elems[index];
-				ssaValue *field_elem = ssa_build_expr(proc, elem);
-				Type *t = ssa_type(field_elem);
-				GB_ASSERT(t->kind != Type_Tuple);
-				ssaValue *ev = ssa_emit_conv(proc, field_elem, et);
-				ssaValue *i = ssa_make_const_int(proc->module->allocator, index);
-				result = ssa_emit(proc, ssa_make_instr_insert_element(proc, result, ev, i));
-			}
-
-			if (gb_array_count(cl->elems) == 1 && bt->Vector.count > 1) {
-				isize index_count = bt->Vector.count;
-				i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count);
-				for (isize i = 0; i < index_count; i++) {
-					indices[i] = 0;
+				if (gb_array_count(cl->elems) == 1 && bt->Vector.count > 1) {
+					isize index_count = bt->Vector.count;
+					i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count);
+					for (isize i = 0; i < index_count; i++) {
+						indices[i] = 0;
+					}
+					ssaValue *sv = ssa_emit(proc, ssa_make_instr_shuffle_vector(proc, result, indices, index_count));
+					ssa_emit_store(proc, v, sv);
+					return ssa_emit_load(proc, v);
 				}
-				ssaValue *sv = ssa_emit(proc, ssa_make_instr_shuffle_vector(proc, result, indices, index_count));
-				ssa_emit_store(proc, v, sv);
-				return ssa_emit_load(proc, v);
 			}
-
 			return result;
 		} break;
 
@@ -2153,18 +2218,24 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 			GB_ASSERT(is_type_struct(bt));
 			auto *st = &bt->Record;
 			if (cl->elems != NULL && gb_array_count(cl->elems) > 0) {
+				ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
 				gb_for_array(field_index, cl->elems) {
-					isize index = field_index;
-					AstNode *elem = cl->elems[index];
+					AstNode *elem = cl->elems[field_index];
+					if (is_elem_const(proc->module, elem)) {
+						continue;
+					}
+
 					ssaValue *field_expr = NULL;
 					Entity *field = NULL;
+					isize index = field_index;
 
 					if (elem->kind == AstNode_FieldValue) {
-						ast_node(kv, FieldValue, elem);
-						Selection sel = lookup_field(proc->module->allocator, bt, kv->field->Ident.string, false);
+						ast_node(fv, FieldValue, elem);
+						Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false);
 						index = sel.index[0];
-						field_expr = ssa_build_expr(proc, kv->value);
+						field_expr = ssa_build_expr(proc, fv->value);
 					} else {
+						TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem);
 						Selection sel = lookup_field(proc->module->allocator, bt, st->fields_in_src_order[field_index]->token.string, false);
 						index = sel.index[0];
 						field_expr = ssa_build_expr(proc, elem);
@@ -2182,47 +2253,62 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 			}
 		} break;
 		case Type_Array: {
-			gb_for_array(i, cl->elems) {
-				AstNode *elem = cl->elems[i];
-				ssaValue *field_expr = ssa_build_expr(proc, elem);
-				Type *t = ssa_type(field_expr);
-				GB_ASSERT(t->kind != Type_Tuple);
-				ssaValue *ev = ssa_emit_conv(proc, field_expr, et);
-				ssaValue *gep = ssa_emit_struct_gep(proc, v, i, et);
-				ssa_emit_store(proc, gep, ev);
+			if (cl->elems != NULL && gb_array_count(cl->elems) > 0) {
+				ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
+				gb_for_array(i, cl->elems) {
+					AstNode *elem = cl->elems[i];
+					if (is_elem_const(proc->module, elem)) {
+						continue;
+					}
+					ssaValue *field_expr = ssa_build_expr(proc, elem);
+					Type *t = ssa_type(field_expr);
+					GB_ASSERT(t->kind != Type_Tuple);
+					ssaValue *ev = ssa_emit_conv(proc, field_expr, et);
+					ssaValue *gep = ssa_emit_struct_gep(proc, v, i, et);
+					ssa_emit_store(proc, gep, ev);
+				}
 			}
 		} break;
 		case Type_Slice: {
-			i64 count = gb_array_count(cl->elems);
-			Type *elem_type = bt->Slice.elem;
-			Type *elem_ptr_type = make_type_pointer(proc->module->allocator, elem_type);
-			ssaValue *array = ssa_add_local_generated(proc, make_type_array(proc->module->allocator, elem_type, count));
-
-			gb_for_array(i, cl->elems) {
-				AstNode *elem = cl->elems[i];
-				ssaValue *field_expr = ssa_build_expr(proc, elem);
-				Type *t = ssa_type(field_expr);
-				GB_ASSERT(t->kind != Type_Tuple);
-				ssaValue *ev = ssa_emit_conv(proc, field_expr, elem_type);
-				ssaValue *gep = ssa_emit_struct_gep(proc, array, i, elem_ptr_type);
-				ssa_emit_store(proc, gep, ev);
-			}
+			if (cl->elems != NULL && gb_array_count(cl->elems) > 0) {
+				Type *elem_type = bt->Slice.elem;
+				Type *elem_ptr_type = make_type_pointer(proc->module->allocator, elem_type);
+				Type *elem_ptr_ptr_type = make_type_pointer(proc->module->allocator, elem_ptr_type);
+				Type *t_int_ptr = make_type_pointer(proc->module->allocator, t_int);
+				ssaValue *slice = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr));
+				GB_ASSERT(slice->kind == ssaValue_ConstantSlice);
+
+				ssaValue *data = ssa_emit_struct_gep(proc, slice->ConstantSlice.backing_array, v_zero32, elem_ptr_type);
+
+				gb_for_array(i, cl->elems) {
+					AstNode *elem = cl->elems[i];
+					if (is_elem_const(proc->module,elem)) {
+						continue;
+					}
 
-			ssaValue *elem = ssa_array_elem(proc, array);
-			ssaValue *len = ssa_array_len(proc, ssa_emit_load(proc, array));
-			ssaValue *gep0 = ssa_emit_struct_gep(proc, v, v_zero32, ssa_type(elem));
-			ssaValue *gep1 = ssa_emit_struct_gep(proc, v, v_one32, t_int);
-			ssaValue *gep2 = ssa_emit_struct_gep(proc, v, v_two32, t_int);
+					ssaValue *field_expr = ssa_build_expr(proc, elem);
+					Type *t = ssa_type(field_expr);
+					GB_ASSERT(t->kind != Type_Tuple);
+					ssaValue *ev = ssa_emit_conv(proc, field_expr, elem_type);
+					ssaValue *offset = ssa_emit_ptr_offset(proc, data, ssa_make_const_int(proc->module->allocator, i));
+					ssa_emit_store(proc, offset, ev);
+				}
 
-			ssa_emit_store(proc, gep0, elem);
-			ssa_emit_store(proc, gep1, len);
-			ssa_emit_store(proc, gep2, len);
+				ssaValue *gep0 = ssa_emit_struct_gep(proc, v, v_zero32, elem_ptr_ptr_type);
+				ssaValue *gep1 = ssa_emit_struct_gep(proc, v, v_one32, t_int_ptr);
+				ssaValue *gep2 = ssa_emit_struct_gep(proc, v, v_two32, t_int_ptr);
+
+				ssa_emit_store(proc, gep0, data);
+				ssa_emit_store(proc, gep1, ssa_make_const_int(proc->module->allocator, slice->ConstantSlice.count));
+				ssa_emit_store(proc, gep2, ssa_make_const_int(proc->module->allocator, slice->ConstantSlice.count));
+			}
 		} break;
 		}
 
 		return ssa_emit_load(proc, v);
 	case_end;
 
+
 	case_ast_node(ce, CallExpr, expr);
 		AstNode *p = unparen_expr(ce->proc);
 		if (p->kind == AstNode_Ident) {

+ 27 - 6
src/common.cpp

@@ -4,20 +4,39 @@
 
 #include "string.cpp"
 
-String get_module_dir(gbAllocator a) {
-	isize len = GetModuleFileNameW(NULL, NULL, 0);
-	if (len == 0) {
-		return make_string(NULL, 0);
+gb_global String global_module_path = {};
+gb_global b32 global_module_path_set = false;
+
+String get_module_dir() {
+	if (global_module_path_set) {
+		return global_module_path;
 	}
+
+	gbArray(wchar_t) path_buf;
+	gb_array_init_reserve(path_buf, gb_heap_allocator(), 300);
+	defer (gb_array_free(path_buf));
+	gb_array_resize(path_buf, 300);
+
+	isize len = 0;
+	for (;;) {
+		len = GetModuleFileNameW(NULL, path_buf, gb_array_count(path_buf));
+		if (len == 0) {
+			return make_string(NULL, 0);
+		}
+		if (len < gb_array_count(path_buf)) {
+			break;
+		}
+		gb_array_resize(path_buf, 2*gb_array_count(path_buf) + 300);
+	}
+
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
 	defer (gb_temp_arena_memory_end(tmp));
 
-
 	wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
 
 	String16 str = {text, len};
 	GetModuleFileNameW(NULL, text, len);
-	String path = string16_to_string(a, str);
+	String path = string16_to_string(gb_heap_allocator(), str);
 	for (isize i = path.len-1; i >= 0; i--) {
 		u8 c = path.text[i];
 		if (c == '/' || c == '\\') {
@@ -26,6 +45,8 @@ String get_module_dir(gbAllocator a) {
 		path.len--;
 	}
 
+	global_module_path = path;
+	global_module_path_set = true;
 
 	return path;
 }

+ 1 - 2
src/main.cpp

@@ -118,8 +118,7 @@ int main(int argc, char **argv) {
 	init_string_buffer_memory();
 	init_global_error_collector();
 
-	String module_dir = get_module_dir(gb_heap_allocator());
-	// defer (gb_free(gb_heap_allocator(), module_dir.text));
+	String module_dir = get_module_dir();
 
 	INIT_TIMER();
 

+ 1 - 4
src/parser.cpp

@@ -2919,10 +2919,7 @@ String get_fullpath_relative(gbAllocator a, String base_dir, String path) {
 }
 
 String get_fullpath_core(gbAllocator a, String path) {
-	String module_dir = get_module_dir(gb_heap_allocator());
-	defer (if (module_dir.len > 0) {
-		gb_free(gb_heap_allocator(), module_dir.text);
-	});
+	String module_dir = get_module_dir();
 
 	char core[] = "core/";
 	isize core_len = gb_size_of(core)-1;