authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-11 20:33:06-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-11 20:33:06-07:00
logccc8e9f4c328cb29fa7f21101d8c20fd23e4942a
treed26d3a0b31e281352b8327924e7aae4ffd095307
parent733830f8a5c7c1a3f24aaeda451114b839a7eba9

support enums with values attached


4 files changed, 243 insertions(+), 56 deletions(-)

src/all_types.hpp+4
...@@ -324,6 +324,7 @@ struct AstNodeFieldAccessExpr {...@@ -324,6 +324,7 @@ struct AstNodeFieldAccessExpr {
324 TypeStructField *type_struct_field;324 TypeStructField *type_struct_field;
325 TypeEnumField *type_enum_field;325 TypeEnumField *type_enum_field;
326 Expr resolved_expr;326 Expr resolved_expr;
327 StructValExprCodeGen resolved_struct_val_expr; // for enum values
327};328};
328329
329struct AstNodeExternBlock {330struct AstNodeExternBlock {
...@@ -718,8 +719,10 @@ struct TypeTableEntryMetaType {...@@ -718,8 +719,10 @@ struct TypeTableEntryMetaType {
718struct TypeTableEntryEnum {719struct TypeTableEntryEnum {
719 AstNode *decl_node;720 AstNode *decl_node;
720 uint32_t field_count;721 uint32_t field_count;
722 uint32_t gen_field_count;
721 TypeEnumField *fields;723 TypeEnumField *fields;
722 bool is_invalid; // true if any fields are invalid724 bool is_invalid; // true if any fields are invalid
725 TypeTableEntry *tag_type;
723726
724 // reminder: hash tables must be initialized before use727 // reminder: hash tables must be initialized before use
725 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;728 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
...@@ -916,6 +919,7 @@ struct CodeGen {...@@ -916,6 +919,7 @@ struct CodeGen {
916 ImportTableEntry *root_import;919 ImportTableEntry *root_import;
917 ImportTableEntry *bootstrap_import;920 ImportTableEntry *bootstrap_import;
918 LLVMValueRef memcpy_fn_val;921 LLVMValueRef memcpy_fn_val;
922 LLVMValueRef memset_fn_val;
919 bool error_during_imports;923 bool error_during_imports;
920};924};
921925
src/analyze.cpp+62-18
...@@ -465,6 +465,8 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,...@@ -465,6 +465,8 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
465 zig_panic("TODO eval_const_expr max_value");465 zig_panic("TODO eval_const_expr max_value");
466 } else if (buf_eql_str(name, "min_value")) {466 } else if (buf_eql_str(name, "min_value")) {
467 zig_panic("TODO eval_const_expr min_value");467 zig_panic("TODO eval_const_expr min_value");
468 } else if (buf_eql_str(name, "value_count")) {
469 zig_panic("TODO eval_const_expr value_count");
468 } else {470 } else {
469 return g->builtin_types.entry_invalid;471 return g->builtin_types.entry_invalid;
470 }472 }
...@@ -767,10 +769,13 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt...@@ -767,10 +769,13 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
767 enum_type->data.enumeration.embedded_in_current = false;769 enum_type->data.enumeration.embedded_in_current = false;
768770
769 if (!enum_type->data.enumeration.is_invalid) {771 if (!enum_type->data.enumeration.is_invalid) {
770 uint64_t tag_size_in_bits = get_number_literal_type_unsigned(g, field_count)->size_in_bits;772 enum_type->data.enumeration.gen_field_count = gen_field_index;
773
774 uint64_t tag_size_in_bits = num_lit_bit_count(get_number_literal_kind_unsigned(field_count));
771 enum_type->align_in_bits = tag_size_in_bits;775 enum_type->align_in_bits = tag_size_in_bits;
772 enum_type->size_in_bits = tag_size_in_bits + biggest_union_member_size_in_bits;776 enum_type->size_in_bits = tag_size_in_bits + biggest_union_member_size_in_bits;
773 TypeTableEntry *tag_type_entry = get_int_type_unsigned(g, field_count);777 TypeTableEntry *tag_type_entry = get_int_type_unsigned(g, field_count);
778 enum_type->data.enumeration.tag_type = tag_type_entry;
774779
775 if (biggest_union_member) {780 if (biggest_union_member) {
776 // create llvm type for union781 // create llvm type for union
...@@ -1520,22 +1525,20 @@ static TypeStructField *get_struct_field(TypeTableEntry *struct_type, Buf *name)...@@ -1520,22 +1525,20 @@ static TypeStructField *get_struct_field(TypeTableEntry *struct_type, Buf *name)
1520static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,1525static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1521 AstNode *field_access_node, AstNode *value_node, TypeTableEntry *enum_type, Buf *field_name)1526 AstNode *field_access_node, AstNode *value_node, TypeTableEntry *enum_type, Buf *field_name)
1522{1527{
1528 assert(field_access_node->type == NodeTypeFieldAccessExpr);
1529
1523 TypeEnumField *type_enum_field = get_enum_field(enum_type, field_name);1530 TypeEnumField *type_enum_field = get_enum_field(enum_type, field_name);
1524 field_access_node->data.field_access_expr.type_enum_field = type_enum_field;1531 field_access_node->data.field_access_expr.type_enum_field = type_enum_field;
1532
1525 if (type_enum_field) {1533 if (type_enum_field) {
1526 if (value_node) {1534 if (value_node) {
1527 if (type_enum_field->type_entry->id == TypeTableEntryIdVoid) {1535 analyze_expression(g, import, context, type_enum_field->type_entry, value_node);
1528 add_node_error(g, field_access_node,
1529 buf_sprintf("enum value '%s.%s' has void parameter",
1530 buf_ptr(&enum_type->name),
1531 buf_ptr(field_name)));
15321536
1533 } else {1537 StructValExprCodeGen *codegen = &field_access_node->data.field_access_expr.resolved_struct_val_expr;
1534 analyze_expression(g, import, context, type_enum_field->type_entry, value_node);1538 codegen->type_entry = enum_type;
1535 }1539 codegen->source_node = field_access_node;
1536 } else if (type_enum_field->type_entry->id == TypeTableEntryIdVoid) {1540 context->struct_val_expr_alloca_list.append(codegen);
1537 // OK1541 } else if (type_enum_field->type_entry->id != TypeTableEntryIdVoid) {
1538 } else {
1539 add_node_error(g, field_access_node,1542 add_node_error(g, field_access_node,
1540 buf_sprintf("enum value '%s.%s' requires parameter of type '%s'",1543 buf_sprintf("enum value '%s.%s' requires parameter of type '%s'",
1541 buf_ptr(&enum_type->name),1544 buf_ptr(&enum_type->name),
...@@ -2295,7 +2298,8 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, AstNode *node, TypeTabl...@@ -2295,7 +2298,8 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, AstNode *node, TypeTabl
2295{2298{
2296 if (type_entry->id == TypeTableEntryIdInt ||2299 if (type_entry->id == TypeTableEntryIdInt ||
2297 type_entry->id == TypeTableEntryIdFloat ||2300 type_entry->id == TypeTableEntryIdFloat ||
2298 type_entry->id == TypeTableEntryIdBool)2301 type_entry->id == TypeTableEntryIdBool ||
2302 type_entry->id == TypeTableEntryIdInvalid)
2299 {2303 {
2300 return type_entry;2304 return type_entry;
2301 } else {2305 } else {
...@@ -2314,15 +2318,38 @@ static TypeTableEntry *analyze_compiler_fn_type(CodeGen *g, ImportTableEntry *im...@@ -2314,15 +2318,38 @@ static TypeTableEntry *analyze_compiler_fn_type(CodeGen *g, ImportTableEntry *im
2314 TypeTableEntry *type_entry = resolve_type(g, node->data.compiler_fn_type.type, import, context, false);2318 TypeTableEntry *type_entry = resolve_type(g, node->data.compiler_fn_type.type, import, context, false);
23152319
2316 if (buf_eql_str(name, "sizeof")) {2320 if (buf_eql_str(name, "sizeof")) {
2317 uint64_t size_in_bytes = type_entry->size_in_bits / 8;2321 if (type_entry->id == TypeTableEntryIdInvalid) {
2322 return type_entry;
2323 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
2324 add_node_error(g, node,
2325 buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
2326 return g->builtin_types.entry_invalid;
2327 } else {
2328 uint64_t size_in_bytes = type_entry->size_in_bits / 8;
23182329
2319 TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, size_in_bytes);2330 TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, size_in_bytes);
2320 TypeTableEntry *resolved_type = resolve_rhs_number_literal(g, nullptr, expected_type, node, num_lit_type);2331 TypeTableEntry *resolved_type = resolve_rhs_number_literal(g, nullptr, expected_type, node, num_lit_type);
2321 return resolved_type ? resolved_type : num_lit_type;2332 return resolved_type ? resolved_type : num_lit_type;
2333 }
2322 } else if (buf_eql_str(name, "min_value")) {2334 } else if (buf_eql_str(name, "min_value")) {
2323 return analyze_min_max_value(g, node, type_entry, "no min value available for type '%s'");2335 return analyze_min_max_value(g, node, type_entry, "no min value available for type '%s'");
2324 } else if (buf_eql_str(name, "max_value")) {2336 } else if (buf_eql_str(name, "max_value")) {
2325 return analyze_min_max_value(g, node, type_entry, "no max value available for type '%s'");2337 return analyze_min_max_value(g, node, type_entry, "no max value available for type '%s'");
2338 } else if (buf_eql_str(name, "value_count")) {
2339 if (type_entry->id == TypeTableEntryIdInvalid) {
2340 return type_entry;
2341 } else if (type_entry->id == TypeTableEntryIdEnum) {
2342 uint64_t value_count = type_entry->data.enumeration.field_count;
2343
2344 TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, value_count);
2345 TypeTableEntry *resolved_type = resolve_rhs_number_literal(g, nullptr, expected_type, node, num_lit_type);
2346 return resolved_type ? resolved_type : num_lit_type;
2347
2348 } else {
2349 add_node_error(g, node,
2350 buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name)));
2351 return g->builtin_types.entry_invalid;
2352 }
2326 } else {2353 } else {
2327 add_node_error(g, node,2354 add_node_error(g, node,
2328 buf_sprintf("invalid compiler function: '%s'", buf_ptr(name)));2355 buf_sprintf("invalid compiler function: '%s'", buf_ptr(name)));
...@@ -2451,7 +2478,24 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import...@@ -2451,7 +2478,24 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
2451 } else if (struct_type->id == TypeTableEntryIdMetaType &&2478 } else if (struct_type->id == TypeTableEntryIdMetaType &&
2452 struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum)2479 struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum)
2453 {2480 {
2454 zig_panic("TODO enum initialization");2481 TypeTableEntry *enum_type = struct_type->data.meta_type.child_type;
2482 Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name;
2483 int param_count = node->data.fn_call_expr.params.length;
2484 if (param_count > 1) {
2485 add_node_error(g, first_executing_node(node->data.fn_call_expr.params.at(1)),
2486 buf_sprintf("enum values accept only one parameter"));
2487 return enum_type;
2488 } else {
2489 AstNode *value_node;
2490 if (param_count == 1) {
2491 value_node = node->data.fn_call_expr.params.at(0);
2492 } else {
2493 value_node = nullptr;
2494 }
2495
2496 return analyze_enum_value_expr(g, import, context, fn_ref_expr, value_node,
2497 enum_type, field_name);
2498 }
2455 } else {2499 } else {
2456 add_node_error(g, fn_ref_expr->data.field_access_expr.struct_expr,2500 add_node_error(g, fn_ref_expr->data.field_access_expr.struct_expr,
2457 buf_sprintf("member reference base type not struct or enum"));2501 buf_sprintf("member reference base type not struct or enum"));
src/codegen.cpp+127-36
...@@ -137,8 +137,13 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str, bool c) {...@@ -137,8 +137,13 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str, bool c) {
137137
138static TypeTableEntry *get_expr_type(AstNode *node) {138static TypeTableEntry *get_expr_type(AstNode *node) {
139 Expr *expr = get_resolved_expr(node);139 Expr *expr = get_resolved_expr(node);
140 TypeTableEntry *cast_type = expr->implicit_cast.after_type;140 if (expr->implicit_maybe_cast.after_type) {
141 return cast_type ? cast_type : expr->type_entry;141 return expr->implicit_maybe_cast.after_type;
142 }
143 if (expr->implicit_cast.after_type) {
144 return expr->implicit_cast.after_type;
145 }
146 return expr->type_entry;
142}147}
143148
144static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {149static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
...@@ -237,6 +242,51 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -237,6 +242,51 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
237 zig_unreachable();242 zig_unreachable();
238}243}
239244
245static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntry *enum_type,
246 AstNode *arg_node)
247{
248 assert(node->type == NodeTypeFieldAccessExpr);
249
250 uint64_t value = node->data.field_access_expr.type_enum_field->value;
251 LLVMTypeRef tag_type_ref = enum_type->data.enumeration.tag_type->type_ref;
252 LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, value, false);
253
254 if (enum_type->data.enumeration.gen_field_count == 0) {
255 return tag_value;
256 } else {
257 TypeTableEntry *arg_node_type = nullptr;
258 LLVMValueRef new_union_val = gen_expr(g, arg_node);
259 if (arg_node) {
260 arg_node_type = get_expr_type(arg_node);
261 new_union_val = gen_expr(g, arg_node);
262 } else {
263 arg_node_type = g->builtin_types.entry_void;
264 }
265
266 LLVMValueRef tmp_struct_ptr = node->data.field_access_expr.resolved_struct_val_expr.ptr;
267
268 // populate the new tag value
269 add_debug_source_node(g, node);
270 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
271 LLVMBuildStore(g->builder, tag_value, tag_field_ptr);
272
273 if (arg_node_type->id != TypeTableEntryIdVoid) {
274 // populate the union value
275 TypeTableEntry *union_val_type = get_expr_type(arg_node);
276 LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
277 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr,
278 LLVMPointerType(union_val_type->type_ref, 0), "");
279
280 gen_assign_raw(g, arg_node, BinOpTypeAssign, bitcasted_union_field_ptr, new_union_val,
281 union_val_type, union_val_type);
282
283 }
284
285 return tmp_struct_ptr;
286 }
287}
288
289
240static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {290static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
241 assert(node->type == NodeTypeFnCallExpr);291 assert(node->type == NodeTypeFnCallExpr);
242292
...@@ -253,6 +303,19 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -253,6 +303,19 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
253 } else if (struct_type->id == TypeTableEntryIdPointer) {303 } else if (struct_type->id == TypeTableEntryIdPointer) {
254 assert(struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct);304 assert(struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct);
255 fn_table_entry = struct_type->data.pointer.child_type->data.structure.fn_table.get(name);305 fn_table_entry = struct_type->data.pointer.child_type->data.structure.fn_table.get(name);
306 } else if (struct_type->id == TypeTableEntryIdMetaType &&
307 struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum)
308 {
309 TypeTableEntry *enum_type = struct_type->data.meta_type.child_type;
310 int param_count = node->data.fn_call_expr.params.length;
311 AstNode *arg1_node;
312 if (param_count == 1) {
313 arg1_node = node->data.fn_call_expr.params.at(0);
314 } else {
315 assert(param_count == 0);
316 arg1_node = nullptr;
317 }
318 return gen_enum_value_expr(g, fn_ref_expr, enum_type, arg1_node);
256 } else {319 } else {
257 zig_unreachable();320 zig_unreachable();
258 }321 }
...@@ -500,15 +563,6 @@ static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lva...@@ -500,15 +563,6 @@ static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lva
500 }563 }
501}564}
502565
503static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntry *enum_type) {
504 assert(node->type == NodeTypeFieldAccessExpr);
505
506 uint64_t value = node->data.field_access_expr.type_enum_field->value;
507 LLVMTypeRef tag_type_ref = enum_type->type_ref;
508
509 return LLVMConstInt(tag_type_ref, value, false);
510}
511
512static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {566static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
513 assert(node->type == NodeTypeFieldAccessExpr);567 assert(node->type == NodeTypeFieldAccessExpr);
514568
...@@ -546,7 +600,7 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva...@@ -546,7 +600,7 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva
546 {600 {
547 assert(!is_lvalue);601 assert(!is_lvalue);
548 TypeTableEntry *enum_type = struct_type->data.meta_type.child_type;602 TypeTableEntry *enum_type = struct_type->data.meta_type.child_type;
549 return gen_enum_value_expr(g, node, enum_type);603 return gen_enum_value_expr(g, node, enum_type, nullptr);
550 } else {604 } else {
551 zig_panic("gen_field_access_expr bad struct type");605 zig_panic("gen_field_access_expr bad struct type");
552 }606 }
...@@ -968,7 +1022,9 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {...@@ -968,7 +1022,9 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
968static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValueRef src, LLVMValueRef dest,1022static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValueRef src, LLVMValueRef dest,
969 TypeTableEntry *type_entry)1023 TypeTableEntry *type_entry)
970{1024{
971 assert(type_entry->id == TypeTableEntryIdStruct || type_entry->id == TypeTableEntryIdMaybe);1025 assert(type_entry->id == TypeTableEntryIdStruct ||
1026 type_entry->id == TypeTableEntryIdMaybe ||
1027 (type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0));
9721028
973 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);1029 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
9741030
...@@ -991,8 +1047,13 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b...@@ -991,8 +1047,13 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
991 LLVMValueRef target_ref, LLVMValueRef value,1047 LLVMValueRef target_ref, LLVMValueRef value,
992 TypeTableEntry *op1_type, TypeTableEntry *op2_type)1048 TypeTableEntry *op1_type, TypeTableEntry *op2_type)
993{1049{
994 if (op1_type->id == TypeTableEntryIdStruct) {1050 if (op1_type->id == TypeTableEntryIdStruct ||
995 assert(op2_type->id == TypeTableEntryIdStruct);1051 (op1_type->id == TypeTableEntryIdEnum && op1_type->data.enumeration.gen_field_count != 0) ||
1052 op1_type->id == TypeTableEntryIdMaybe)
1053 {
1054 assert(op2_type->id == TypeTableEntryIdStruct ||
1055 (op2_type->id == TypeTableEntryIdEnum && op2_type->data.enumeration.gen_field_count != 0) ||
1056 op2_type->id == TypeTableEntryIdMaybe);
996 assert(op1_type == op2_type);1057 assert(op1_type == op2_type);
997 assert(bin_op == BinOpTypeAssign);1058 assert(bin_op == BinOpTypeAssign);
9981059
...@@ -1546,32 +1607,48 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa...@@ -1546,32 +1607,48 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa
15461607
1547 if (var_decl->expr) {1608 if (var_decl->expr) {
1548 *init_value = gen_expr(g, var_decl->expr);1609 *init_value = gen_expr(g, var_decl->expr);
1549 } else {
1550 *init_value = LLVMConstNull(variable->type->type_ref);
1551 }1610 }
1552 if (variable->type->id == TypeTableEntryIdVoid) {1611 if (variable->type->id == TypeTableEntryIdVoid) {
1553 return nullptr;1612 return nullptr;
1554 } else {1613 } else {
1555 LLVMValueRef store_instr;1614 if (var_decl->expr) {
1556 LLVMValueRef value;1615 TypeTableEntry *expr_type = get_expr_type(var_decl->expr);
1557 if (unwrap_maybe) {1616 LLVMValueRef value;
1558 assert(var_decl->expr);1617 if (unwrap_maybe) {
1559 value = gen_unwrap_maybe(g, source_node, *init_value);1618 assert(var_decl->expr);
1560 } else {1619 assert(expr_type->id == TypeTableEntryIdMaybe);
1561 value = *init_value;1620 value = gen_unwrap_maybe(g, source_node, *init_value);
1562 }1621 expr_type = expr_type->data.maybe.child_type;
1563 if ((variable->type->id == TypeTableEntryIdStruct || variable->type->id == TypeTableEntryIdMaybe) &&1622 } else {
1564 var_decl->expr)1623 value = *init_value;
1565 {1624 }
1566 store_instr = gen_struct_memcpy(g, source_node, value, variable->value_ref, variable->type);1625 gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref,
1567 } else {1626 value, variable->type, expr_type);
1627 } else if (g->build_type != CodeGenBuildTypeRelease) {
1628 // memset uninitialized memory to 0xa
1568 add_debug_source_node(g, source_node);1629 add_debug_source_node(g, source_node);
1569 store_instr = LLVMBuildStore(g->builder, value, variable->value_ref);1630 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
1631 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
1632 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, variable->value_ref, ptr_u8, "");
1633 LLVMValueRef byte_count = LLVMConstInt(LLVMIntType(g->pointer_size_bytes * 8),
1634 variable->type->size_in_bits / 8, false);
1635 LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(),
1636 variable->type->align_in_bits / 8, false);
1637 LLVMValueRef params[] = {
1638 dest_ptr,
1639 fill_char,
1640 byte_count,
1641 align_in_bytes,
1642 LLVMConstNull(LLVMInt1Type()), // is volatile
1643 };
1644
1645 LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, "");
1570 }1646 }
15711647
1572 LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(source_node->line + 1, source_node->column + 1,1648 LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(source_node->line + 1, source_node->column + 1,
1573 g->cur_block_context->di_scope);1649 g->cur_block_context->di_scope);
1574 LLVMZigInsertDeclare(g->dbuilder, variable->value_ref, variable->di_loc_var, debug_loc, store_instr);1650 LLVMZigInsertDeclareAtEnd(g->dbuilder, variable->value_ref, variable->di_loc_var, debug_loc,
1651 LLVMGetInsertBlock(g->builder));
1575 return nullptr;1652 return nullptr;
1576 }1653 }
1577}1654}
...@@ -1644,6 +1721,17 @@ static LLVMValueRef gen_compiler_fn_type(CodeGen *g, AstNode *node) {...@@ -1644,6 +1721,17 @@ static LLVMValueRef gen_compiler_fn_type(CodeGen *g, AstNode *node) {
1644 } else {1721 } else {
1645 zig_unreachable();1722 zig_unreachable();
1646 }1723 }
1724 } else if (buf_eql_str(name, "value_count")) {
1725 if (type_entry->id == TypeTableEntryIdEnum) {
1726 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
1727 AstNodeNumberLiteral num_lit_node;
1728 num_lit_node.kind = type_entry->data.num_lit.kind;
1729 num_lit_node.overflow = false;
1730 num_lit_node.data.x_uint = type_entry->data.enumeration.field_count;
1731 return gen_number_literal_raw(g, node, codegen_num_lit, &num_lit_node);
1732 } else {
1733 zig_unreachable();
1734 }
1647 } else {1735 } else {
1648 zig_unreachable();1736 zig_unreachable();
1649 }1737 }
...@@ -2112,6 +2200,7 @@ static void define_builtin_types(CodeGen *g) {...@@ -2112,6 +2200,7 @@ static void define_builtin_types(CodeGen *g) {
2112 buf_resize(&entry->name, 0);2200 buf_resize(&entry->name, 0);
2113 buf_appendf(&entry->name, "(%s literal)", num_lit_str(num_lit_kind));2201 buf_appendf(&entry->name, "(%s literal)", num_lit_str(num_lit_kind));
2114 entry->data.num_lit.kind = num_lit_kind;2202 entry->data.num_lit.kind = num_lit_kind;
2203 entry->size_in_bits = num_lit_bit_count(num_lit_kind);
2115 g->num_lit_types[i] = entry;2204 g->num_lit_types[i] = entry;
2116 }2205 }
21172206
...@@ -2377,10 +2466,10 @@ static void define_builtin_fns(CodeGen *g) {...@@ -2377,10 +2466,10 @@ static void define_builtin_fns(CodeGen *g) {
2377 };2466 };
2378 LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 5, false);2467 LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 5, false);
2379 Buf *name = buf_sprintf("llvm.memcpy.p0i8.p0i8.i%d", g->pointer_size_bytes * 8);2468 Buf *name = buf_sprintf("llvm.memcpy.p0i8.p0i8.i%d", g->pointer_size_bytes * 8);
2380 g->memcpy_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);2469 builtin_fn->fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
2381 builtin_fn->fn_val = g->memcpy_fn_val;2470 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
2382 assert(LLVMGetIntrinsicID(g->memcpy_fn_val));
23832471
2472 g->memcpy_fn_val = builtin_fn->fn_val;
2384 g->builtin_fn_table.put(&builtin_fn->name, builtin_fn);2473 g->builtin_fn_table.put(&builtin_fn->name, builtin_fn);
2385 }2474 }
2386 {2475 {
...@@ -2406,6 +2495,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -2406,6 +2495,7 @@ static void define_builtin_fns(CodeGen *g) {
2406 builtin_fn->fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);2495 builtin_fn->fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
2407 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));2496 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
24082497
2498 g->memset_fn_val = builtin_fn->fn_val;
2409 g->builtin_fn_table.put(&builtin_fn->name, builtin_fn);2499 g->builtin_fn_table.put(&builtin_fn->name, builtin_fn);
2410 }2500 }
2411}2501}
...@@ -2658,7 +2748,8 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou...@@ -2658,7 +2748,8 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
2658 g->bootstrap_import = add_special_code(g, "bootstrap.zig");2748 g->bootstrap_import = add_special_code(g, "bootstrap.zig");
2659 }2749 }
26602750
2661 add_special_code(g, "builtin.zig");2751 // TODO re-enable this
2752 //add_special_code(g, "builtin.zig");
2662 }2753 }
26632754
2664 if (g->verbose) {2755 if (g->verbose) {
test/run_tests.cpp+50-2
...@@ -355,7 +355,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -355,7 +355,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
355use "std.zig";355use "std.zig";
356356
357pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {357pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
358 var zero : i32;358 var zero : i32 = 0;
359 if (zero == 0) { print_str("zero\n"); }359 if (zero == 0) { print_str("zero\n"); }
360360
361 var i = 0 as i32;361 var i = 0 as i32;
...@@ -619,6 +619,7 @@ use "std.zig";...@@ -619,6 +619,7 @@ use "std.zig";
619619
620pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {620pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
621 var foo : Foo;621 var foo : Foo;
622 @memset(&foo, 0, #sizeof(Foo));
622 foo.a += 1;623 foo.a += 1;
623 foo.b = foo.a == 1;624 foo.b = foo.a == 1;
624 test_foo(foo);625 test_foo(foo);
...@@ -689,7 +690,7 @@ fn test_initializer() {...@@ -689,7 +690,7 @@ fn test_initializer() {
689use "std.zig";690use "std.zig";
690691
691const g1 : i32 = 1233 + 1;692const g1 : i32 = 1233 + 1;
692var g2 : i32;693var g2 : i32 = 0;
693694
694pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {695pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
695 if (g2 != 0) { print_str("BAD\n"); }696 if (g2 != 0) { print_str("BAD\n"); }
...@@ -1044,6 +1045,53 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -1044,6 +1045,53 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
1044 return 0;1045 return 0;
1045}1046}
1046 )SOURCE", "OK\n");1047 )SOURCE", "OK\n");
1048
1049 add_simple_case("enum type", R"SOURCE(
1050use "std.zig";
1051
1052struct Point {
1053 x: u64,
1054 y: u64,
1055}
1056
1057enum Foo {
1058 One: i32,
1059 Two: Point,
1060 Three: void,
1061}
1062
1063enum Bar {
1064 A,
1065 B,
1066 C,
1067 D,
1068}
1069
1070pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
1071 const foo1 = Foo.One(13);
1072 const foo2 = Foo.Two(Point { .x = 1234, .y = 5678, });
1073 const bar = Bar.A;
1074
1075 if (#value_count(Foo) != 3) {
1076 print_str("BAD\n");
1077 }
1078
1079 if (#value_count(Bar) != 4) {
1080 print_str("BAD\n");
1081 }
1082
1083 if (#sizeof(Foo) != 17) {
1084 print_str("BAD\n");
1085 }
1086 if (#sizeof(Bar) != 1) {
1087 print_str("BAD\n");
1088 }
1089
1090 print_str("OK\n");
1091
1092 return 0;
1093}
1094 )SOURCE", "OK\n");
1047}1095}
10481096
10491097