authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-22 23:12:33-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-22 23:12:33-07:00
loge269caae02778c5b15a101c42d2d2d5150af59c8
tree6c9244e636c03fbd732fd7277740a0309a43b990
parent0e51c16ef57b3b8239c512d78f0dcafb202be21c

implement undefined literal


3 files changed, 95 insertions(+), 75 deletions(-)

src/all_types.hpp+3
...@@ -62,6 +62,7 @@ struct ConstPtrValue {...@@ -62,6 +62,7 @@ struct ConstPtrValue {
62struct ConstExprValue {62struct ConstExprValue {
63 bool ok; // true if constant expression evalution worked63 bool ok; // true if constant expression evalution worked
64 bool depends_on_compile_var;64 bool depends_on_compile_var;
65 bool undef;
6566
66 union {67 union {
67 BigNum x_bignum;68 BigNum x_bignum;
...@@ -808,6 +809,7 @@ enum TypeTableEntryId {...@@ -808,6 +809,7 @@ enum TypeTableEntryId {
808 TypeTableEntryIdStruct,809 TypeTableEntryIdStruct,
809 TypeTableEntryIdNumLitFloat,810 TypeTableEntryIdNumLitFloat,
810 TypeTableEntryIdNumLitInt,811 TypeTableEntryIdNumLitInt,
812 TypeTableEntryIdUndefLit,
811 TypeTableEntryIdMaybe,813 TypeTableEntryIdMaybe,
812 TypeTableEntryIdError,814 TypeTableEntryIdError,
813 TypeTableEntryIdEnum,815 TypeTableEntryIdEnum,
...@@ -949,6 +951,7 @@ struct CodeGen {...@@ -949,6 +951,7 @@ struct CodeGen {
949 TypeTableEntry *entry_invalid;951 TypeTableEntry *entry_invalid;
950 TypeTableEntry *entry_num_lit_int;952 TypeTableEntry *entry_num_lit_int;
951 TypeTableEntry *entry_num_lit_float;953 TypeTableEntry *entry_num_lit_float;
954 TypeTableEntry *entry_undef;
952 } builtin_types;955 } builtin_types;
953956
954 LLVMTargetDataRef target_data_ref;957 LLVMTargetDataRef target_data_ref;
src/analyze.cpp+4-3
...@@ -111,6 +111,7 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {...@@ -111,6 +111,7 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
111 case TypeTableEntryIdMaybe:111 case TypeTableEntryIdMaybe:
112 case TypeTableEntryIdFn:112 case TypeTableEntryIdFn:
113 case TypeTableEntryIdError:113 case TypeTableEntryIdError:
114 case TypeTableEntryIdUndefLit:
114 // nothing to init115 // nothing to init
115 break;116 break;
116 case TypeTableEntryIdStruct:117 case TypeTableEntryIdStruct:
...@@ -1063,6 +1064,7 @@ static bool type_has_codegen_value(TypeTableEntryId id) {...@@ -1063,6 +1064,7 @@ static bool type_has_codegen_value(TypeTableEntryId id) {
1063 case TypeTableEntryIdUnreachable:1064 case TypeTableEntryIdUnreachable:
1064 case TypeTableEntryIdNumLitFloat:1065 case TypeTableEntryIdNumLitFloat:
1065 case TypeTableEntryIdNumLitInt:1066 case TypeTableEntryIdNumLitInt:
1067 case TypeTableEntryIdUndefLit:
1066 return false;1068 return false;
10671069
1068 case TypeTableEntryIdBool:1070 case TypeTableEntryIdBool:
...@@ -2481,10 +2483,9 @@ static TypeTableEntry *analyze_undefined_literal_expr(CodeGen *g, ImportTableEnt...@@ -2481,10 +2483,9 @@ static TypeTableEntry *analyze_undefined_literal_expr(CodeGen *g, ImportTableEnt
2481 ConstExprValue *const_val = &expr->const_val;2483 ConstExprValue *const_val = &expr->const_val;
24822484
2483 const_val->ok = true;2485 const_val->ok = true;
2486 const_val->undef = true;
24842487
2485 zig_panic("TODO");2488 return expected_type ? expected_type : g->builtin_types.entry_undef;
2486
2487 return expected_type;
2488}2489}
24892490
24902491
src/codegen.cpp+88-72
...@@ -1725,84 +1725,91 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa...@@ -1725,84 +1725,91 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa
1725 }1725 }
1726 if (variable->type->size_in_bits == 0) {1726 if (variable->type->size_in_bits == 0) {
1727 return nullptr;1727 return nullptr;
1728 } else {1728 }
1729 if (var_decl->expr) {1729
1730 TypeTableEntry *expr_type = get_expr_type(var_decl->expr);1730 bool have_init_expr = false;
1731 LLVMValueRef value;1731 if (var_decl->expr) {
1732 if (unwrap_maybe) {1732 ConstExprValue *const_val = &get_resolved_expr(var_decl->expr)->const_val;
1733 assert(var_decl->expr);1733 if (!const_val->ok || !const_val->undef) {
1734 assert(expr_type->id == TypeTableEntryIdMaybe);1734 have_init_expr = true;
1735 value = gen_unwrap_maybe(g, source_node, *init_value);1735 }
1736 expr_type = expr_type->data.maybe.child_type;1736 }
1737 } else {1737 if (have_init_expr) {
1738 value = *init_value;1738 TypeTableEntry *expr_type = get_expr_type(var_decl->expr);
1739 }1739 LLVMValueRef value;
1740 gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref,1740 if (unwrap_maybe) {
1741 value, variable->type, expr_type);1741 assert(var_decl->expr);
1742 assert(expr_type->id == TypeTableEntryIdMaybe);
1743 value = gen_unwrap_maybe(g, source_node, *init_value);
1744 expr_type = expr_type->data.maybe.child_type;
1742 } else {1745 } else {
1743 bool ignore_uninit = false;1746 value = *init_value;
1744 TypeTableEntry *var_type = get_type_for_type_node(var_decl->type);1747 }
1745 if (var_type->id == TypeTableEntryIdStruct &&1748 gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref,
1746 var_type->data.structure.is_unknown_size_array)1749 value, variable->type, expr_type);
1747 {1750 } else {
1748 assert(var_decl->type->type == NodeTypeArrayType);1751 bool ignore_uninit = false;
1749 AstNode *size_node = var_decl->type->data.array_type.size;1752 TypeTableEntry *var_type = get_type_for_type_node(var_decl->type);
1750 if (size_node) {1753 if (var_type->id == TypeTableEntryIdStruct &&
1751 ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;1754 var_type->data.structure.is_unknown_size_array)
1752 if (!const_val->ok) {1755 {
1753 TypeTableEntry *ptr_type = var_type->data.structure.fields[0].type_entry;1756 assert(var_decl->type->type == NodeTypeArrayType);
1754 assert(ptr_type->id == TypeTableEntryIdPointer);1757 AstNode *size_node = var_decl->type->data.array_type.size;
1755 TypeTableEntry *child_type = ptr_type->data.pointer.child_type;1758 if (size_node) {
17561759 ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
1757 LLVMValueRef size_val = gen_expr(g, size_node);1760 if (!const_val->ok) {
17581761 TypeTableEntry *ptr_type = var_type->data.structure.fields[0].type_entry;
1759 add_debug_source_node(g, source_node);1762 assert(ptr_type->id == TypeTableEntryIdPointer);
1760 LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref,1763 TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
1761 size_val, "");1764
17621765 LLVMValueRef size_val = gen_expr(g, size_node);
1763 // store the freshly allocated pointer in the unknown size array struct1766
1764 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder,1767 add_debug_source_node(g, source_node);
1765 variable->value_ref, 0, "");1768 LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref,
1766 LLVMBuildStore(g->builder, ptr_val, ptr_field_ptr);1769 size_val, "");
17671770
1768 // store the size in the len field1771 // store the freshly allocated pointer in the unknown size array struct
1769 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder,1772 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder,
1770 variable->value_ref, 1, "");1773 variable->value_ref, 0, "");
1771 LLVMBuildStore(g->builder, size_val, len_field_ptr);1774 LLVMBuildStore(g->builder, ptr_val, ptr_field_ptr);
17721775
1773 // don't clobber what we just did with debug initialization1776 // store the size in the len field
1774 ignore_uninit = true;1777 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder,
1775 }1778 variable->value_ref, 1, "");
1779 LLVMBuildStore(g->builder, size_val, len_field_ptr);
1780
1781 // don't clobber what we just did with debug initialization
1782 ignore_uninit = true;
1776 }1783 }
1777 }1784 }
1778 if (!ignore_uninit && g->build_type != CodeGenBuildTypeRelease) {
1779 // memset uninitialized memory to 0xa
1780 add_debug_source_node(g, source_node);
1781 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
1782 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
1783 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, variable->value_ref, ptr_u8, "");
1784 LLVMValueRef byte_count = LLVMConstInt(LLVMIntType(g->pointer_size_bytes * 8),
1785 variable->type->size_in_bits / 8, false);
1786 LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(),
1787 variable->type->align_in_bits / 8, false);
1788 LLVMValueRef params[] = {
1789 dest_ptr,
1790 fill_char,
1791 byte_count,
1792 align_in_bytes,
1793 LLVMConstNull(LLVMInt1Type()), // is volatile
1794 };
1795
1796 LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, "");
1797 }
1798 }1785 }
1786 if (!ignore_uninit && g->build_type != CodeGenBuildTypeRelease) {
1787 // memset uninitialized memory to 0xa
1788 add_debug_source_node(g, source_node);
1789 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
1790 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
1791 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, variable->value_ref, ptr_u8, "");
1792 LLVMValueRef byte_count = LLVMConstInt(LLVMIntType(g->pointer_size_bytes * 8),
1793 variable->type->size_in_bits / 8, false);
1794 LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(),
1795 variable->type->align_in_bits / 8, false);
1796 LLVMValueRef params[] = {
1797 dest_ptr,
1798 fill_char,
1799 byte_count,
1800 align_in_bytes,
1801 LLVMConstNull(LLVMInt1Type()), // is volatile
1802 };
17991803
1800 LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(source_node->line + 1, source_node->column + 1,1804 LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, "");
1801 g->cur_block_context->di_scope);1805 }
1802 LLVMZigInsertDeclareAtEnd(g->dbuilder, variable->value_ref, variable->di_loc_var, debug_loc,
1803 LLVMGetInsertBlock(g->builder));
1804 return nullptr;
1805 }1806 }
1807
1808 LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(source_node->line + 1, source_node->column + 1,
1809 g->cur_block_context->di_scope);
1810 LLVMZigInsertDeclareAtEnd(g->dbuilder, variable->value_ref, variable->di_loc_var, debug_loc,
1811 LLVMGetInsertBlock(g->builder));
1812 return nullptr;
1806}1813}
18071814
1808static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {1815static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {
...@@ -2035,6 +2042,10 @@ static void build_label_blocks(CodeGen *g, AstNode *block_node) {...@@ -2035,6 +2042,10 @@ static void build_label_blocks(CodeGen *g, AstNode *block_node) {
2035static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {2042static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
2036 assert(const_val->ok);2043 assert(const_val->ok);
20372044
2045 if (const_val->undef) {
2046 return LLVMConstNull(type_entry->type_ref);
2047 }
2048
2038 if (type_entry->id == TypeTableEntryIdInt) {2049 if (type_entry->id == TypeTableEntryIdInt) {
2039 return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);2050 return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);
2040 } else if (type_entry->id == TypeTableEntryIdFloat) {2051 } else if (type_entry->id == TypeTableEntryIdFloat) {
...@@ -2389,6 +2400,11 @@ static void define_builtin_types(CodeGen *g) {...@@ -2389,6 +2400,11 @@ static void define_builtin_types(CodeGen *g) {
2389 buf_init_from_str(&entry->name, "(integer literal)");2400 buf_init_from_str(&entry->name, "(integer literal)");
2390 g->builtin_types.entry_num_lit_int = entry;2401 g->builtin_types.entry_num_lit_int = entry;
2391 }2402 }
2403 {
2404 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUndefLit);
2405 buf_init_from_str(&entry->name, "(undefined)");
2406 g->builtin_types.entry_undef = entry;
2407 }
23922408
2393 for (int i = 0; i < array_length(int_sizes_in_bits); i += 1) {2409 for (int i = 0; i < array_length(int_sizes_in_bits); i += 1) {
2394 int size_in_bits = int_sizes_in_bits[i];2410 int size_in_bits = int_sizes_in_bits[i];