authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-22 20:36:08-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-22 20:36:08-07:00
log21fc5a6402c527675900397ea60f107730985f1c
tree6b94e455082ed74aa0c4da45c0e6f6124b13b60c
parent1158bc3eadd8127301f96ecb9bcbb04cf04156b8

un-special case constant global strings


3 files changed, 120 insertions(+), 41 deletions(-)

src/all_types.hpp+12-2
...@@ -49,6 +49,16 @@ struct ConstStructValue {...@@ -49,6 +49,16 @@ struct ConstStructValue {
49 ConstExprValue **fields;49 ConstExprValue **fields;
50};50};
5151
52struct ConstArrayValue {
53 ConstExprValue **fields;
54};
55
56struct ConstPtrValue {
57 ConstExprValue **ptr;
58 // len should almost always be 1. exceptions include C strings
59 uint64_t len;
60};
61
52struct ConstExprValue {62struct ConstExprValue {
53 bool ok; // true if constant expression evalution worked63 bool ok; // true if constant expression evalution worked
54 bool depends_on_compile_var;64 bool depends_on_compile_var;
...@@ -61,6 +71,8 @@ struct ConstExprValue {...@@ -61,6 +71,8 @@ struct ConstExprValue {
61 ConstExprValue *x_maybe;71 ConstExprValue *x_maybe;
62 ConstEnumValue x_enum;72 ConstEnumValue x_enum;
63 ConstStructValue x_struct;73 ConstStructValue x_struct;
74 ConstArrayValue x_array;
75 ConstPtrValue x_ptr;
64 } data;76 } data;
65};77};
6678
...@@ -900,7 +912,6 @@ struct CodeGen {...@@ -900,7 +912,6 @@ struct CodeGen {
900 ZigList<Buf *> lib_search_paths;912 ZigList<Buf *> lib_search_paths;
901913
902 // reminder: hash tables must be initialized before use914 // reminder: hash tables must be initialized before use
903 HashMap<Buf *, LLVMValueRef, buf_hash, buf_eql_buf> str_table;
904 HashMap<Buf *, bool, buf_hash, buf_eql_buf> link_table;915 HashMap<Buf *, bool, buf_hash, buf_eql_buf> link_table;
905 HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;916 HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
906 HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;917 HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
...@@ -924,7 +935,6 @@ struct CodeGen {...@@ -924,7 +935,6 @@ struct CodeGen {
924 TypeTableEntry *entry_usize;935 TypeTableEntry *entry_usize;
925 TypeTableEntry *entry_f32;936 TypeTableEntry *entry_f32;
926 TypeTableEntry *entry_f64;937 TypeTableEntry *entry_f64;
927 TypeTableEntry *entry_c_string_literal;
928 TypeTableEntry *entry_void;938 TypeTableEntry *entry_void;
929 TypeTableEntry *entry_unreachable;939 TypeTableEntry *entry_unreachable;
930 TypeTableEntry *entry_type;940 TypeTableEntry *entry_type;
src/analyze.cpp+73-8
...@@ -1795,6 +1795,46 @@ static TypeTableEntry *resolve_expr_const_val_as_null(CodeGen *g, AstNode *node,...@@ -1795,6 +1795,46 @@ static TypeTableEntry *resolve_expr_const_val_as_null(CodeGen *g, AstNode *node,
1795 return type;1795 return type;
1796}1796}
17971797
1798static TypeTableEntry *resolve_expr_const_val_as_c_string_lit(CodeGen *g, AstNode *node, Buf *str) {
1799 Expr *expr = get_resolved_expr(node);
1800 expr->const_val.ok = true;
1801
1802 int len_with_null = buf_len(str) + 1;
1803 expr->const_val.data.x_ptr.ptr = allocate<ConstExprValue*>(len_with_null);
1804 expr->const_val.data.x_ptr.len = len_with_null;
1805
1806 ConstExprValue *all_chars = allocate<ConstExprValue>(len_with_null);
1807 for (int i = 0; i < buf_len(str); i += 1) {
1808 ConstExprValue *this_char = &all_chars[i];
1809 this_char->ok = true;
1810 bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);
1811 expr->const_val.data.x_ptr.ptr[i] = this_char;
1812 }
1813
1814 ConstExprValue *null_char = &all_chars[len_with_null - 1];
1815 null_char->ok = true;
1816 bignum_init_unsigned(&null_char->data.x_bignum, 0);
1817 expr->const_val.data.x_ptr.ptr[len_with_null - 1] = null_char;
1818
1819 return get_pointer_to_type(g, g->builtin_types.entry_u8, true);
1820}
1821
1822static TypeTableEntry *resolve_expr_const_val_as_string_lit(CodeGen *g, AstNode *node, Buf *str) {
1823 Expr *expr = get_resolved_expr(node);
1824 expr->const_val.ok = true;
1825 expr->const_val.data.x_array.fields = allocate<ConstExprValue*>(buf_len(str));
1826
1827 ConstExprValue *all_chars = allocate<ConstExprValue>(buf_len(str));
1828 for (int i = 0; i < buf_len(str); i += 1) {
1829 ConstExprValue *this_char = &all_chars[i];
1830 this_char->ok = true;
1831 bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);
1832 expr->const_val.data.x_array.fields[i] = this_char;
1833 }
1834 return get_array_type(g, g->builtin_types.entry_u8, buf_len(str));
1835}
1836
1837
1798static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,1838static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,
1799 TypeTableEntry *expected_type, uint64_t x)1839 TypeTableEntry *expected_type, uint64_t x)
1800{1840{
...@@ -2737,8 +2777,28 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex...@@ -2737,8 +2777,28 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex
2737 *const_val = *other_val;2777 *const_val = *other_val;
2738 break;2778 break;
2739 case CastOpToUnknownSizeArray:2779 case CastOpToUnknownSizeArray:
2740 zig_panic("TODO CastOpToUnknownSizeArray");2780 {
2741 break;2781 TypeTableEntry *other_type = get_resolved_expr(expr_node)->type_entry;
2782 assert(other_type->id == TypeTableEntryIdArray);
2783
2784 ConstExprValue *all_fields = allocate<ConstExprValue>(2);
2785 ConstExprValue *ptr_field = &all_fields[0];
2786 ConstExprValue *len_field = &all_fields[1];
2787
2788 const_val->data.x_struct.fields = allocate<ConstExprValue*>(2);
2789 const_val->data.x_struct.fields[0] = ptr_field;
2790 const_val->data.x_struct.fields[1] = len_field;
2791
2792 ptr_field->ok = true;
2793 ptr_field->data.x_ptr.ptr = other_val->data.x_array.fields;
2794 ptr_field->data.x_ptr.len = other_type->data.array.len;
2795
2796 len_field->ok = true;
2797 bignum_init_unsigned(&len_field->data.x_bignum, other_type->data.array.len);
2798
2799 const_val->ok = true;
2800 break;
2801 }
2742 case CastOpMaybeWrap:2802 case CastOpMaybeWrap:
2743 const_val->data.x_maybe = other_val;2803 const_val->data.x_maybe = other_val;
2744 const_val->ok = true;2804 const_val->ok = true;
...@@ -3422,6 +3482,16 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,...@@ -3422,6 +3482,16 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,
3422 return g->builtin_types.entry_unreachable;3482 return g->builtin_types.entry_unreachable;
3423}3483}
34243484
3485static TypeTableEntry *analyze_string_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3486 TypeTableEntry *expected_type, AstNode *node)
3487{
3488 if (node->data.string_literal.c) {
3489 return resolve_expr_const_val_as_c_string_lit(g, node, &node->data.string_literal.buf);
3490 } else {
3491 return resolve_expr_const_val_as_string_lit(g, node, &node->data.string_literal.buf);
3492 }
3493}
3494
3425// When you call analyze_expression, the node you pass might no longer be the child node3495// When you call analyze_expression, the node you pass might no longer be the child node
3426// you thought it was due to implicit casting rewriting the AST.3496// you thought it was due to implicit casting rewriting the AST.
3427static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,3497static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
...@@ -3544,12 +3614,7 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -3544,12 +3614,7 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
3544 return_type = analyze_error_literal_expr(g, import, context, expected_type, node);3614 return_type = analyze_error_literal_expr(g, import, context, expected_type, node);
3545 break;3615 break;
3546 case NodeTypeStringLiteral:3616 case NodeTypeStringLiteral:
3547 if (node->data.string_literal.c) {3617 return_type = analyze_string_literal_expr(g, import, context, expected_type, node);
3548 return_type = g->builtin_types.entry_c_string_literal;
3549 } else {
3550 return_type = get_array_type(g, g->builtin_types.entry_u8,
3551 buf_len(&node->data.string_literal.buf));
3552 }
3553 break;3618 break;
3554 case NodeTypeCharLiteral:3619 case NodeTypeCharLiteral:
3555 return_type = g->builtin_types.entry_u8;3620 return_type = g->builtin_types.entry_u8;
src/codegen.cpp+35-31
...@@ -19,7 +19,6 @@...@@ -19,7 +19,6 @@
1919
20CodeGen *codegen_create(Buf *root_source_dir) {20CodeGen *codegen_create(Buf *root_source_dir) {
21 CodeGen *g = allocate<CodeGen>(1);21 CodeGen *g = allocate<CodeGen>(1);
22 g->str_table.init(32);
23 g->link_table.init(32);22 g->link_table.init(32);
24 g->import_table.init(32);23 g->import_table.init(32);
25 g->builtin_fn_table.init(32);24 g->builtin_fn_table.init(32);
...@@ -92,22 +91,6 @@ static void add_debug_source_node(CodeGen *g, AstNode *node) {...@@ -92,22 +91,6 @@ static void add_debug_source_node(CodeGen *g, AstNode *node) {
92 g->cur_block_context->di_scope);91 g->cur_block_context->di_scope);
93}92}
9493
95static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str, bool c) {
96 auto entry = g->str_table.maybe_get(str);
97 if (entry) {
98 return entry->value;
99 }
100 LLVMValueRef text = LLVMConstString(buf_ptr(str), buf_len(str), !c);
101 LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(text), "");
102 LLVMSetLinkage(global_value, LLVMPrivateLinkage);
103 LLVMSetInitializer(global_value, text);
104 LLVMSetGlobalConstant(global_value, true);
105 LLVMSetUnnamedAddr(global_value, true);
106 g->str_table.put(str, global_value);
107
108 return global_value;
109}
110
111static TypeTableEntry *get_expr_type(AstNode *node) {94static TypeTableEntry *get_expr_type(AstNode *node) {
112 return get_resolved_expr(node)->type_entry;95 return get_resolved_expr(node)->type_entry;
113}96}
...@@ -1993,17 +1976,6 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -1993,17 +1976,6 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
1993 return gen_asm_expr(g, node);1976 return gen_asm_expr(g, node);
1994 case NodeTypeErrorLiteral:1977 case NodeTypeErrorLiteral:
1995 return gen_error_literal(g, node);1978 return gen_error_literal(g, node);
1996 case NodeTypeStringLiteral:
1997 {
1998 Buf *str = &node->data.string_literal.buf;
1999 LLVMValueRef str_val = find_or_create_string(g, str, node->data.string_literal.c);
2000 LLVMValueRef indices[] = {
2001 LLVMConstNull(g->builtin_types.entry_isize->type_ref),
2002 LLVMConstNull(g->builtin_types.entry_isize->type_ref),
2003 };
2004 LLVMValueRef ptr_val = LLVMBuildInBoundsGEP(g->builder, str_val, indices, 2, "");
2005 return ptr_val;
2006 }
2007 case NodeTypeCharLiteral:1979 case NodeTypeCharLiteral:
2008 return LLVMConstInt(LLVMInt8Type(), node->data.char_literal.value, false);1980 return LLVMConstInt(LLVMInt8Type(), node->data.char_literal.value, false);
2009 case NodeTypeSymbol:1981 case NodeTypeSymbol:
...@@ -2035,6 +2007,7 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -2035,6 +2007,7 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
2035 return gen_switch_expr(g, node);2007 return gen_switch_expr(g, node);
2036 case NodeTypeNumberLiteral:2008 case NodeTypeNumberLiteral:
2037 case NodeTypeBoolLiteral:2009 case NodeTypeBoolLiteral:
2010 case NodeTypeStringLiteral:
2038 // caught by constant expression eval codegen2011 // caught by constant expression eval codegen
2039 zig_unreachable();2012 zig_unreachable();
2040 case NodeTypeRoot:2013 case NodeTypeRoot:
...@@ -2117,7 +2090,14 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -2117,7 +2090,14 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
2117 }2090 }
2118 return LLVMConstNamedStruct(type_entry->type_ref, fields, type_entry->data.structure.gen_field_count);2091 return LLVMConstNamedStruct(type_entry->type_ref, fields, type_entry->data.structure.gen_field_count);
2119 } else if (type_entry->id == TypeTableEntryIdArray) {2092 } else if (type_entry->id == TypeTableEntryIdArray) {
2120 zig_panic("TODO");2093 TypeTableEntry *child_type = type_entry->data.array.child_type;
2094 uint64_t len = type_entry->data.array.len;
2095 LLVMValueRef *values = allocate<LLVMValueRef>(len);
2096 for (int i = 0; i < len; i += 1) {
2097 ConstExprValue *field_value = const_val->data.x_array.fields[i];
2098 values[i] = gen_const_val(g, child_type, field_value);
2099 }
2100 return LLVMConstArray(child_type->type_ref, values, len);
2121 } else if (type_entry->id == TypeTableEntryIdEnum) {2101 } else if (type_entry->id == TypeTableEntryIdEnum) {
2122 LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref;2102 LLVMTypeRef tag_type_ref = type_entry->data.enumeration.tag_type->type_ref;
2123 LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, const_val->data.x_enum.tag, false);2103 LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, const_val->data.x_enum.tag, false);
...@@ -2135,6 +2115,32 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -2135,6 +2115,32 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
2135 }2115 }
2136 } else if (type_entry->id == TypeTableEntryIdFn) {2116 } else if (type_entry->id == TypeTableEntryIdFn) {
2137 return const_val->data.x_fn->fn_value;2117 return const_val->data.x_fn->fn_value;
2118 } else if (type_entry->id == TypeTableEntryIdPointer) {
2119 TypeTableEntry *child_type = type_entry->data.pointer.child_type;
2120 int len = const_val->data.x_ptr.len;
2121 LLVMValueRef target_val;
2122 if (len == 1) {
2123 target_val = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[0]);
2124 } else if (len > 1) {
2125 LLVMValueRef *values = allocate<LLVMValueRef>(len);
2126 for (int i = 0; i < len; i += 1) {
2127 values[i] = gen_const_val(g, child_type, const_val->data.x_ptr.ptr[i]);
2128 }
2129 target_val = LLVMConstArray(child_type->type_ref, values, len);
2130 } else {
2131 zig_unreachable();
2132 }
2133 LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(target_val), "");
2134 LLVMSetInitializer(global_value, target_val);
2135 LLVMSetLinkage(global_value, LLVMPrivateLinkage);
2136 LLVMSetGlobalConstant(global_value, type_entry->data.pointer.is_const);
2137 LLVMSetUnnamedAddr(global_value, true);
2138
2139 if (len > 1) {
2140 return LLVMConstBitCast(global_value, type_entry->type_ref);
2141 } else {
2142 return global_value;
2143 }
2138 } else {2144 } else {
2139 zig_unreachable();2145 zig_unreachable();
2140 }2146 }
...@@ -2532,8 +2538,6 @@ static void define_builtin_types(CodeGen *g) {...@@ -2532,8 +2538,6 @@ static void define_builtin_types(CodeGen *g) {
2532 g->primitive_type_table.put(&entry->name, entry);2538 g->primitive_type_table.put(&entry->name, entry);
2533 }2539 }
25342540
2535 g->builtin_types.entry_c_string_literal = get_pointer_to_type(g, get_int_type(g, false, 8), true);
2536
2537 g->builtin_types.entry_u8 = get_int_type(g, false, 8);2541 g->builtin_types.entry_u8 = get_int_type(g, false, 8);
2538 g->builtin_types.entry_u16 = get_int_type(g, false, 16);2542 g->builtin_types.entry_u16 = get_int_type(g, false, 16);
2539 g->builtin_types.entry_u32 = get_int_type(g, false, 32);2543 g->builtin_types.entry_u32 = get_int_type(g, false, 32);