Browse Source

Fix exact value bug when updating expressions

Ginger Bill 8 years ago
parent
commit
b9719df0ad
8 changed files with 86 additions and 52 deletions
  1. 7 0
      code/demo.odin
  2. 7 8
      core/_preload.odin
  3. 7 5
      core/fmt.odin
  4. 2 1
      core/utf8.odin
  5. 1 2
      src/checker/checker.cpp
  6. 36 18
      src/checker/expr.cpp
  7. 3 6
      src/codegen/print_llvm.cpp
  8. 23 12
      src/codegen/ssa.cpp

+ 7 - 0
code/demo.odin

@@ -1,6 +1,13 @@
 #import "fmt.odin"
 #import "fmt.odin"
 
 
 main :: proc() {
 main :: proc() {
+	Thing :: struct {
+		f: f32
+		a: any
+	}
+	t := Thing{1, "Hello"}
 
 
+
+	fmt.printf("Here % %\n", 123, 2.0)
 }
 }
 
 

+ 7 - 8
core/_preload.odin

@@ -74,11 +74,12 @@ type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
 	if info == nil {
 	if info == nil {
 		return nil
 		return nil
 	}
 	}
-	match type i : info {
+	base := info
+	match type i : base {
 	case Type_Info.Named:
 	case Type_Info.Named:
-		info = i.base
+		base = i.base
 	}
 	}
-	return info
+	return base
 }
 }
 
 
 
 
@@ -259,10 +260,10 @@ __string_eq :: proc(a, b: string) -> bool {
 	if a.count != b.count {
 	if a.count != b.count {
 		return false
 		return false
 	}
 	}
-	if ^a[0] == ^b[0] {
+	if a.data == b.data {
 		return true
 		return true
 	}
 	}
-	return mem.compare(^a[0], ^b[0], a.count) == 0
+	return mem.compare(a.data, b.data, a.count) == 0
 }
 }
 
 
 __string_cmp :: proc(a, b : string) -> int {
 __string_cmp :: proc(a, b : string) -> int {
@@ -312,9 +313,7 @@ __substring_expr_error :: proc(file: string, line, column: int,
 }
 }
 
 
 __enum_to_string :: proc(info: ^Type_Info, value: i64) -> string {
 __enum_to_string :: proc(info: ^Type_Info, value: i64) -> string {
-	info = type_info_base(info)
-
-	match type ti : info {
+	match type ti : type_info_base(info) {
 	case Type_Info.Enum:
 	case Type_Info.Enum:
 		// TODO(bill): Search faster than linearly
 		// TODO(bill): Search faster than linearly
 		for i := 0; i < ti.values.count; i++ {
 		for i := 0; i < ti.values.count; i++ {

+ 7 - 5
core/fmt.odin

@@ -90,7 +90,8 @@ print_pointer_to_buffer :: proc(buffer: ^[]byte, p: rawptr) #inline {
 
 
 print_f32_to_buffer :: proc(buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 7) }
 print_f32_to_buffer :: proc(buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 7) }
 print_f64_to_buffer :: proc(buffer: ^[]byte, f: f64) #inline { print__f64(buffer, f, 10) }
 print_f64_to_buffer :: proc(buffer: ^[]byte, f: f64) #inline { print__f64(buffer, f, 10) }
-print_u64_to_buffer :: proc(buffer: ^[]byte, i: u64) {
+print_u64_to_buffer :: proc(buffer: ^[]byte, value: u64) {
+	i := value
 	buf: [22]byte
 	buf: [22]byte
 	len := 0
 	len := 0
 	if i == 0 {
 	if i == 0 {
@@ -105,7 +106,8 @@ print_u64_to_buffer :: proc(buffer: ^[]byte, i: u64) {
 	byte_reverse(buf[:len])
 	byte_reverse(buf[:len])
 	print_string_to_buffer(buffer, buf[:len] as string)
 	print_string_to_buffer(buffer, buf[:len] as string)
 }
 }
-print_i64_to_buffer :: proc(buffer: ^[]byte, i: i64) {
+print_i64_to_buffer :: proc(buffer: ^[]byte, value: i64) {
+	i := value
 	neg := i < 0
 	neg := i < 0
 	if neg {
 	if neg {
 		i = -i
 		i = -i
@@ -114,7 +116,8 @@ print_i64_to_buffer :: proc(buffer: ^[]byte, i: i64) {
 	print_u64_to_buffer(buffer, i as u64)
 	print_u64_to_buffer(buffer, i as u64)
 }
 }
 
 
-print__f64 :: proc(buffer: ^[]byte, f: f64, decimal_places: int) {
+print__f64 :: proc(buffer: ^[]byte, value: f64, decimal_places: int) {
+	f := value
 	if f == 0 {
 	if f == 0 {
 		print_rune_to_buffer(buffer, #rune "0")
 		print_rune_to_buffer(buffer, #rune "0")
 		return
 		return
@@ -555,12 +558,11 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) {
 bprint :: proc(buf: ^[]byte, args: ..any) {
 bprint :: proc(buf: ^[]byte, args: ..any) {
 	is_type_string :: proc(info: ^Type_Info) -> bool {
 	is_type_string :: proc(info: ^Type_Info) -> bool {
 		using Type_Info
 		using Type_Info
-		info = type_info_base(info)
 		if info == nil {
 		if info == nil {
 			return false
 			return false
 		}
 		}
 
 
-		match type i : info {
+		match type i : type_info_base(info) {
 		case String:
 		case String:
 			return true
 			return true
 		}
 		}

+ 2 - 1
core/utf8.odin

@@ -39,7 +39,8 @@ accept_sizes := [256]byte{
 	0x34, 0x04, 0x04, 0x04, 0x44, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xf0-0xff
 	0x34, 0x04, 0x04, 0x04, 0x44, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xf0-0xff
 }
 }
 
 
-encode_rune :: proc(r: rune) -> ([4]byte, int) {
+encode_rune :: proc(r_: rune) -> ([4]byte, int) {
+	r := r_
 	buf: [4]byte
 	buf: [4]byte
 	i := r as u32
 	i := r as u32
 	mask: byte : 0x3f
 	mask: byte : 0x3f

+ 1 - 2
src/checker/checker.cpp

@@ -645,7 +645,6 @@ void add_untyped(CheckerInfo *i, AstNode *expression, b32 lhs, AddressingMode mo
 	map_set(&i->untyped, hash_pointer(expression), make_expression_info(lhs, mode, basic_type, value));
 	map_set(&i->untyped, hash_pointer(expression), make_expression_info(lhs, mode, basic_type, value));
 }
 }
 
 
-
 void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode, Type *type, ExactValue value) {
 void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode, Type *type, ExactValue value) {
 	GB_ASSERT(expression != NULL);
 	GB_ASSERT(expression != NULL);
 	if (mode == Addressing_Invalid)
 	if (mode == Addressing_Invalid)
@@ -1306,7 +1305,7 @@ void check_parsed_files(Checker *c) {
 		ExpressionInfo *info = &entry->value;
 		ExpressionInfo *info = &entry->value;
 		if (info != NULL && expr != NULL) {
 		if (info != NULL && expr != NULL) {
 			if (is_type_typed(info->type)) {
 			if (is_type_typed(info->type)) {
-				compiler_error("%s (type %s) is typed!", expr_to_string(expr), info->type);
+				compiler_error("%s (type %s) is typed!", expr_to_string(expr), type_to_string(info->type));
 			}
 			}
 			add_type_and_value(&c->info, expr, info->mode, info->type, info->value);
 			add_type_and_value(&c->info, expr, info->mode, info->type, info->value);
 		}
 		}

+ 36 - 18
src/checker/expr.cpp

@@ -933,7 +933,11 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
 			o->type = t_invalid;
 			o->type = t_invalid;
 			return;
 			return;
 		}
 		}
-		o->mode = Addressing_Variable;
+		// if (e->Variable.param) {
+			// o->mode = Addressing_Value;
+		// } else {
+			o->mode = Addressing_Variable;
+		// }
 		break;
 		break;
 
 
 	case Entity_TypeName: {
 	case Entity_TypeName: {
@@ -2239,7 +2243,6 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
 
 
 
 
 	operand->type = target_type;
 	operand->type = target_type;
-	update_expr_type(c, operand->expr, target_type, true);
 }
 }
 
 
 b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *value) {
 b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *value) {
@@ -3265,7 +3268,6 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
 	defer (gb_temp_arena_memory_end(tmp));
 	defer (gb_temp_arena_memory_end(tmp));
 
 
-	isize operand_count = 0;
 	Array<Operand> operands;
 	Array<Operand> operands;
 	array_init(&operands, c->tmp_allocator, 2*param_count);
 	array_init(&operands, c->tmp_allocator, 2*param_count);
 
 
@@ -3289,11 +3291,10 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
 		}
 		}
 	}
 	}
 
 
-	operand_count = operands.count;
 	i32 error_code = 0;
 	i32 error_code = 0;
-	if (operand_count < param_count) {
+	if (operands.count < param_count) {
 		error_code = -1;
 		error_code = -1;
-	} else if (!variadic && operand_count > param_count) {
+	} else if (!variadic && operands.count > param_count) {
 		error_code = +1;
 		error_code = +1;
 	}
 	}
 	if (error_code != 0) {
 	if (error_code != 0) {
@@ -3303,16 +3304,22 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
 		}
 		}
 
 
 		gbString proc_str = expr_to_string(ce->proc);
 		gbString proc_str = expr_to_string(ce->proc);
+		defer (gb_string_free(proc_str));
 		error(ast_node_token(call), err_fmt, proc_str, param_count);
 		error(ast_node_token(call), err_fmt, proc_str, param_count);
-		gb_string_free(proc_str);
 		operand->mode = Addressing_Invalid;
 		operand->mode = Addressing_Invalid;
 	}
 	}
 
 
 	GB_ASSERT(proc_type->Proc.params != NULL);
 	GB_ASSERT(proc_type->Proc.params != NULL);
 	Entity **sig_params = proc_type->Proc.params->Tuple.variables;
 	Entity **sig_params = proc_type->Proc.params->Tuple.variables;
-	for (isize i = 0; i < param_count; i++) {
-		Type *arg_type = sig_params[i]->type;
-		check_assignment(c, &operands[i], arg_type, make_string("argument"), true);
+	isize operand_index = 0;
+	for (; operand_index < param_count; operand_index++) {
+		Type *arg_type = sig_params[operand_index]->type;
+		Operand o = operands[operand_index];
+		if (variadic) {
+
+			o = operands[operand_index];
+		}
+		check_assignment(c, &o, arg_type, make_string("argument"), true);
 	}
 	}
 
 
 	if (variadic) {
 	if (variadic) {
@@ -3320,18 +3327,18 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
 		Type *slice = sig_params[param_count]->type;
 		Type *slice = sig_params[param_count]->type;
 		Type *elem = base_type(slice)->Slice.elem;
 		Type *elem = base_type(slice)->Slice.elem;
 		Type *t = elem;
 		Type *t = elem;
-		for (isize i = param_count; i < operand_count; i++) {
-			Operand *o = &operands[i];
+		for (; operand_index < operands.count; operand_index++) {
+			Operand o = operands[operand_index];
 			if (vari_expand) {
 			if (vari_expand) {
 				variadic_expand = true;
 				variadic_expand = true;
 				t = slice;
 				t = slice;
-				if (i != param_count) {
-					error(ast_node_token(o->expr),
+				if (operand_index != param_count) {
+					error(ast_node_token(o.expr),
 					      "`..` in a variadic procedure can only have one variadic argument at the end");
 					      "`..` in a variadic procedure can only have one variadic argument at the end");
 					break;
 					break;
 				}
 				}
 			}
 			}
-			check_assignment(c, o, t, make_string("argument"), true);
+			check_assignment(c, &o, t, make_string("argument"), true);
 		}
 		}
 	}
 	}
 }
 }
@@ -3574,10 +3581,14 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 						fields_visited[sel.index[0]] = true;
 						fields_visited[sel.index[0]] = true;
 						check_expr(c, o, fv->value);
 						check_expr(c, o, fv->value);
 
 
+						if (base_type(field->type) == t_any) {
+							is_constant = false;
+						}
 						if (is_constant) {
 						if (is_constant) {
 							is_constant = o->mode == Addressing_Constant;
 							is_constant = o->mode == Addressing_Constant;
 						}
 						}
 
 
+
 						check_assignment(c, o, field->type, make_string("structure literal"));
 						check_assignment(c, o, field->type, make_string("structure literal"));
 					}
 					}
 				} else {
 				} else {
@@ -3596,6 +3607,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 							break;
 							break;
 						}
 						}
 
 
+						if (base_type(field->type) == t_any) {
+							is_constant = false;
+						}
 						if (is_constant) {
 						if (is_constant) {
 							is_constant = o->mode == Addressing_Constant;
 							is_constant = o->mode == Addressing_Constant;
 						}
 						}
@@ -3632,15 +3646,18 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 			isize index = 0;
 			isize index = 0;
 			isize elem_count = cl->elems.count;
 			isize elem_count = cl->elems.count;
 
 
+			if (base_type(elem_type) == t_any) {
+				is_constant = false;
+			}
+
 			for (; index < elem_count; index++) {
 			for (; index < elem_count; index++) {
 				AstNode *e = cl->elems[index];
 				AstNode *e = cl->elems[index];
 				if (e->kind == AstNode_FieldValue) {
 				if (e->kind == AstNode_FieldValue) {
 					error(ast_node_token(e),
 					error(ast_node_token(e),
-					      "`field = value` is only allowed in structure literals");
+					      "`field = value` is only allowed in struct literals");
 					continue;
 					continue;
 				}
 				}
 
 
-
 				if (t->kind == Type_Array &&
 				if (t->kind == Type_Array &&
 				    t->Array.count >= 0 &&
 				    t->Array.count >= 0 &&
 				    index >= t->Array.count) {
 				    index >= t->Array.count) {
@@ -3660,8 +3677,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 					is_constant = operand.mode == Addressing_Constant;
 					is_constant = operand.mode == Addressing_Constant;
 				}
 				}
 			}
 			}
-			if (max < index)
+			if (max < index) {
 				max = index;
 				max = index;
+			}
 
 
 			if (t->kind == Type_Vector) {
 			if (t->kind == Type_Vector) {
 				if (t->Vector.count > 1 && gb_is_between(index, 2, t->Vector.count-1)) {
 				if (t->Vector.count > 1 && gb_is_between(index, 2, t->Vector.count-1)) {

+ 3 - 6
src/codegen/print_llvm.cpp

@@ -145,12 +145,10 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
 		case Basic_i16:    ssa_fprintf(f, "i16");                     break;
 		case Basic_i16:    ssa_fprintf(f, "i16");                     break;
 		case Basic_i32:    ssa_fprintf(f, "i32");                     break;
 		case Basic_i32:    ssa_fprintf(f, "i32");                     break;
 		case Basic_i64:    ssa_fprintf(f, "i64");                     break;
 		case Basic_i64:    ssa_fprintf(f, "i64");                     break;
-		// case Basic_i128:   ssa_fprintf(f, "i128");                    break;
 		case Basic_u8:     ssa_fprintf(f, "i8");                      break;
 		case Basic_u8:     ssa_fprintf(f, "i8");                      break;
 		case Basic_u16:    ssa_fprintf(f, "i16");                     break;
 		case Basic_u16:    ssa_fprintf(f, "i16");                     break;
 		case Basic_u32:    ssa_fprintf(f, "i32");                     break;
 		case Basic_u32:    ssa_fprintf(f, "i32");                     break;
 		case Basic_u64:    ssa_fprintf(f, "i64");                     break;
 		case Basic_u64:    ssa_fprintf(f, "i64");                     break;
-		// case Basic_u128:   ssa_fprintf(f, "i128");                    break;
 		case Basic_f32:    ssa_fprintf(f, "float");                   break;
 		case Basic_f32:    ssa_fprintf(f, "float");                   break;
 		case Basic_f64:    ssa_fprintf(f, "double");                  break;
 		case Basic_f64:    ssa_fprintf(f, "double");                  break;
 		case Basic_rawptr: ssa_fprintf(f, "%%..rawptr");              break;
 		case Basic_rawptr: ssa_fprintf(f, "%%..rawptr");              break;
@@ -176,12 +174,11 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
 		ssa_print_type(f, m, t->Array.elem);
 		ssa_print_type(f, m, t->Array.elem);
 		ssa_fprintf(f, "]");
 		ssa_fprintf(f, "]");
 		break;
 		break;
-	case Type_Vector: {
-		// TODO(bill): actually do correctly
+	case Type_Vector:
 		ssa_fprintf(f, "<%lld x ", t->Vector.count);
 		ssa_fprintf(f, "<%lld x ", t->Vector.count);
 		ssa_print_type(f, m, t->Vector.elem);
 		ssa_print_type(f, m, t->Vector.elem);
 		ssa_fprintf(f, ">");
 		ssa_fprintf(f, ">");
-	} break;
+		break;
 	case Type_Slice:
 	case Type_Slice:
 		ssa_fprintf(f, "{");
 		ssa_fprintf(f, "{");
 		ssa_print_type(f, m, t->Slice.elem);
 		ssa_print_type(f, m, t->Slice.elem);
@@ -278,7 +275,7 @@ void ssa_print_compound_element(ssaFileBuffer *f, ssaModule *m, ExactValue v, Ty
 		ssa_fprintf(f, " ");
 		ssa_fprintf(f, " ");
 	}
 	}
 
 
-	if (v.kind == ExactValue_Invalid) {
+	if (v.kind == ExactValue_Invalid || base_type(elem_type) == t_any) {
 		ssa_fprintf(f, "zeroinitializer");
 		ssa_fprintf(f, "zeroinitializer");
 	} else if (v.kind == ExactValue_String) {
 	} else if (v.kind == ExactValue_String) {
 		// HACK NOTE(bill): This is a hack but it works because strings are created at the very end
 		// HACK NOTE(bill): This is a hack but it works because strings are created at the very end

+ 23 - 12
src/codegen/ssa.cpp

@@ -1418,6 +1418,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
 	proc->curr_block = proc->decl_block;
 	proc->curr_block = proc->decl_block;
 	ssa_emit_jump(proc, proc->entry_block);
 	ssa_emit_jump(proc, proc->entry_block);
 
 
+#if 0
 	ssa_optimize_blocks(proc);
 	ssa_optimize_blocks(proc);
 	ssa_build_referrers(proc);
 	ssa_build_referrers(proc);
 	ssa_build_dom_tree(proc);
 	ssa_build_dom_tree(proc);
@@ -1428,7 +1429,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
 	// [ ] Local stored once?  Replace loads with dominating store
 	// [ ] Local stored once?  Replace loads with dominating store
 	// [ ] Convert to phi nodes
 	// [ ] Convert to phi nodes
 	ssa_opt_mem2reg(proc);
 	ssa_opt_mem2reg(proc);
-
+#endif
 
 
 // Number registers
 // Number registers
 	i32 reg_index = 0;
 	i32 reg_index = 0;
@@ -1923,6 +1924,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
 				ev = exact_value_to_float(ev);
 				ev = exact_value_to_float(ev);
 			} else if (is_type_string(dst)) {
 			} else if (is_type_string(dst)) {
 				// Handled elsewhere
 				// Handled elsewhere
+				GB_ASSERT(ev.kind == ExactValue_String);
 			} else if (is_type_integer(dst)) {
 			} else if (is_type_integer(dst)) {
 				ev = exact_value_to_integer(ev);
 				ev = exact_value_to_integer(ev);
 			} else if (is_type_pointer(dst)) {
 			} else if (is_type_pointer(dst)) {
@@ -2479,7 +2481,10 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 		case Type_Slice:  et = bt->Slice.elem;  break;
 		case Type_Slice:  et = bt->Slice.elem;  break;
 		}
 		}
 
 
-		auto is_elem_const = [](ssaModule *m, AstNode *elem) -> b32 {
+		auto is_elem_const = [](ssaModule *m, AstNode *elem, Type *elem_type) -> b32 {
+			if (base_type(elem_type) == t_any) {
+				return false;
+			}
 			if (elem->kind == AstNode_FieldValue) {
 			if (elem->kind == AstNode_FieldValue) {
 				elem = elem->FieldValue.value;
 				elem = elem->FieldValue.value;
 			}
 			}
@@ -2495,7 +2500,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 			ssaValue *result = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr));
 			ssaValue *result = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr));
 			for_array(index, cl->elems) {
 			for_array(index, cl->elems) {
 				AstNode *elem = cl->elems[index];
 				AstNode *elem = cl->elems[index];
-				if (is_elem_const(proc->module, elem)) {
+				if (is_elem_const(proc->module, elem, et)) {
 					continue;
 					continue;
 				}
 				}
 				ssaValue *field_elem = ssa_build_expr(proc, elem);
 				ssaValue *field_elem = ssa_build_expr(proc, elem);
@@ -2526,9 +2531,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
 				ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
 				for_array(field_index, cl->elems) {
 				for_array(field_index, cl->elems) {
 					AstNode *elem = cl->elems[field_index];
 					AstNode *elem = cl->elems[field_index];
-					if (is_elem_const(proc->module, elem)) {
-						continue;
-					}
 
 
 					ssaValue *field_expr = NULL;
 					ssaValue *field_expr = NULL;
 					Entity *field = NULL;
 					Entity *field = NULL;
@@ -2538,17 +2540,23 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 						ast_node(fv, FieldValue, elem);
 						ast_node(fv, FieldValue, elem);
 						Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false);
 						Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false);
 						index = sel.index[0];
 						index = sel.index[0];
-						field_expr = ssa_build_expr(proc, fv->value);
+						elem = fv->value;
 					} else {
 					} else {
 						TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem);
 						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);
 						Selection sel = lookup_field(proc->module->allocator, bt, st->fields_in_src_order[field_index]->token.string, false);
 						index = sel.index[0];
 						index = sel.index[0];
-						field_expr = ssa_build_expr(proc, elem);
 					}
 					}
 
 
+					field = st->fields[index];
+					if (is_elem_const(proc->module, elem, field->type)) {
+						continue;
+					}
+
+					field_expr = ssa_build_expr(proc, elem);
+
 					GB_ASSERT(ssa_type(field_expr)->kind != Type_Tuple);
 					GB_ASSERT(ssa_type(field_expr)->kind != Type_Tuple);
 
 
-					field = st->fields[index];
+
 
 
 					Type *ft = field->type;
 					Type *ft = field->type;
 					ssaValue *fv = ssa_emit_conv(proc, field_expr, ft);
 					ssaValue *fv = ssa_emit_conv(proc, field_expr, ft);
@@ -2562,7 +2570,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
 				ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
 				for_array(i, cl->elems) {
 				for_array(i, cl->elems) {
 					AstNode *elem = cl->elems[i];
 					AstNode *elem = cl->elems[i];
-					if (is_elem_const(proc->module, elem)) {
+					if (is_elem_const(proc->module, elem, et)) {
 						continue;
 						continue;
 					}
 					}
 					ssaValue *field_expr = ssa_build_expr(proc, elem);
 					ssaValue *field_expr = ssa_build_expr(proc, elem);
@@ -2587,7 +2595,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 
 
 				for_array(i, cl->elems) {
 				for_array(i, cl->elems) {
 					AstNode *elem = cl->elems[i];
 					AstNode *elem = cl->elems[i];
-					if (is_elem_const(proc->module,elem)) {
+					if (is_elem_const(proc->module, elem, et)) {
 						continue;
 						continue;
 					}
 					}
 
 
@@ -3034,12 +3042,15 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 				ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_two32, t_int), len);
 				ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_two32, t_int), len);
 			}
 			}
 
 
+			if (args[0]->kind == ssaValue_Constant) {
+				auto *c = &args[0]->Constant;
+				gb_printf_err("%s %d\n", type_to_string(c->type), c->value.kind);
+			}
 
 
 			arg_count = type->param_count;
 			arg_count = type->param_count;
 			args[arg_count-1] = ssa_emit_load(proc, slice);
 			args[arg_count-1] = ssa_emit_load(proc, slice);
 		}
 		}
 
 
-
 		return ssa_emit_call(proc, value, args, arg_count);
 		return ssa_emit_call(proc, value, args, arg_count);
 	case_end;
 	case_end;