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 {
6262struct ConstExprValue {
6363 bool ok; // true if constant expression evalution worked
6464 bool depends_on_compile_var;
65 bool undef;
6566
6667 union {
6768 BigNum x_bignum;
......@@ -808,6 +809,7 @@ enum TypeTableEntryId {
808809 TypeTableEntryIdStruct,
809810 TypeTableEntryIdNumLitFloat,
810811 TypeTableEntryIdNumLitInt,
812 TypeTableEntryIdUndefLit,
811813 TypeTableEntryIdMaybe,
812814 TypeTableEntryIdError,
813815 TypeTableEntryIdEnum,
......@@ -949,6 +951,7 @@ struct CodeGen {
949951 TypeTableEntry *entry_invalid;
950952 TypeTableEntry *entry_num_lit_int;
951953 TypeTableEntry *entry_num_lit_float;
954 TypeTableEntry *entry_undef;
952955 } builtin_types;
953956
954957 LLVMTargetDataRef target_data_ref;
src/analyze.cpp+4-3
......@@ -111,6 +111,7 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
111111 case TypeTableEntryIdMaybe:
112112 case TypeTableEntryIdFn:
113113 case TypeTableEntryIdError:
114 case TypeTableEntryIdUndefLit:
114115 // nothing to init
115116 break;
116117 case TypeTableEntryIdStruct:
......@@ -1063,6 +1064,7 @@ static bool type_has_codegen_value(TypeTableEntryId id) {
10631064 case TypeTableEntryIdUnreachable:
10641065 case TypeTableEntryIdNumLitFloat:
10651066 case TypeTableEntryIdNumLitInt:
1067 case TypeTableEntryIdUndefLit:
10661068 return false;
10671069
10681070 case TypeTableEntryIdBool:
......@@ -2481,10 +2483,9 @@ static TypeTableEntry *analyze_undefined_literal_expr(CodeGen *g, ImportTableEnt
24812483 ConstExprValue *const_val = &expr->const_val;
24822484
24832485 const_val->ok = true;
2486 const_val->undef = true;
24842487
2485 zig_panic("TODO");
2486
2487 return expected_type;
2488 return expected_type ? expected_type : g->builtin_types.entry_undef;
24882489}
24892490
24902491
src/codegen.cpp+88-72
......@@ -1725,84 +1725,91 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa
17251725 }
17261726 if (variable->type->size_in_bits == 0) {
17271727 return nullptr;
1728 } else {
1729 if (var_decl->expr) {
1730 TypeTableEntry *expr_type = get_expr_type(var_decl->expr);
1731 LLVMValueRef value;
1732 if (unwrap_maybe) {
1733 assert(var_decl->expr);
1734 assert(expr_type->id == TypeTableEntryIdMaybe);
1735 value = gen_unwrap_maybe(g, source_node, *init_value);
1736 expr_type = expr_type->data.maybe.child_type;
1737 } else {
1738 value = *init_value;
1739 }
1740 gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref,
1741 value, variable->type, expr_type);
1728 }
1729
1730 bool have_init_expr = false;
1731 if (var_decl->expr) {
1732 ConstExprValue *const_val = &get_resolved_expr(var_decl->expr)->const_val;
1733 if (!const_val->ok || !const_val->undef) {
1734 have_init_expr = true;
1735 }
1736 }
1737 if (have_init_expr) {
1738 TypeTableEntry *expr_type = get_expr_type(var_decl->expr);
1739 LLVMValueRef value;
1740 if (unwrap_maybe) {
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;
17421745 } else {
1743 bool ignore_uninit = false;
1744 TypeTableEntry *var_type = get_type_for_type_node(var_decl->type);
1745 if (var_type->id == TypeTableEntryIdStruct &&
1746 var_type->data.structure.is_unknown_size_array)
1747 {
1748 assert(var_decl->type->type == NodeTypeArrayType);
1749 AstNode *size_node = var_decl->type->data.array_type.size;
1750 if (size_node) {
1751 ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
1752 if (!const_val->ok) {
1753 TypeTableEntry *ptr_type = var_type->data.structure.fields[0].type_entry;
1754 assert(ptr_type->id == TypeTableEntryIdPointer);
1755 TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
1756
1757 LLVMValueRef size_val = gen_expr(g, size_node);
1758
1759 add_debug_source_node(g, source_node);
1760 LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref,
1761 size_val, "");
1762
1763 // store the freshly allocated pointer in the unknown size array struct
1764 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder,
1765 variable->value_ref, 0, "");
1766 LLVMBuildStore(g->builder, ptr_val, ptr_field_ptr);
1767
1768 // store the size in the len field
1769 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder,
1770 variable->value_ref, 1, "");
1771 LLVMBuildStore(g->builder, size_val, len_field_ptr);
1772
1773 // don't clobber what we just did with debug initialization
1774 ignore_uninit = true;
1775 }
1746 value = *init_value;
1747 }
1748 gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref,
1749 value, variable->type, expr_type);
1750 } else {
1751 bool ignore_uninit = false;
1752 TypeTableEntry *var_type = get_type_for_type_node(var_decl->type);
1753 if (var_type->id == TypeTableEntryIdStruct &&
1754 var_type->data.structure.is_unknown_size_array)
1755 {
1756 assert(var_decl->type->type == NodeTypeArrayType);
1757 AstNode *size_node = var_decl->type->data.array_type.size;
1758 if (size_node) {
1759 ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
1760 if (!const_val->ok) {
1761 TypeTableEntry *ptr_type = var_type->data.structure.fields[0].type_entry;
1762 assert(ptr_type->id == TypeTableEntryIdPointer);
1763 TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
1764
1765 LLVMValueRef size_val = gen_expr(g, size_node);
1766
1767 add_debug_source_node(g, source_node);
1768 LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref,
1769 size_val, "");
1770
1771 // store the freshly allocated pointer in the unknown size array struct
1772 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder,
1773 variable->value_ref, 0, "");
1774 LLVMBuildStore(g->builder, ptr_val, ptr_field_ptr);
1775
1776 // store the size in the len field
1777 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder,
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;
17761783 }
17771784 }
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 }
17981785 }
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,
1801 g->cur_block_context->di_scope);
1802 LLVMZigInsertDeclareAtEnd(g->dbuilder, variable->value_ref, variable->di_loc_var, debug_loc,
1803 LLVMGetInsertBlock(g->builder));
1804 return nullptr;
1804 LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, "");
1805 }
18051806 }
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;
18061813}
18071814
18081815static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {
......@@ -2035,6 +2042,10 @@ static void build_label_blocks(CodeGen *g, AstNode *block_node) {
20352042static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
20362043 assert(const_val->ok);
20372044
2045 if (const_val->undef) {
2046 return LLVMConstNull(type_entry->type_ref);
2047 }
2048
20382049 if (type_entry->id == TypeTableEntryIdInt) {
20392050 return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false);
20402051 } else if (type_entry->id == TypeTableEntryIdFloat) {
......@@ -2389,6 +2400,11 @@ static void define_builtin_types(CodeGen *g) {
23892400 buf_init_from_str(&entry->name, "(integer literal)");
23902401 g->builtin_types.entry_num_lit_int = entry;
23912402 }
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
23932409 for (int i = 0; i < array_length(int_sizes_in_bits); i += 1) {
23942410 int size_in_bits = int_sizes_in_bits[i];