authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-15 04:45:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-15 04:45:25-07:00
logb0f608a6a76ff4ffd0455ec64fd8597ac0b860b9
treeee12336d63e13334e7ccc0a9f1c509a89ff82f69
parent0c9afede9e6216aa59cd69dd9ed1ca544e24df30

merge constant expression evaluator with analyzer


4 files changed, 603 insertions(+), 621 deletions(-)

doc/vim/syntax/zig.vim+3-3
...@@ -8,14 +8,14 @@ if exists("b:current_syntax")...@@ -8,14 +8,14 @@ if exists("b:current_syntax")
8endif8endif
99
10syn keyword zigStorage const var extern volatile export pub noalias10syn keyword zigStorage const var extern volatile export pub noalias
11syn keyword zigStructure struct enum type11syn keyword zigStructure struct enum
12syn keyword zigStatement goto break return continue asm12syn keyword zigStatement goto break return continue asm
13syn keyword zigConditional if else switch13syn keyword zigConditional if else switch
14syn keyword zigRepeat while for14syn keyword zigRepeat while for
1515
16syn keyword zigConstant null16syn keyword zigConstant null
17syn keyword zigKeyword fn use17syn keyword zigKeyword fn import
18syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 string void unreachable18syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 string void unreachable type
1919
20syn keyword zigBoolean true false20syn keyword zigBoolean true false
2121
src/all_types.hpp+18-27
...@@ -57,6 +57,21 @@ struct Cast {...@@ -57,6 +57,21 @@ struct Cast {
57 AstNode *source_node;57 AstNode *source_node;
58};58};
5959
60struct ConstExprValue {
61 bool ok; // true if constant expression evalution worked
62 bool depends_on_compile_var;
63
64 union {
65 uint64_t x_uint;
66 int64_t x_int;
67 double x_float;
68 bool x_bool;
69 FnTableEntry *x_fn;
70 TypeTableEntry *x_type;
71 ConstExprValue *x_maybe;
72 } data;
73};
74
60struct Expr {75struct Expr {
61 TypeTableEntry *type_entry;76 TypeTableEntry *type_entry;
62 // the context in which this expression is evaluated.77 // the context in which this expression is evaluated.
...@@ -66,6 +81,8 @@ struct Expr {...@@ -66,6 +81,8 @@ struct Expr {
66 // may be null for no cast81 // may be null for no cast
67 Cast implicit_cast; // happens first82 Cast implicit_cast; // happens first
68 Cast implicit_maybe_cast; // happens second83 Cast implicit_maybe_cast; // happens second
84
85 ConstExprValue const_val;
69};86};
7087
71struct NumLitCodeGen {88struct NumLitCodeGen {
...@@ -490,7 +507,6 @@ struct AstNodeNumberLiteral {...@@ -490,7 +507,6 @@ struct AstNodeNumberLiteral {
490507
491 union {508 union {
492 uint64_t x_uint;509 uint64_t x_uint;
493 int64_t x_int;
494 double x_float;510 double x_float;
495 } data;511 } data;
496512
...@@ -534,8 +550,6 @@ struct AstNodeSymbolExpr {...@@ -534,8 +550,6 @@ struct AstNodeSymbolExpr {
534 // populated by semantic analyzer550 // populated by semantic analyzer
535 Expr resolved_expr;551 Expr resolved_expr;
536 VariableTableEntry *variable;552 VariableTableEntry *variable;
537 TypeTableEntry *meta_type;
538 FnTableEntry *fn_entry;
539};553};
540554
541struct AstNodeBoolLiteral {555struct AstNodeBoolLiteral {
...@@ -670,10 +684,6 @@ struct TypeTableEntryMaybe {...@@ -670,10 +684,6 @@ struct TypeTableEntryMaybe {
670 TypeTableEntry *child_type;684 TypeTableEntry *child_type;
671};685};
672686
673struct TypeTableEntryMetaType {
674 TypeTableEntry *child_type;
675};
676
677struct TypeTableEntryEnum {687struct TypeTableEntryEnum {
678 AstNode *decl_node;688 AstNode *decl_node;
679 uint32_t field_count;689 uint32_t field_count;
...@@ -731,7 +741,6 @@ struct TypeTableEntry {...@@ -731,7 +741,6 @@ struct TypeTableEntry {
731 TypeTableEntryNumLit num_lit;741 TypeTableEntryNumLit num_lit;
732 TypeTableEntryMaybe maybe;742 TypeTableEntryMaybe maybe;
733 TypeTableEntryEnum enumeration;743 TypeTableEntryEnum enumeration;
734 TypeTableEntryMetaType meta_type;
735 TypeTableEntryFn fn;744 TypeTableEntryFn fn;
736 } data;745 } data;
737746
...@@ -740,7 +749,6 @@ struct TypeTableEntry {...@@ -740,7 +749,6 @@ struct TypeTableEntry {
740 TypeTableEntry *unknown_size_array_parent[2];749 TypeTableEntry *unknown_size_array_parent[2];
741 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;750 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;
742 TypeTableEntry *maybe_parent;751 TypeTableEntry *maybe_parent;
743 TypeTableEntry *meta_parent;
744};752};
745753
746struct ImporterInfo {754struct ImporterInfo {
...@@ -852,6 +860,7 @@ struct CodeGen {...@@ -852,6 +860,7 @@ struct CodeGen {
852 TypeTableEntry *entry_c_string_literal;860 TypeTableEntry *entry_c_string_literal;
853 TypeTableEntry *entry_void;861 TypeTableEntry *entry_void;
854 TypeTableEntry *entry_unreachable;862 TypeTableEntry *entry_unreachable;
863 TypeTableEntry *entry_type;
855 TypeTableEntry *entry_invalid;864 TypeTableEntry *entry_invalid;
856 } builtin_types;865 } builtin_types;
857866
...@@ -923,22 +932,4 @@ struct BlockContext {...@@ -923,22 +932,4 @@ struct BlockContext {
923 LLVMZigDIScope *di_scope;932 LLVMZigDIScope *di_scope;
924};933};
925934
926struct ConstExprValue {
927 bool ok; // true if constant expression evalution worked
928 bool depends_on_compile_var;
929
930 union {
931 uint64_t x_uint;
932 int64_t x_int;
933 double x_float;
934 bool x_bool;
935 FnTableEntry *x_fn;
936 TypeTableEntry *x_type;
937 struct {
938 bool is_null;
939 ConstExprValue *child_val;
940 } x_maybe;
941 } data;
942};
943
944#endif935#endif
src/analyze.cpp+563-577
...@@ -13,8 +13,6 @@...@@ -13,8 +13,6 @@
1313
14static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,14static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
15 TypeTableEntry *expected_type, AstNode *node);15 TypeTableEntry *expected_type, AstNode *node);
16static void eval_const_expr(CodeGen *g, BlockContext *context,
17 AstNode *node, ConstExprValue *out_val);
18static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,16static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,
19 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);17 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);
20static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);18static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);
...@@ -158,20 +156,6 @@ static TypeTableEntry *get_int_type_unsigned(CodeGen *g, uint64_t x) {...@@ -158,20 +156,6 @@ static TypeTableEntry *get_int_type_unsigned(CodeGen *g, uint64_t x) {
158 return get_int_type(g, false, num_lit_bit_count(get_number_literal_kind_unsigned(x)));156 return get_int_type(g, false, num_lit_bit_count(get_number_literal_kind_unsigned(x)));
159}157}
160158
161static TypeTableEntry *get_meta_type(CodeGen *g, TypeTableEntry *child_type) {
162 if (child_type->meta_parent) {
163 return child_type->meta_parent;
164 } else {
165 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdMetaType);
166 buf_resize(&entry->name, 0);
167 buf_appendf(&entry->name, "(%s declaration)", buf_ptr(&child_type->name));
168
169 entry->data.meta_type.child_type = child_type;
170 child_type->meta_parent = entry;
171 return entry;
172 }
173}
174
175TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {159TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
176 assert(child_type->id != TypeTableEntryIdInvalid);160 assert(child_type->id != TypeTableEntryIdInvalid);
177 TypeTableEntry **parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];161 TypeTableEntry **parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];
...@@ -327,301 +311,36 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry...@@ -327,301 +311,36 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry
327 }311 }
328}312}
329313
330// like analyze expression, but expects a type. creates an error if resulting type is314// If the node does not have a constant expression value with a metatype, generates an error
331// not a meta type. unwraps it if it is.315// and returns invalid type. Otherwise, returns the type of the constant expression value.
332static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,316// Must be called after analyze_expression on the same node.
333 AstNode *node)317static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {
334{318 Expr *expr = get_resolved_expr(node);
335 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, node);319 assert(expr->type_entry);
336 if (type_entry->id == TypeTableEntryIdInvalid) {320 if (expr->type_entry->id == TypeTableEntryIdInvalid) {
337 return type_entry;321 return g->builtin_types.entry_invalid;
338 } else if (type_entry->id == TypeTableEntryIdMetaType) {322 } else if (expr->type_entry->id == TypeTableEntryIdMetaType) {
339 return type_entry->data.meta_type.child_type;323 // OK
340 } else {324 } else {
341 add_node_error(g, first_executing_node(node),325 add_node_error(g, node, buf_sprintf("expected type, found expression"));
342 buf_sprintf("expected type, found expression"));
343 get_resolved_expr(node)->type_entry = g->builtin_types.entry_invalid;
344 return g->builtin_types.entry_invalid;326 return g->builtin_types.entry_invalid;
345 }327 }
346}
347
348static void eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
349 AstNode *node, ConstExprValue *out_val)
350{
351 AstNode *op1_node = node->data.bin_op_expr.op1;
352 AstNode *op2_node = node->data.bin_op_expr.op2;
353 ConstExprValue op1_val = {0};
354 ConstExprValue op2_val = {0};
355 eval_const_expr(g, context, op1_node, &op1_val);
356 eval_const_expr(g, context, op2_node, &op2_val);
357
358 if (!op1_val.ok || !op2_val.ok) {
359 return;
360 }
361328
362 TypeTableEntry *op1_type = get_resolved_expr(op1_node)->type_entry;329 ConstExprValue *const_val = &expr->const_val;
363 TypeTableEntry *op2_type = get_resolved_expr(op2_node)->type_entry;330 if (!const_val->ok) {
364331 add_node_error(g, node, buf_sprintf("unable to resolve constant expression"));
365 // TODO complete more of this function instead of returning invalid332 return g->builtin_types.entry_invalid;
366 // returning invalid makes the "unable to evaluate constant expression" error
367
368 switch (node->data.bin_op_expr.bin_op) {
369 case BinOpTypeCmpNotEq:
370 {
371 if (op1_type->id == TypeTableEntryIdInt &&
372 op2_type->id == TypeTableEntryIdInt)
373 {
374 out_val->data.x_bool = (op1_val.data.x_uint == op2_val.data.x_uint);
375 out_val->ok = true;
376 }
377 break;
378 }
379 case BinOpTypeCmpLessThan:
380 {
381 if (op1_type->id == TypeTableEntryIdInt &&
382 op2_type->id == TypeTableEntryIdInt)
383 {
384 if (op1_type->data.integral.is_signed &&
385 op2_type->data.integral.is_signed)
386 {
387 out_val->data.x_bool = (op1_val.data.x_int < op2_val.data.x_int);
388 out_val->ok = true;
389 } else if (!op1_type->data.integral.is_signed &&
390 !op2_type->data.integral.is_signed)
391 {
392 out_val->data.x_bool = (op1_val.data.x_uint < op2_val.data.x_uint);
393 out_val->ok = true;
394 }
395 }
396 break;
397 }
398 case BinOpTypeMod:
399 {
400 if (op1_type->id == TypeTableEntryIdInt &&
401 op2_type->id == TypeTableEntryIdInt)
402 {
403 if (op1_type->data.integral.is_signed &&
404 op2_type->data.integral.is_signed)
405 {
406 out_val->data.x_int = op1_val.data.x_int % op2_val.data.x_int;
407 out_val->ok = true;
408 } else if (!op1_type->data.integral.is_signed &&
409 !op2_type->data.integral.is_signed)
410 {
411 out_val->data.x_uint = op1_val.data.x_uint % op2_val.data.x_uint;
412 out_val->ok = true;
413 }
414 }
415 break;
416 }
417 case BinOpTypeBoolOr:
418 case BinOpTypeBoolAnd:
419 case BinOpTypeCmpEq:
420 case BinOpTypeCmpGreaterThan:
421 case BinOpTypeCmpLessOrEq:
422 case BinOpTypeCmpGreaterOrEq:
423 case BinOpTypeBinOr:
424 case BinOpTypeBinXor:
425 case BinOpTypeBinAnd:
426 case BinOpTypeBitShiftLeft:
427 case BinOpTypeBitShiftRight:
428 case BinOpTypeAdd:
429 case BinOpTypeSub:
430 case BinOpTypeMult:
431 case BinOpTypeDiv:
432 case BinOpTypeUnwrapMaybe:
433 break;
434 case BinOpTypeInvalid:
435 case BinOpTypeAssign:
436 case BinOpTypeAssignTimes:
437 case BinOpTypeAssignDiv:
438 case BinOpTypeAssignMod:
439 case BinOpTypeAssignPlus:
440 case BinOpTypeAssignMinus:
441 case BinOpTypeAssignBitShiftLeft:
442 case BinOpTypeAssignBitShiftRight:
443 case BinOpTypeAssignBitAnd:
444 case BinOpTypeAssignBitXor:
445 case BinOpTypeAssignBitOr:
446 case BinOpTypeAssignBoolAnd:
447 case BinOpTypeAssignBoolOr:
448 zig_unreachable();
449 }
450}
451
452static void eval_const_expr_builtin(CodeGen *g, BlockContext *context, AstNode *node, ConstExprValue *out_val) {
453 switch (node->data.fn_call_expr.builtin_fn->id) {
454 case BuiltinFnIdInvalid:
455 zig_unreachable();
456 case BuiltinFnIdAddWithOverflow:
457 case BuiltinFnIdSubWithOverflow:
458 case BuiltinFnIdMulWithOverflow:
459 case BuiltinFnIdMemcpy:
460 case BuiltinFnIdMemset:
461 break;
462 case BuiltinFnIdSizeof:
463 {
464 AstNode *type_node = node->data.fn_call_expr.params.at(0);
465 TypeTableEntry *target_type = unwrapped_node_type(type_node);
466 out_val->data.x_uint = target_type->size_in_bits / 8;
467 out_val->ok = true;
468 break;
469 }
470 case BuiltinFnIdMaxValue:
471 case BuiltinFnIdMinValue:
472 zig_panic("TODO eval_const_expr_fn_call max/min value");
473 case BuiltinFnIdValueCount:
474 zig_panic("TODO eval_const_expr_fn_call value_count");
475 case BuiltinFnIdTypeof:
476 // TODO
477 out_val->ok = true;
478 break;
479 }
480}
481
482static void eval_const_expr_fn_call_known(CodeGen *g, BlockContext *context,
483 AstNode *node, ConstExprValue *out_val)
484{
485 // currently no functions can be constant expression evaluated,
486 // so we do nothing
487}
488
489static void eval_const_expr_fn_call_cast(CodeGen *g, BlockContext *context,
490 AstNode *node, ConstExprValue *out_val)
491{
492 assert(node->type == NodeTypeFnCallExpr);
493 AstNode *expr_node = node->data.fn_call_expr.params.at(0);
494 Cast *cast = &node->data.fn_call_expr.cast;
495 switch (cast->op) {
496 case CastOpNothing:
497 case CastOpPtrToInt:
498 case CastOpPointerReinterpret:
499 case CastOpIntWidenOrShorten:
500 {
501 eval_const_expr(g, context, expr_node, out_val);
502 break;
503 }
504 case CastOpMaybeWrap:
505 {
506 ConstExprValue *child_val = allocate<ConstExprValue>(1);
507 eval_const_expr(g, context, expr_node, child_val);
508 if (!child_val->ok) {
509 return;
510 }
511 out_val->data.x_maybe.child_val = child_val;
512 out_val->data.x_maybe.is_null = false;
513 out_val->ok = true;
514 break;
515 }
516 case CastOpToUnknownSizeArray:
517 zig_panic("TODO eval_const_expr CastOpToUnknownSizeArray");
518 }333 }
519}
520334
521static void eval_const_expr_fn_call(CodeGen *g, BlockContext *context,335 return const_val->data.x_type;
522 AstNode *node, ConstExprValue *out_val)
523{
524 if (node->data.fn_call_expr.is_builtin) {
525 return eval_const_expr_builtin(g, context, node, out_val);
526 }
527 if (node->data.fn_call_expr.fn_entry) {
528 return eval_const_expr_fn_call_known(g, context, node, out_val);
529 }
530 return eval_const_expr_fn_call_cast(g, context, node, out_val);
531}336}
532337
533static void eval_const_expr_prefix_op_expr(CodeGen *g, BlockContext *context, AstNode *node,338// Calls analyze_expression on node, and then resolve_type.
534 ConstExprValue *out_val)339static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
340 AstNode *node)
535{341{
536 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;342 analyze_expression(g, import, context, nullptr, node);
537 switch (node->data.prefix_op_expr.prefix_op) {343 return resolve_type(g, node);
538 case PrefixOpInvalid:
539 zig_unreachable();
540 case PrefixOpBoolNot:
541 {
542 eval_const_expr(g, context, expr_node, out_val);
543 if (out_val->ok) {
544 out_val->data.x_bool = !out_val->data.x_bool;
545 }
546 break;
547 }
548 case PrefixOpBinNot:
549 break;
550 case PrefixOpNegation:
551 break;
552 case PrefixOpAddressOf:
553 {
554 if (get_resolved_expr(node)->type_entry->id == TypeTableEntryIdMetaType) {
555 eval_const_expr(g, context, expr_node, out_val);
556 }
557 break;
558 }
559 case PrefixOpConstAddressOf:
560 break;
561 case PrefixOpDereference:
562 break;
563 case PrefixOpMaybe:
564 break;
565 }
566}
567
568static void eval_const_expr(CodeGen *g, BlockContext *context, AstNode *node, ConstExprValue *out_val) {
569 switch (node->type) {
570 case NodeTypeNumberLiteral:
571 {
572 if (is_num_lit_unsigned(node->data.number_literal.kind)) {
573 out_val->data.x_uint = node->data.number_literal.data.x_uint;
574 out_val->ok = true;
575 } else if (is_num_lit_float(node->data.number_literal.kind)) {
576 out_val->data.x_uint = node->data.number_literal.data.x_float;
577 out_val->ok = true;
578 }
579 break;
580 }
581 case NodeTypeBoolLiteral:
582 out_val->data.x_uint = node->data.bool_literal.value ? 1 : 0;
583 out_val->ok = true;
584 break;
585 case NodeTypeNullLiteral:
586 out_val->data.x_maybe.is_null = true;
587 out_val->ok = true;
588 break;
589 case NodeTypeBinOpExpr:
590 eval_const_expr_bin_op(g, context, node, out_val);
591 break;
592 case NodeTypeSymbol:
593 {
594 VariableTableEntry *var = node->data.symbol_expr.variable;
595 if (var) {
596 if (var->is_const) {
597 AstNode *decl_node = var->decl_node;
598 if (decl_node->type == NodeTypeVariableDeclaration) {
599 AstNode *expr_node = decl_node->data.variable_declaration.expr;
600 if (expr_node) {
601 BlockContext *next_context = get_resolved_expr(expr_node)->block_context;
602 eval_const_expr(g, next_context, expr_node, out_val);
603 }
604 }
605 }
606 } else if (node->data.symbol_expr.meta_type) {
607 out_val->ok = true;
608 } else if (node->data.symbol_expr.fn_entry) {
609 out_val->ok = true;
610 out_val->data.x_fn = node->data.symbol_expr.fn_entry;
611 } else {
612 zig_unreachable();
613 }
614 break;
615 }
616 case NodeTypeFnCallExpr:
617 eval_const_expr_fn_call(g, context, node, out_val);
618 break;
619 case NodeTypePrefixOpExpr:
620 eval_const_expr_prefix_op_expr(g, context, node, out_val);
621 break;
622 default:
623 break;
624 }
625}344}
626345
627static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry,346static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry,
...@@ -662,9 +381,8 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -662,9 +381,8 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
662381
663 fn_table_entry->type_entry = fn_type;382 fn_table_entry->type_entry = fn_type;
664383
665 Buf *name = &node->data.fn_proto.name;
666 buf_resize(&fn_type->name, 0);384 buf_resize(&fn_type->name, 0);
667 buf_appendf(&fn_type->name, "fn %s(", buf_ptr(name));385 buf_appendf(&fn_type->name, "fn(");
668 for (int i = 0; i < param_count; i += 1) {386 for (int i = 0; i < param_count; i += 1) {
669 AstNode *child = node->data.fn_proto.params.at(i);387 AstNode *child = node->data.fn_proto.params.at(i);
670 assert(child->type == NodeTypeParamDecl);388 assert(child->type == NodeTypeParamDecl);
...@@ -672,8 +390,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -672,8 +390,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
672 child->data.param_decl.type);390 child->data.param_decl.type);
673 fn_table_entry->type_entry->data.fn.param_types[i] = type_entry;391 fn_table_entry->type_entry->data.fn.param_types[i] = type_entry;
674392
675 buf_appendf(&fn_type->name, "%s : %s",393 buf_appendf(&fn_type->name, "%s", buf_ptr(&type_entry->name));
676 buf_ptr(&child->data.param_decl.name), buf_ptr(&type_entry->name));
677394
678 if (i + 1 < param_count) {395 if (i + 1 < param_count) {
679 buf_appendf(&fn_type->name, ", ");396 buf_appendf(&fn_type->name, ", ");
...@@ -1212,13 +929,14 @@ static FnTableEntry *get_context_fn_entry(BlockContext *context) {...@@ -1212,13 +929,14 @@ static FnTableEntry *get_context_fn_entry(BlockContext *context) {
1212}929}
1213930
1214static TypeTableEntry *unwrapped_node_type(AstNode *node) {931static TypeTableEntry *unwrapped_node_type(AstNode *node) {
1215 TypeTableEntry *meta_type_entry = get_resolved_expr(node)->type_entry;932 Expr *expr = get_resolved_expr(node);
1216 if (meta_type_entry->id == TypeTableEntryIdInvalid) {933 if (expr->type_entry->id == TypeTableEntryIdInvalid) {
1217 return meta_type_entry;934 return expr->type_entry;
1218 } else {
1219 assert(meta_type_entry->id == TypeTableEntryIdMetaType);
1220 return meta_type_entry->data.meta_type.child_type;
1221 }935 }
936 assert(expr->type_entry->id == TypeTableEntryIdMetaType);
937 ConstExprValue *const_val = &expr->const_val;
938 assert(const_val->ok);
939 return const_val->data.x_type;
1222}940}
1223941
1224static TypeTableEntry *get_return_type(BlockContext *context) {942static TypeTableEntry *get_return_type(BlockContext *context) {
...@@ -1704,8 +1422,6 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i...@@ -1704,8 +1422,6 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
1704 AstNode *struct_expr_node = node->data.field_access_expr.struct_expr;1422 AstNode *struct_expr_node = node->data.field_access_expr.struct_expr;
1705 TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, struct_expr_node);1423 TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, struct_expr_node);
17061424
1707 TypeTableEntry *return_type;
1708
1709 if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&1425 if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
1710 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))1426 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
1711 {1427 {
...@@ -1716,40 +1432,45 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i...@@ -1716,40 +1432,45 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
17161432
1717 node->data.field_access_expr.type_struct_field = get_struct_field(bare_struct_type, field_name);1433 node->data.field_access_expr.type_struct_field = get_struct_field(bare_struct_type, field_name);
1718 if (node->data.field_access_expr.type_struct_field) {1434 if (node->data.field_access_expr.type_struct_field) {
1719 return_type = node->data.field_access_expr.type_struct_field->type_entry;1435 return node->data.field_access_expr.type_struct_field->type_entry;
1720 } else {1436 } else {
1721 add_node_error(g, node,1437 add_node_error(g, node,
1722 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&struct_type->name)));1438 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&struct_type->name)));
1723 return_type = g->builtin_types.entry_invalid;1439 return g->builtin_types.entry_invalid;
1724 }1440 }
1725 } else if (struct_type->id == TypeTableEntryIdArray) {1441 } else if (struct_type->id == TypeTableEntryIdArray) {
1726 Buf *name = &node->data.field_access_expr.field_name;1442 Buf *name = &node->data.field_access_expr.field_name;
1727 if (buf_eql_str(name, "len")) {1443 if (buf_eql_str(name, "len")) {
1728 return_type = g->builtin_types.entry_usize;1444 return g->builtin_types.entry_usize;
1729 } else if (buf_eql_str(name, "ptr")) {1445 } else if (buf_eql_str(name, "ptr")) {
1730 // TODO determine whether the pointer should be const1446 // TODO determine whether the pointer should be const
1731 return_type = get_pointer_to_type(g, struct_type->data.array.child_type, false);1447 return get_pointer_to_type(g, struct_type->data.array.child_type, false);
1732 } else {1448 } else {
1733 add_node_error(g, node,1449 add_node_error(g, node,
1734 buf_sprintf("no member named '%s' in '%s'", buf_ptr(name),1450 buf_sprintf("no member named '%s' in '%s'", buf_ptr(name),
1735 buf_ptr(&struct_type->name)));1451 buf_ptr(&struct_type->name)));
1736 return_type = g->builtin_types.entry_invalid;1452 return g->builtin_types.entry_invalid;
1453 }
1454 } else if (struct_type->id == TypeTableEntryIdMetaType) {
1455 TypeTableEntry *enum_type = resolve_type(g, struct_expr_node);
1456
1457 if (enum_type->id == TypeTableEntryIdInvalid) {
1458 return g->builtin_types.entry_invalid;
1459 } else if (enum_type->id == TypeTableEntryIdEnum) {
1460 Buf *field_name = &node->data.field_access_expr.field_name;
1461 return analyze_enum_value_expr(g, import, context, node, nullptr, enum_type, field_name);
1462 } else {
1463 add_node_error(g, node,
1464 buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name)));
1465 return g->builtin_types.entry_invalid;
1737 }1466 }
1738 } else if (struct_type->id == TypeTableEntryIdMetaType &&
1739 struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum)
1740 {
1741 TypeTableEntry *enum_type = struct_type->data.meta_type.child_type;
1742 Buf *field_name = &node->data.field_access_expr.field_name;
1743 return_type = analyze_enum_value_expr(g, import, context, node, nullptr, enum_type, field_name);
1744 } else {1467 } else {
1745 if (struct_type->id != TypeTableEntryIdInvalid) {1468 if (struct_type->id != TypeTableEntryIdInvalid) {
1746 add_node_error(g, node,1469 add_node_error(g, node,
1747 buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name)));1470 buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name)));
1748 }1471 }
1749 return_type = g->builtin_types.entry_invalid;1472 return g->builtin_types.entry_invalid;
1750 }1473 }
1751
1752 return return_type;
1753}1474}
17541475
1755static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,1476static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
...@@ -1826,6 +1547,52 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i...@@ -1826,6 +1547,52 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i
1826 return return_type;1547 return return_type;
1827}1548}
18281549
1550static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type) {
1551 Expr *expr = get_resolved_expr(node);
1552 expr->const_val.ok = true;
1553 expr->const_val.data.x_type = type;
1554 return g->builtin_types.entry_type;
1555}
1556
1557static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode *node, AstNode *other) {
1558 Expr *expr = get_resolved_expr(node);
1559 Expr *other_expr = get_resolved_expr(other);
1560 expr->const_val = other_expr->const_val;
1561 return other_expr->type_entry;
1562}
1563
1564static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn) {
1565 Expr *expr = get_resolved_expr(node);
1566 expr->const_val.ok = true;
1567 expr->const_val.data.x_fn = fn;
1568 return fn->type_entry;
1569}
1570
1571static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node, bool value) {
1572 Expr *expr = get_resolved_expr(node);
1573 expr->const_val.ok = true;
1574 expr->const_val.data.x_bool = value;
1575 return g->builtin_types.entry_bool;
1576}
1577
1578static TypeTableEntry *resolve_expr_const_val_as_null(CodeGen *g, AstNode *node, TypeTableEntry *type) {
1579 Expr *expr = get_resolved_expr(node);
1580 expr->const_val.ok = true;
1581 expr->const_val.data.x_maybe = nullptr;
1582 return type;
1583}
1584
1585static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,
1586 TypeTableEntry *expected_type, uint64_t x)
1587{
1588 Expr *expr = get_resolved_expr(node);
1589 expr->const_val.ok = true;
1590 expr->const_val.data.x_uint = x;
1591 TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, x);
1592 TypeTableEntry *resolved_type = resolve_rhs_number_literal(g, nullptr, expected_type, node, num_lit_type);
1593 return resolved_type ? resolved_type : num_lit_type;
1594}
1595
1829static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,1596static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1830 TypeTableEntry *expected_type, AstNode *node)1597 TypeTableEntry *expected_type, AstNode *node)
1831{1598{
...@@ -1833,28 +1600,33 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,...@@ -1833,28 +1600,33 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
18331600
1834 auto primitive_table_entry = g->primitive_type_table.maybe_get(variable_name);1601 auto primitive_table_entry = g->primitive_type_table.maybe_get(variable_name);
1835 if (primitive_table_entry) {1602 if (primitive_table_entry) {
1836 TypeTableEntry *meta_type = get_meta_type(g, primitive_table_entry->value);1603 return resolve_expr_const_val_as_type(g, node, primitive_table_entry->value);
1837 node->data.symbol_expr.meta_type = meta_type;
1838 return meta_type;
1839 }1604 }
18401605
1841 VariableTableEntry *var = find_variable(context, variable_name);1606 VariableTableEntry *var = find_variable(context, variable_name);
1842 if (var) {1607 if (var) {
1843 node->data.symbol_expr.variable = var;1608 node->data.symbol_expr.variable = var;
1609 if (var->is_const) {
1610 AstNode *decl_node = var->decl_node;
1611 if (decl_node->type == NodeTypeVariableDeclaration) {
1612 AstNode *expr_node = decl_node->data.variable_declaration.expr;
1613 ConstExprValue *const_val = &get_resolved_expr(expr_node)->const_val;
1614 if (const_val->ok) {
1615 return resolve_expr_const_val_as_other_expr(g, node, expr_node);
1616 }
1617 }
1618 }
1844 return var->type;1619 return var->type;
1845 }1620 }
18461621
1847 TypeTableEntry *container_type = find_container(context, variable_name);1622 TypeTableEntry *container_type = find_container(context, variable_name);
1848 if (container_type) {1623 if (container_type) {
1849 TypeTableEntry *meta_type = get_meta_type(g, container_type);1624 return resolve_expr_const_val_as_type(g, node, container_type);
1850 node->data.symbol_expr.meta_type = meta_type;
1851 return meta_type;
1852 }1625 }
18531626
1854 auto fn_table_entry = import->fn_table.maybe_get(variable_name);1627 auto fn_table_entry = import->fn_table.maybe_get(variable_name);
1855 if (fn_table_entry) {1628 if (fn_table_entry) {
1856 node->data.symbol_expr.fn_entry = fn_table_entry->value;1629 return resolve_expr_const_val_as_fn(g, node, fn_table_entry->value);
1857 return node->data.symbol_expr.fn_entry->type_entry;
1858 }1630 }
18591631
1860 add_node_error(g, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));1632 add_node_error(g, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
...@@ -1990,10 +1762,148 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc...@@ -1990,10 +1762,148 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
1990 return expected_rhs_type;1762 return expected_rhs_type;
1991}1763}
19921764
1765static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) {
1766 if (bin_op == BinOpTypeBoolOr) {
1767 return a || b;
1768 } else if (bin_op == BinOpTypeBoolAnd) {
1769 return a && b;
1770 } else {
1771 zig_unreachable();
1772 }
1773}
1774
1775static bool eval_bool_bin_op_signed(int64_t a, BinOpType bin_op, int64_t b) {
1776 if (bin_op == BinOpTypeCmpEq) {
1777 return a == b;
1778 } else if (bin_op == BinOpTypeCmpNotEq) {
1779 return a != b;
1780 } else if (bin_op == BinOpTypeCmpLessThan) {
1781 return a < b;
1782 } else if (bin_op == BinOpTypeCmpGreaterThan) {
1783 return a > b;
1784 } else if (bin_op == BinOpTypeCmpLessOrEq) {
1785 return a <= b;
1786 } else if (bin_op == BinOpTypeCmpGreaterOrEq) {
1787 return a >= b;
1788 } else {
1789 zig_unreachable();
1790 }
1791}
1792
1793static bool eval_bool_bin_op_unsigned(uint64_t a, BinOpType bin_op, uint64_t b) {
1794 if (bin_op == BinOpTypeCmpEq) {
1795 return a == b;
1796 } else if (bin_op == BinOpTypeCmpNotEq) {
1797 return a != b;
1798 } else if (bin_op == BinOpTypeCmpLessThan) {
1799 return a < b;
1800 } else if (bin_op == BinOpTypeCmpGreaterThan) {
1801 return a > b;
1802 } else if (bin_op == BinOpTypeCmpLessOrEq) {
1803 return a <= b;
1804 } else if (bin_op == BinOpTypeCmpGreaterOrEq) {
1805 return a >= b;
1806 } else {
1807 zig_unreachable();
1808 }
1809}
1810
1811static bool eval_bool_bin_op_float(double a, BinOpType bin_op, double b) {
1812 if (bin_op == BinOpTypeCmpEq) {
1813 return a == b;
1814 } else if (bin_op == BinOpTypeCmpNotEq) {
1815 return a != b;
1816 } else if (bin_op == BinOpTypeCmpLessThan) {
1817 return a < b;
1818 } else if (bin_op == BinOpTypeCmpGreaterThan) {
1819 return a > b;
1820 } else if (bin_op == BinOpTypeCmpLessOrEq) {
1821 return a <= b;
1822 } else if (bin_op == BinOpTypeCmpGreaterOrEq) {
1823 return a >= b;
1824 } else {
1825 zig_unreachable();
1826 }
1827}
1828
1829static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1830 AstNode *node)
1831{
1832 assert(node->type == NodeTypeBinOpExpr);
1833 BinOpType bin_op_type = node->data.bin_op_expr.bin_op;
1834
1835 AstNode *op1 = node->data.bin_op_expr.op1;
1836 AstNode *op2 = node->data.bin_op_expr.op2;
1837 TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, op1);
1838 TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, op2);
1839
1840 TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, context, node,
1841 op1, op2, op1_type, op2_type);
1842
1843 if (resolved_type->id == TypeTableEntryIdInvalid) {
1844 return g->builtin_types.entry_invalid;
1845 }
1846
1847 ConstExprValue *op1_val = &get_resolved_expr(op1)->const_val;
1848 ConstExprValue *op2_val = &get_resolved_expr(op2)->const_val;
1849 if (!op1_val->ok || !op2_val->ok) {
1850 return g->builtin_types.entry_bool;
1851 }
1852
1853 bool answer;
1854 if (resolved_type->id == TypeTableEntryIdInt) {
1855 if (op1_type->data.integral.is_signed &&
1856 op2_type->data.integral.is_signed)
1857 {
1858 answer = eval_bool_bin_op_signed(op1_val->data.x_int, bin_op_type, op2_val->data.x_int);
1859 } else if (!op1_type->data.integral.is_signed &&
1860 !op2_type->data.integral.is_signed)
1861 {
1862 answer = eval_bool_bin_op_unsigned(op1_val->data.x_uint, bin_op_type, op2_val->data.x_uint);
1863 } else {
1864 zig_unreachable();
1865 }
1866 } else if (resolved_type->id == TypeTableEntryIdFloat) {
1867 answer = eval_bool_bin_op_float(op1_val->data.x_float, bin_op_type, op2_val->data.x_float);
1868 } else {
1869 zig_unreachable();
1870 }
1871
1872 return resolve_expr_const_val_as_bool(g, node, answer);
1873}
1874
1875static TypeTableEntry *analyze_logic_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1876 AstNode *node)
1877{
1878 assert(node->type == NodeTypeBinOpExpr);
1879 BinOpType bin_op_type = node->data.bin_op_expr.bin_op;
1880
1881 AstNode *op1 = node->data.bin_op_expr.op1;
1882 AstNode *op2 = node->data.bin_op_expr.op2;
1883 TypeTableEntry *op1_type = analyze_expression(g, import, context, g->builtin_types.entry_bool, op1);
1884 TypeTableEntry *op2_type = analyze_expression(g, import, context, g->builtin_types.entry_bool, op2);
1885
1886 if (op1_type->id == TypeTableEntryIdInvalid ||
1887 op2_type->id == TypeTableEntryIdInvalid)
1888 {
1889 return g->builtin_types.entry_invalid;
1890 }
1891
1892 ConstExprValue *op1_val = &get_resolved_expr(op1)->const_val;
1893 ConstExprValue *op2_val = &get_resolved_expr(op2)->const_val;
1894 if (!op1_val->ok || !op2_val->ok) {
1895 return g->builtin_types.entry_bool;
1896 }
1897
1898 bool answer = eval_bool_bin_op_bool(op1_val->data.x_bool, bin_op_type, op2_val->data.x_bool);
1899 return resolve_expr_const_val_as_bool(g, node, answer);
1900}
1901
1993static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,1902static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1994 TypeTableEntry *expected_type, AstNode *node)1903 TypeTableEntry *expected_type, AstNode *node)
1995{1904{
1996 switch (node->data.bin_op_expr.bin_op) {1905 BinOpType bin_op_type = node->data.bin_op_expr.bin_op;
1906 switch (bin_op_type) {
1997 case BinOpTypeAssign:1907 case BinOpTypeAssign:
1998 case BinOpTypeAssignTimes:1908 case BinOpTypeAssignTimes:
1999 case BinOpTypeAssignDiv:1909 case BinOpTypeAssignDiv:
...@@ -2025,25 +1935,14 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,...@@ -2025,25 +1935,14 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
2025 }1935 }
2026 case BinOpTypeBoolOr:1936 case BinOpTypeBoolOr:
2027 case BinOpTypeBoolAnd:1937 case BinOpTypeBoolAnd:
2028 analyze_expression(g, import, context, g->builtin_types.entry_bool, node->data.bin_op_expr.op1);1938 return analyze_logic_bin_op_expr(g, import, context, node);
2029 analyze_expression(g, import, context, g->builtin_types.entry_bool, node->data.bin_op_expr.op2);
2030 return g->builtin_types.entry_bool;
2031 case BinOpTypeCmpEq:1939 case BinOpTypeCmpEq:
2032 case BinOpTypeCmpNotEq:1940 case BinOpTypeCmpNotEq:
2033 case BinOpTypeCmpLessThan:1941 case BinOpTypeCmpLessThan:
2034 case BinOpTypeCmpGreaterThan:1942 case BinOpTypeCmpGreaterThan:
2035 case BinOpTypeCmpLessOrEq:1943 case BinOpTypeCmpLessOrEq:
2036 case BinOpTypeCmpGreaterOrEq:1944 case BinOpTypeCmpGreaterOrEq:
2037 {1945 return analyze_bool_bin_op_expr(g, import, context, node);
2038 AstNode *op1 = node->data.bin_op_expr.op1;
2039 AstNode *op2 = node->data.bin_op_expr.op2;
2040 TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, op1);
2041 TypeTableEntry *rhs_type = analyze_expression(g, import, context, nullptr, op2);
2042
2043 resolve_peer_type_compatibility(g, context, node, op1, op2, lhs_type, rhs_type);
2044
2045 return g->builtin_types.entry_bool;
2046 }
2047 case BinOpTypeBinOr:1946 case BinOpTypeBinOr:
2048 case BinOpTypeBinXor:1947 case BinOpTypeBinXor:
2049 case BinOpTypeBinAnd:1948 case BinOpTypeBinAnd:
...@@ -2178,30 +2077,41 @@ static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *i...@@ -2178,30 +2077,41 @@ static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *i
2178{2077{
2179 assert(node->type == NodeTypeNullLiteral);2078 assert(node->type == NodeTypeNullLiteral);
21802079
2181 if (expected_type) {2080 if (!expected_type) {
2182 assert(expected_type->id == TypeTableEntryIdMaybe);
2183
2184 node->data.null_literal.resolved_struct_val_expr.type_entry = expected_type;
2185 node->data.null_literal.resolved_struct_val_expr.source_node = node;
2186 block_context->struct_val_expr_alloca_list.append(&node->data.null_literal.resolved_struct_val_expr);
2187
2188 return expected_type;
2189 } else {
2190 add_node_error(g, node,2081 add_node_error(g, node,
2191 buf_sprintf("unable to determine null type"));2082 buf_sprintf("unable to determine null type"));
2192 return g->builtin_types.entry_invalid;2083 return g->builtin_types.entry_invalid;
2193 }2084 }
2085
2086 assert(expected_type->id == TypeTableEntryIdMaybe);
2087
2088 node->data.null_literal.resolved_struct_val_expr.type_entry = expected_type;
2089 node->data.null_literal.resolved_struct_val_expr.source_node = node;
2090 block_context->struct_val_expr_alloca_list.append(&node->data.null_literal.resolved_struct_val_expr);
2091
2092 return resolve_expr_const_val_as_null(g, node, expected_type);
2194}2093}
21952094
2196static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import,2095static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import,
2197 BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node)2096 BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node)
2198{2097{
2199 TypeTableEntry *num_lit_type = g->num_lit_types[node->data.number_literal.kind];
2200 if (node->data.number_literal.overflow) {2098 if (node->data.number_literal.overflow) {
2201 add_node_error(g, node,2099 add_node_error(g, node, buf_sprintf("number literal too large to be represented in any type"));
2202 buf_sprintf("number literal too large to be represented in any type"));
2203 return g->builtin_types.entry_invalid;2100 return g->builtin_types.entry_invalid;
2204 } else if (expected_type) {2101 }
2102
2103 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
2104 const_val->ok = true;
2105 if (is_num_lit_unsigned(node->data.number_literal.kind)) {
2106 const_val->data.x_uint = node->data.number_literal.data.x_uint;
2107 } else if (is_num_lit_float(node->data.number_literal.kind)) {
2108 const_val->data.x_float = node->data.number_literal.data.x_float;
2109 } else {
2110 zig_unreachable();
2111 }
2112
2113 TypeTableEntry *num_lit_type = g->num_lit_types[node->data.number_literal.kind];
2114 if (expected_type) {
2205 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);2115 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
2206 assert(!codegen_num_lit->resolved_type);2116 assert(!codegen_num_lit->resolved_type);
2207 TypeTableEntry *after_implicit_cast_resolved_type =2117 TypeTableEntry *after_implicit_cast_resolved_type =
...@@ -2235,18 +2145,17 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,...@@ -2235,18 +2145,17 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,
2235 return g->builtin_types.entry_invalid;2145 return g->builtin_types.entry_invalid;
2236 }2146 }
22372147
2238 ConstExprValue const_val = {0};2148 ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
2239 eval_const_expr(g, context, size_node, &const_val);2149 if (const_val->ok) {
22402150 return resolve_expr_const_val_as_type(g, node,
2241 if (const_val.ok) {2151 get_array_type(g, import, child_type, const_val->data.x_uint));
2242 return get_meta_type(g, get_array_type(g, import, child_type, const_val.data.x_uint));
2243 } else {2152 } else {
2244 add_node_error(g, size_node,2153 add_node_error(g, size_node, buf_create_from_str("unable to resolve constant expression"));
2245 buf_create_from_str("unable to resolve constant expression"));
2246 return g->builtin_types.entry_invalid;2154 return g->builtin_types.entry_invalid;
2247 }2155 }
2248 } else {2156 } else {
2249 return get_meta_type(g, get_unknown_size_array_type(g, import, child_type, node->data.array_type.is_const));2157 return resolve_expr_const_val_as_type(g, node,
2158 get_unknown_size_array_type(g, import, child_type, node->data.array_type.is_const));
2250 }2159 }
2251}2160}
22522161
...@@ -2271,11 +2180,9 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,...@@ -2271,11 +2180,9 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,
2271 } else {2180 } else {
2272 // if the condition is a simple constant expression and there are no break statements2181 // if the condition is a simple constant expression and there are no break statements
2273 // then the return type is unreachable2182 // then the return type is unreachable
2274 ConstExprValue const_val = {0};2183 ConstExprValue *const_val = &get_resolved_expr(condition_node)->const_val;
2275 eval_const_expr(g, context, condition_node, &const_val);2184 if (const_val->ok) {
22762185 if (const_val->data.x_bool) {
2277 if (const_val.ok) {
2278 if (const_val.data.x_bool) {
2279 node->data.while_expr.condition_always_true = true;2186 node->data.while_expr.condition_always_true = true;
2280 if (!node->data.while_expr.contains_break) {2187 if (!node->data.while_expr.contains_break) {
2281 expr_return_type = g->builtin_types.entry_unreachable;2188 expr_return_type = g->builtin_types.entry_unreachable;
...@@ -2360,19 +2267,23 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,...@@ -2360,19 +2267,23 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,
2360}2267}
23612268
2362static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,2269static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2363 AstNode *node, const char *err_format)2270 AstNode *node, const char *err_format, bool is_max)
2364{2271{
2365 assert(node->type == NodeTypeFnCallExpr);2272 assert(node->type == NodeTypeFnCallExpr);
2366 assert(node->data.fn_call_expr.params.length == 1);2273 assert(node->data.fn_call_expr.params.length == 1);
23672274
2368 AstNode *type_node = node->data.fn_call_expr.params.at(0);2275 AstNode *type_node = node->data.fn_call_expr.params.at(0);
2369 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);2276 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
2370 if (type_entry->id == TypeTableEntryIdInt ||2277 if (type_entry->id == TypeTableEntryIdInvalid) {
2371 type_entry->id == TypeTableEntryIdFloat ||2278 return g->builtin_types.entry_invalid;
2372 type_entry->id == TypeTableEntryIdBool ||2279 } else if (type_entry->id == TypeTableEntryIdInt) {
2373 type_entry->id == TypeTableEntryIdInvalid)2280 // TODO const expr eval for min/max int
2374 {
2375 return type_entry;2281 return type_entry;
2282 } else if (type_entry->id == TypeTableEntryIdFloat) {
2283 // TODO const expr eval for min/max float
2284 return type_entry;
2285 } else if (type_entry->id == TypeTableEntryIdBool) {
2286 return resolve_expr_const_val_as_bool(g, node, is_max);
2376 } else {2287 } else {
2377 add_node_error(g, node,2288 add_node_error(g, node,
2378 buf_sprintf(err_format, buf_ptr(&type_entry->name)));2289 buf_sprintf(err_format, buf_ptr(&type_entry->name)));
...@@ -2380,8 +2291,46 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor...@@ -2380,8 +2291,46 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor
2380 }2291 }
2381}2292}
23822293
2294static void eval_const_expr_implicit_cast(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2295 AstNode *node, Cast *cast, AstNode *expr_node)
2296{
2297 switch (cast->op) {
2298 case CastOpNothing:
2299 case CastOpPtrToInt:
2300 case CastOpIntWidenOrShorten:
2301 case CastOpPointerReinterpret:
2302 {
2303 ConstExprValue *other_val = &get_resolved_expr(expr_node)->const_val;
2304 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
2305 if (other_val != const_val) {
2306 *const_val = *other_val;
2307 }
2308 break;
2309 }
2310 case CastOpToUnknownSizeArray:
2311 // TODO eval const expr
2312 break;
2313 case CastOpMaybeWrap:
2314 {
2315 ConstExprValue *other_val = &get_resolved_expr(expr_node)->const_val;
2316 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
2317 if (!other_val->ok) {
2318 break;
2319 } else if (const_val == other_val) {
2320 ConstExprValue *new_val = allocate<ConstExprValue>(1);
2321 memcpy(new_val, other_val, sizeof(ConstExprValue));
2322 other_val = new_val;
2323 }
2324
2325 const_val->data.x_maybe = other_val;
2326 const_val->ok = true;
2327 break;
2328 }
2329 }
2330}
2331
2383static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,2332static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2384 AstNode *node, TypeTableEntry *invoke_type_entry)2333 AstNode *node)
2385{2334{
2386 assert(node->type == NodeTypeFnCallExpr);2335 assert(node->type == NodeTypeFnCallExpr);
23872336
...@@ -2394,7 +2343,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -2394,7 +2343,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
2394 }2343 }
23952344
2396 AstNode *expr_node = node->data.fn_call_expr.params.at(0);2345 AstNode *expr_node = node->data.fn_call_expr.params.at(0);
2397 TypeTableEntry *wanted_type = invoke_type_entry->data.meta_type.child_type;2346 TypeTableEntry *wanted_type = resolve_type(g, fn_ref_expr);
2398 TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, expr_node);2347 TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, expr_node);
23992348
2400 if (wanted_type->id == TypeTableEntryIdInvalid ||2349 if (wanted_type->id == TypeTableEntryIdInvalid ||
...@@ -2411,11 +2360,13 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -2411,11 +2360,13 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
2411 actual_type->id == TypeTableEntryIdPointer)2360 actual_type->id == TypeTableEntryIdPointer)
2412 {2361 {
2413 cast->op = CastOpPtrToInt;2362 cast->op = CastOpPtrToInt;
2363 eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node);
2414 return wanted_type;2364 return wanted_type;
2415 } else if (wanted_type->id == TypeTableEntryIdInt &&2365 } else if (wanted_type->id == TypeTableEntryIdInt &&
2416 actual_type->id == TypeTableEntryIdInt)2366 actual_type->id == TypeTableEntryIdInt)
2417 {2367 {
2418 cast->op = CastOpIntWidenOrShorten;2368 cast->op = CastOpIntWidenOrShorten;
2369 eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node);
2419 return wanted_type;2370 return wanted_type;
2420 } else if (wanted_type->id == TypeTableEntryIdStruct &&2371 } else if (wanted_type->id == TypeTableEntryIdStruct &&
2421 wanted_type->data.structure.is_unknown_size_array &&2372 wanted_type->data.structure.is_unknown_size_array &&
...@@ -2424,6 +2375,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -2424,6 +2375,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
2424 {2375 {
2425 cast->op = CastOpToUnknownSizeArray;2376 cast->op = CastOpToUnknownSizeArray;
2426 context->cast_expr_alloca_list.append(cast);2377 context->cast_expr_alloca_list.append(cast);
2378 eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node);
2427 return wanted_type;2379 return wanted_type;
2428 } else if (actual_type->id == TypeTableEntryIdNumberLiteral &&2380 } else if (actual_type->id == TypeTableEntryIdNumberLiteral &&
2429 num_lit_fits_in_other_type(g, actual_type, wanted_type))2381 num_lit_fits_in_other_type(g, actual_type, wanted_type))
...@@ -2432,11 +2384,13 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -2432,11 +2384,13 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
2432 assert(!codegen_num_lit->resolved_type);2384 assert(!codegen_num_lit->resolved_type);
2433 codegen_num_lit->resolved_type = wanted_type;2385 codegen_num_lit->resolved_type = wanted_type;
2434 cast->op = CastOpNothing;2386 cast->op = CastOpNothing;
2387 eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node);
2435 return wanted_type;2388 return wanted_type;
2436 } else if (actual_type->id == TypeTableEntryIdPointer &&2389 } else if (actual_type->id == TypeTableEntryIdPointer &&
2437 wanted_type->id == TypeTableEntryIdPointer)2390 wanted_type->id == TypeTableEntryIdPointer)
2438 {2391 {
2439 cast->op = CastOpPointerReinterpret;2392 cast->op = CastOpPointerReinterpret;
2393 eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node);
2440 return wanted_type;2394 return wanted_type;
2441 } else {2395 } else {
2442 add_node_error(g, node,2396 add_node_error(g, node,
...@@ -2457,165 +2411,160 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry...@@ -2457,165 +2411,160 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
24572411
2458 auto entry = g->builtin_fn_table.maybe_get(name);2412 auto entry = g->builtin_fn_table.maybe_get(name);
24592413
2460 if (entry) {2414 if (!entry) {
2461 BuiltinFnEntry *builtin_fn = entry->value;2415 add_node_error(g, node,
2462 int actual_param_count = node->data.fn_call_expr.params.length;2416 buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));
2417 return g->builtin_types.entry_invalid;
2418 }
24632419
2464 node->data.fn_call_expr.builtin_fn = builtin_fn;2420 BuiltinFnEntry *builtin_fn = entry->value;
2421 int actual_param_count = node->data.fn_call_expr.params.length;
24652422
2466 if (builtin_fn->param_count != actual_param_count) {2423 node->data.fn_call_expr.builtin_fn = builtin_fn;
2467 add_node_error(g, node,
2468 buf_sprintf("expected %d arguments, got %d",
2469 builtin_fn->param_count, actual_param_count));
2470 return g->builtin_types.entry_invalid;
2471 }
24722424
2473 switch (builtin_fn->id) {2425 if (builtin_fn->param_count != actual_param_count) {
2474 case BuiltinFnIdInvalid:2426 add_node_error(g, node,
2475 zig_unreachable();2427 buf_sprintf("expected %d arguments, got %d",
2476 case BuiltinFnIdAddWithOverflow:2428 builtin_fn->param_count, actual_param_count));
2477 case BuiltinFnIdSubWithOverflow:2429 return g->builtin_types.entry_invalid;
2478 case BuiltinFnIdMulWithOverflow:2430 }
2479 {
2480 AstNode *type_node = node->data.fn_call_expr.params.at(0);
2481 TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node);
2482 if (int_type->id == TypeTableEntryIdInvalid) {
2483 return g->builtin_types.entry_bool;
2484 } else if (int_type->id == TypeTableEntryIdInt) {
2485 AstNode *op1_node = node->data.fn_call_expr.params.at(1);
2486 AstNode *op2_node = node->data.fn_call_expr.params.at(2);
2487 AstNode *result_node = node->data.fn_call_expr.params.at(3);
2488
2489 analyze_expression(g, import, context, int_type, op1_node);
2490 analyze_expression(g, import, context, int_type, op2_node);
2491 analyze_expression(g, import, context, get_pointer_to_type(g, int_type, false),
2492 result_node);
2493 } else {
2494 add_node_error(g, type_node,
2495 buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name)));
2496 }
24972431
2432 switch (builtin_fn->id) {
2433 case BuiltinFnIdInvalid:
2434 zig_unreachable();
2435 case BuiltinFnIdAddWithOverflow:
2436 case BuiltinFnIdSubWithOverflow:
2437 case BuiltinFnIdMulWithOverflow:
2438 {
2439 AstNode *type_node = node->data.fn_call_expr.params.at(0);
2440 TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node);
2441 if (int_type->id == TypeTableEntryIdInvalid) {
2498 return g->builtin_types.entry_bool;2442 return g->builtin_types.entry_bool;
2443 } else if (int_type->id == TypeTableEntryIdInt) {
2444 AstNode *op1_node = node->data.fn_call_expr.params.at(1);
2445 AstNode *op2_node = node->data.fn_call_expr.params.at(2);
2446 AstNode *result_node = node->data.fn_call_expr.params.at(3);
2447
2448 analyze_expression(g, import, context, int_type, op1_node);
2449 analyze_expression(g, import, context, int_type, op2_node);
2450 analyze_expression(g, import, context, get_pointer_to_type(g, int_type, false),
2451 result_node);
2452 } else {
2453 add_node_error(g, type_node,
2454 buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name)));
2499 }2455 }
2500 case BuiltinFnIdMemcpy:
2501 {
2502 AstNode *dest_node = node->data.fn_call_expr.params.at(0);
2503 AstNode *src_node = node->data.fn_call_expr.params.at(1);
2504 AstNode *len_node = node->data.fn_call_expr.params.at(2);
2505 TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node);
2506 TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, src_node);
2507 analyze_expression(g, import, context, builtin_fn->param_types[2], len_node);
2508
2509 if (dest_type->id != TypeTableEntryIdInvalid &&
2510 dest_type->id != TypeTableEntryIdPointer)
2511 {
2512 add_node_error(g, dest_node,
2513 buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
2514 }
2515
2516 if (src_type->id != TypeTableEntryIdInvalid &&
2517 src_type->id != TypeTableEntryIdPointer)
2518 {
2519 add_node_error(g, src_node,
2520 buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&src_type->name)));
2521 }
25222456
2523 if (dest_type->id == TypeTableEntryIdPointer &&2457 // TODO constant expression evaluation
2524 src_type->id == TypeTableEntryIdPointer)
2525 {
2526 uint64_t dest_align_bits = dest_type->data.pointer.child_type->align_in_bits;
2527 uint64_t src_align_bits = src_type->data.pointer.child_type->align_in_bits;
2528 if (dest_align_bits != src_align_bits) {
2529 add_node_error(g, dest_node, buf_sprintf(
2530 "misaligned memcpy, '%s' has alignment '%" PRIu64 ", '%s' has alignment %" PRIu64,
2531 buf_ptr(&dest_type->name), dest_align_bits / 8,
2532 buf_ptr(&src_type->name), src_align_bits / 8));
2533 }
2534 }
25352458
2536 return builtin_fn->return_type;2459 return g->builtin_types.entry_bool;
2537 }2460 }
2538 case BuiltinFnIdMemset:2461 case BuiltinFnIdMemcpy:
2462 {
2463 AstNode *dest_node = node->data.fn_call_expr.params.at(0);
2464 AstNode *src_node = node->data.fn_call_expr.params.at(1);
2465 AstNode *len_node = node->data.fn_call_expr.params.at(2);
2466 TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node);
2467 TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, src_node);
2468 analyze_expression(g, import, context, builtin_fn->param_types[2], len_node);
2469
2470 if (dest_type->id != TypeTableEntryIdInvalid &&
2471 dest_type->id != TypeTableEntryIdPointer)
2539 {2472 {
2540 AstNode *dest_node = node->data.fn_call_expr.params.at(0);2473 add_node_error(g, dest_node,
2541 AstNode *char_node = node->data.fn_call_expr.params.at(1);2474 buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
2542 AstNode *len_node = node->data.fn_call_expr.params.at(2);
2543 TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node);
2544 analyze_expression(g, import, context, builtin_fn->param_types[1], char_node);
2545 analyze_expression(g, import, context, builtin_fn->param_types[2], len_node);
2546
2547 if (dest_type->id != TypeTableEntryIdInvalid &&
2548 dest_type->id != TypeTableEntryIdPointer)
2549 {
2550 add_node_error(g, dest_node,
2551 buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
2552 }
2553
2554 return builtin_fn->return_type;
2555 }2475 }
2556 case BuiltinFnIdSizeof:2476
2477 if (src_type->id != TypeTableEntryIdInvalid &&
2478 src_type->id != TypeTableEntryIdPointer)
2557 {2479 {
2558 AstNode *type_node = node->data.fn_call_expr.params.at(0);2480 add_node_error(g, src_node,
2559 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);2481 buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&src_type->name)));
2560 if (type_entry->id == TypeTableEntryIdInvalid) {2482 }
2561 return g->builtin_types.entry_invalid;
2562 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
2563 add_node_error(g, first_executing_node(type_node),
2564 buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
2565 return g->builtin_types.entry_invalid;
2566 } else {
2567 uint64_t size_in_bytes = type_entry->size_in_bits / 8;
25682483
2569 TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, size_in_bytes);2484 if (dest_type->id == TypeTableEntryIdPointer &&
2570 TypeTableEntry *resolved_type = resolve_rhs_number_literal(g, nullptr, expected_type, node, num_lit_type);2485 src_type->id == TypeTableEntryIdPointer)
2571 return resolved_type ? resolved_type : num_lit_type;2486 {
2487 uint64_t dest_align_bits = dest_type->data.pointer.child_type->align_in_bits;
2488 uint64_t src_align_bits = src_type->data.pointer.child_type->align_in_bits;
2489 if (dest_align_bits != src_align_bits) {
2490 add_node_error(g, dest_node, buf_sprintf(
2491 "misaligned memcpy, '%s' has alignment '%" PRIu64 ", '%s' has alignment %" PRIu64,
2492 buf_ptr(&dest_type->name), dest_align_bits / 8,
2493 buf_ptr(&src_type->name), src_align_bits / 8));
2572 }2494 }
2573 }2495 }
2574 case BuiltinFnIdMaxValue:
2575 return analyze_min_max_value(g, import, context, node, "no max value available for type '%s'");
2576 case BuiltinFnIdMinValue:
2577 return analyze_min_max_value(g, import, context, node, "no min value available for type '%s'");
2578 case BuiltinFnIdValueCount:
2579 {
2580 AstNode *type_node = node->data.fn_call_expr.params.at(0);
2581 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
25822496
2583 if (type_entry->id == TypeTableEntryIdInvalid) {2497 return builtin_fn->return_type;
2584 return type_entry;2498 }
2585 } else if (type_entry->id == TypeTableEntryIdEnum) {2499 case BuiltinFnIdMemset:
2586 uint64_t value_count = type_entry->data.enumeration.field_count;2500 {
2501 AstNode *dest_node = node->data.fn_call_expr.params.at(0);
2502 AstNode *char_node = node->data.fn_call_expr.params.at(1);
2503 AstNode *len_node = node->data.fn_call_expr.params.at(2);
2504 TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node);
2505 analyze_expression(g, import, context, builtin_fn->param_types[1], char_node);
2506 analyze_expression(g, import, context, builtin_fn->param_types[2], len_node);
2507
2508 if (dest_type->id != TypeTableEntryIdInvalid &&
2509 dest_type->id != TypeTableEntryIdPointer)
2510 {
2511 add_node_error(g, dest_node,
2512 buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
2513 }
25872514
2588 TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, value_count);2515 return builtin_fn->return_type;
2589 TypeTableEntry *resolved_type = resolve_rhs_number_literal(g, nullptr, expected_type, node, num_lit_type);2516 }
2590 return resolved_type ? resolved_type : num_lit_type;2517 case BuiltinFnIdSizeof:
2518 {
2519 AstNode *type_node = node->data.fn_call_expr.params.at(0);
2520 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
2521 if (type_entry->id == TypeTableEntryIdInvalid) {
2522 return g->builtin_types.entry_invalid;
2523 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
2524 add_node_error(g, first_executing_node(type_node),
2525 buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
2526 return g->builtin_types.entry_invalid;
2527 } else {
2528 uint64_t size_in_bytes = type_entry->size_in_bits / 8;
2529 return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, size_in_bytes);
2530 }
2531 }
2532 case BuiltinFnIdMaxValue:
2533 return analyze_min_max_value(g, import, context, node,
2534 "no max value available for type '%s'", true);
2535 case BuiltinFnIdMinValue:
2536 return analyze_min_max_value(g, import, context, node,
2537 "no min value available for type '%s'", false);
2538 case BuiltinFnIdValueCount:
2539 {
2540 AstNode *type_node = node->data.fn_call_expr.params.at(0);
2541 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
25912542
2592 } else {2543 if (type_entry->id == TypeTableEntryIdInvalid) {
2593 add_node_error(g, node,2544 return type_entry;
2594 buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name)));2545 } else if (type_entry->id == TypeTableEntryIdEnum) {
2595 return g->builtin_types.entry_invalid;2546 uint64_t value_count = type_entry->data.enumeration.field_count;
2596 }2547 return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, value_count);
2548 } else {
2549 add_node_error(g, node,
2550 buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name)));
2551 return g->builtin_types.entry_invalid;
2597 }2552 }
2598 case BuiltinFnIdTypeof:2553 }
2599 {2554 case BuiltinFnIdTypeof:
2600 AstNode *expr_node = node->data.fn_call_expr.params.at(0);2555 {
2601 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);2556 AstNode *expr_node = node->data.fn_call_expr.params.at(0);
2557 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
26022558
2603 if (type_entry->id == TypeTableEntryIdInvalid) {2559 if (type_entry->id == TypeTableEntryIdInvalid) {
2604 return g->builtin_types.entry_invalid;2560 return g->builtin_types.entry_invalid;
2605 } else if (type_entry->id == TypeTableEntryIdMetaType) {2561 } else {
2606 add_node_error(g, node, buf_sprintf("expected expression, got type"));2562 return resolve_expr_const_val_as_type(g, node, type_entry);
2607 } else {
2608 return get_meta_type(g, type_entry);
2609 }
2610 }2563 }
2564 }
26112565
2612 }
2613 zig_unreachable();
2614 } else {
2615 add_node_error(g, node,
2616 buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));
2617 return g->builtin_types.entry_invalid;
2618 }2566 }
2567 zig_unreachable();
2619}2568}
26202569
2621static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import, BlockContext *context,2570static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import, BlockContext *context,
...@@ -2707,30 +2656,35 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import...@@ -2707,30 +2656,35 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
2707 }2656 }
2708 } else if (struct_type->id == TypeTableEntryIdInvalid) {2657 } else if (struct_type->id == TypeTableEntryIdInvalid) {
2709 return struct_type;2658 return struct_type;
2710 } else if (struct_type->id == TypeTableEntryIdMetaType &&2659 } else if (struct_type->id == TypeTableEntryIdMetaType) {
2711 struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum)2660 TypeTableEntry *enum_type = resolve_type(g, first_param_expr);
2712 {2661
2713 TypeTableEntry *enum_type = struct_type->data.meta_type.child_type;2662 if (enum_type->id == TypeTableEntryIdInvalid) {
2714 Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name;2663 return g->builtin_types.entry_invalid;
2715 int param_count = node->data.fn_call_expr.params.length;2664 } else if (enum_type->id == TypeTableEntryIdEnum) {
2716 if (param_count > 1) {2665 Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name;
2717 add_node_error(g, first_executing_node(node->data.fn_call_expr.params.at(1)),2666 int param_count = node->data.fn_call_expr.params.length;
2718 buf_sprintf("enum values accept only one parameter"));2667 if (param_count > 1) {
2719 return enum_type;2668 add_node_error(g, first_executing_node(node->data.fn_call_expr.params.at(1)),
2720 } else {2669 buf_sprintf("enum values accept only one parameter"));
2721 AstNode *value_node;2670 return enum_type;
2722 if (param_count == 1) {
2723 value_node = node->data.fn_call_expr.params.at(0);
2724 } else {2671 } else {
2725 value_node = nullptr;2672 AstNode *value_node;
2726 }2673 if (param_count == 1) {
2674 value_node = node->data.fn_call_expr.params.at(0);
2675 } else {
2676 value_node = nullptr;
2677 }
27272678
2728 return analyze_enum_value_expr(g, import, context, fn_ref_expr, value_node,2679 return analyze_enum_value_expr(g, import, context, fn_ref_expr, value_node,
2729 enum_type, field_name);2680 enum_type, field_name);
2681 }
2682 } else {
2683 add_node_error(g, first_param_expr, buf_sprintf("member reference base type not struct or enum"));
2684 return g->builtin_types.entry_invalid;
2730 }2685 }
2731 } else {2686 } else {
2732 add_node_error(g, fn_ref_expr->data.field_access_expr.struct_expr,2687 add_node_error(g, first_param_expr, buf_sprintf("member reference base type not struct or enum"));
2733 buf_sprintf("member reference base type not struct or enum"));
2734 return g->builtin_types.entry_invalid;2688 return g->builtin_types.entry_invalid;
2735 }2689 }
2736 }2690 }
...@@ -2742,18 +2696,17 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import...@@ -2742,18 +2696,17 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
27422696
2743 // use constant expression evaluator to figure out the function at compile time.2697 // use constant expression evaluator to figure out the function at compile time.
2744 // otherwise we treat this as a function pointer.2698 // otherwise we treat this as a function pointer.
2745 ConstExprValue const_val = {0};2699 ConstExprValue *const_val = &get_resolved_expr(fn_ref_expr)->const_val;
2746 eval_const_expr(g, context, fn_ref_expr, &const_val);
27472700
2748 if (!const_val.ok) {2701 if (!const_val->ok) {
2749 add_node_error(g, node, buf_sprintf("function pointers not yet supported"));2702 add_node_error(g, node, buf_sprintf("function pointers not yet supported"));
2750 return g->builtin_types.entry_invalid;2703 return g->builtin_types.entry_invalid;
2751 }2704 }
27522705
2753 if (invoke_type_entry->id == TypeTableEntryIdMetaType) {2706 if (invoke_type_entry->id == TypeTableEntryIdMetaType) {
2754 return analyze_cast_expr(g, import, context, node, invoke_type_entry);2707 return analyze_cast_expr(g, import, context, node);
2755 } else if (invoke_type_entry->id == TypeTableEntryIdFn) {2708 } else if (invoke_type_entry->id == TypeTableEntryIdFn) {
2756 return analyze_fn_call_raw(g, import, context, expected_type, node, const_val.data.x_fn, nullptr);2709 return analyze_fn_call_raw(g, import, context, expected_type, node, const_val->data.x_fn, nullptr);
2757 } else {2710 } else {
2758 add_node_error(g, fn_ref_expr,2711 add_node_error(g, fn_ref_expr,
2759 buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name)));2712 buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name)));
...@@ -2764,18 +2717,31 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import...@@ -2764,18 +2717,31 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
2764static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,2717static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2765 TypeTableEntry *expected_type, AstNode *node)2718 TypeTableEntry *expected_type, AstNode *node)
2766{2719{
2767 switch (node->data.prefix_op_expr.prefix_op) {2720 PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;
2721 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
2722 switch (prefix_op) {
2768 case PrefixOpInvalid:2723 case PrefixOpInvalid:
2769 zig_unreachable();2724 zig_unreachable();
2770 case PrefixOpBoolNot:2725 case PrefixOpBoolNot:
2771 analyze_expression(g, import, context, g->builtin_types.entry_bool,2726 {
2772 node->data.prefix_op_expr.primary_expr);2727 TypeTableEntry *type_entry = analyze_expression(g, import, context, g->builtin_types.entry_bool,
2773 return g->builtin_types.entry_bool;2728 expr_node);
2729 if (type_entry->id == TypeTableEntryIdInvalid) {
2730 return g->builtin_types.entry_bool;
2731 }
2732
2733 ConstExprValue *target_const_val = &get_resolved_expr(expr_node)->const_val;
2734 if (!target_const_val->ok) {
2735 return g->builtin_types.entry_bool;
2736 }
2737
2738 bool answer = target_const_val->data.x_bool;
2739 return resolve_expr_const_val_as_bool(g, node, answer);
2740 }
2774 case PrefixOpBinNot:2741 case PrefixOpBinNot:
2775 {2742 {
2776 AstNode *operand_node = node->data.prefix_op_expr.primary_expr;
2777 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,2743 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
2778 operand_node);2744 expr_node);
2779 if (expr_type->id == TypeTableEntryIdInvalid) {2745 if (expr_type->id == TypeTableEntryIdInvalid) {
2780 return expr_type;2746 return expr_type;
2781 } else if (expr_type->id == TypeTableEntryIdInt ||2747 } else if (expr_type->id == TypeTableEntryIdInt ||
...@@ -2784,16 +2750,15 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -2784,16 +2750,15 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
2784 {2750 {
2785 return expr_type;2751 return expr_type;
2786 } else {2752 } else {
2787 add_node_error(g, operand_node, buf_sprintf("invalid binary not type: '%s'",2753 add_node_error(g, expr_node, buf_sprintf("invalid binary not type: '%s'",
2788 buf_ptr(&expr_type->name)));2754 buf_ptr(&expr_type->name)));
2789 return g->builtin_types.entry_invalid;2755 return g->builtin_types.entry_invalid;
2790 }2756 }
2791 }2757 }
2792 case PrefixOpNegation:2758 case PrefixOpNegation:
2793 {2759 {
2794 AstNode *operand_node = node->data.prefix_op_expr.primary_expr;
2795 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,2760 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
2796 operand_node);2761 expr_node);
2797 if (expr_type->id == TypeTableEntryIdInvalid) {2762 if (expr_type->id == TypeTableEntryIdInvalid) {
2798 return expr_type;2763 return expr_type;
2799 } else if (expr_type->id == TypeTableEntryIdInt &&2764 } else if (expr_type->id == TypeTableEntryIdInt &&
...@@ -2805,7 +2770,6 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -2805,7 +2770,6 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
2805 } else if (expr_type->id == TypeTableEntryIdNumberLiteral) {2770 } else if (expr_type->id == TypeTableEntryIdNumberLiteral) {
2806 return expr_type;2771 return expr_type;
2807 } else {2772 } else {
2808 BREAKPOINT;
2809 add_node_error(g, node, buf_sprintf("invalid negation type: '%s'",2773 add_node_error(g, node, buf_sprintf("invalid negation type: '%s'",
2810 buf_ptr(&expr_type->name)));2774 buf_ptr(&expr_type->name)));
2811 return g->builtin_types.entry_invalid;2775 return g->builtin_types.entry_invalid;
...@@ -2814,20 +2778,23 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -2814,20 +2778,23 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
2814 case PrefixOpAddressOf:2778 case PrefixOpAddressOf:
2815 case PrefixOpConstAddressOf:2779 case PrefixOpConstAddressOf:
2816 {2780 {
2817 bool is_const = (node->data.prefix_op_expr.prefix_op == PrefixOpConstAddressOf);2781 bool is_const = (prefix_op == PrefixOpConstAddressOf);
28182782
2819 TypeTableEntry *child_type = analyze_lvalue(g, import, context,2783 TypeTableEntry *child_type = analyze_lvalue(g, import, context,
2820 node->data.prefix_op_expr.primary_expr, LValPurposeAddressOf, is_const);2784 expr_node, LValPurposeAddressOf, is_const);
28212785
2822 if (child_type->id == TypeTableEntryIdInvalid) {2786 if (child_type->id == TypeTableEntryIdInvalid) {
2823 return g->builtin_types.entry_invalid;2787 return g->builtin_types.entry_invalid;
2824 } else if (child_type->id == TypeTableEntryIdMetaType) {2788 } else if (child_type->id == TypeTableEntryIdMetaType) {
2825 TypeTableEntry *meta_child_type = child_type->data.meta_type.child_type;2789 TypeTableEntry *meta_type = analyze_type_expr(g, import, context, expr_node);
2826 if (meta_child_type->id == TypeTableEntryIdUnreachable) {2790 if (meta_type->id == TypeTableEntryIdInvalid) {
2827 add_node_error(g, node,2791 return g->builtin_types.entry_invalid;
2828 buf_create_from_str("pointer to unreachable not allowed"));2792 } else if (meta_type->id == TypeTableEntryIdUnreachable) {
2793 add_node_error(g, node, buf_create_from_str("pointer to unreachable not allowed"));
2794 return g->builtin_types.entry_invalid;
2829 } else {2795 } else {
2830 return get_meta_type(g, get_pointer_to_type(g, meta_child_type, is_const));2796 return resolve_expr_const_val_as_type(g, node,
2797 get_pointer_to_type(g, meta_type, is_const));
2831 }2798 }
2832 } else {2799 } else {
2833 return get_pointer_to_type(g, child_type, is_const);2800 return get_pointer_to_type(g, child_type, is_const);
...@@ -2835,14 +2802,13 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -2835,14 +2802,13 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
2835 }2802 }
2836 case PrefixOpDereference:2803 case PrefixOpDereference:
2837 {2804 {
2838 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr,2805 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
2839 node->data.prefix_op_expr.primary_expr);
2840 if (type_entry->id == TypeTableEntryIdInvalid) {2806 if (type_entry->id == TypeTableEntryIdInvalid) {
2841 return type_entry;2807 return type_entry;
2842 } else if (type_entry->id == TypeTableEntryIdPointer) {2808 } else if (type_entry->id == TypeTableEntryIdPointer) {
2843 return type_entry->data.pointer.child_type;2809 return type_entry->data.pointer.child_type;
2844 } else {2810 } else {
2845 add_node_error(g, node->data.prefix_op_expr.primary_expr,2811 add_node_error(g, expr_node,
2846 buf_sprintf("indirection requires pointer operand ('%s' invalid)",2812 buf_sprintf("indirection requires pointer operand ('%s' invalid)",
2847 buf_ptr(&type_entry->name)));2813 buf_ptr(&type_entry->name)));
2848 return g->builtin_types.entry_invalid;2814 return g->builtin_types.entry_invalid;
...@@ -2850,24 +2816,25 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -2850,24 +2816,25 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
2850 }2816 }
2851 case PrefixOpMaybe:2817 case PrefixOpMaybe:
2852 {2818 {
2853 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr,2819 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
2854 node->data.prefix_op_expr.primary_expr);
28552820
2856 if (type_entry->id == TypeTableEntryIdInvalid) {2821 if (type_entry->id == TypeTableEntryIdInvalid) {
2857 return type_entry;2822 return type_entry;
2858 } else if (type_entry->id == TypeTableEntryIdMetaType) {2823 } else if (type_entry->id == TypeTableEntryIdMetaType) {
2859 TypeTableEntry *child_type = type_entry->data.meta_type.child_type;2824 TypeTableEntry *meta_type = resolve_type(g, expr_node);
2860 if (child_type->id == TypeTableEntryIdUnreachable) {2825 if (meta_type->id == TypeTableEntryIdInvalid) {
2826 return g->builtin_types.entry_invalid;
2827 } else if (meta_type->id == TypeTableEntryIdUnreachable) {
2861 add_node_error(g, node, buf_create_from_str("maybe unreachable type not allowed"));2828 add_node_error(g, node, buf_create_from_str("maybe unreachable type not allowed"));
2862 return g->builtin_types.entry_invalid;2829 return g->builtin_types.entry_invalid;
2863 } else {2830 } else {
2864 return get_meta_type(g, get_maybe_type(g, child_type));2831 return resolve_expr_const_val_as_type(g, node, get_maybe_type(g, meta_type));
2865 }2832 }
2866 } else if (type_entry->id == TypeTableEntryIdUnreachable) {2833 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
2867 add_node_error(g, node->data.prefix_op_expr.primary_expr,2834 add_node_error(g, expr_node, buf_sprintf("unable to wrap unreachable in maybe type"));
2868 buf_sprintf("unable to wrap unreachable in maybe type"));
2869 return g->builtin_types.entry_invalid;2835 return g->builtin_types.entry_invalid;
2870 } else {2836 } else {
2837 // TODO eval const expr
2871 return get_maybe_type(g, type_entry);2838 return get_maybe_type(g, type_entry);
2872 }2839 }
2873 }2840 }
...@@ -3023,7 +2990,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -3023,7 +2990,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
3023 return_type = g->builtin_types.entry_u8;2990 return_type = g->builtin_types.entry_u8;
3024 break;2991 break;
3025 case NodeTypeBoolLiteral:2992 case NodeTypeBoolLiteral:
3026 return_type = g->builtin_types.entry_bool;2993 return_type = resolve_expr_const_val_as_bool(g, node, node->data.bool_literal.value);
3027 break;2994 break;
30282995
3029 case NodeTypeNullLiteral:2996 case NodeTypeNullLiteral:
...@@ -3066,10 +3033,29 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -3066,10 +3033,29 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
3066 assert(return_type);3033 assert(return_type);
3067 resolve_type_compatibility(g, context, node, expected_type, return_type);3034 resolve_type_compatibility(g, context, node, expected_type, return_type);
30683035
3069 get_resolved_expr(node)->type_entry = return_type;3036 Expr *expr = get_resolved_expr(node);
3070 get_resolved_expr(node)->block_context = context;3037 expr->type_entry = return_type;
3038 expr->block_context = context;
30713039
3072 return return_type;3040 if (expr->type_entry->id == TypeTableEntryIdUnreachable) {
3041 return expr->type_entry;
3042 }
3043
3044 /*
3045 Cast *cast_node = &expr->implicit_cast;
3046 if (cast_node->after_type) {
3047 eval_const_expr_implicit_cast(g, import, context, node, cast_node, node);
3048 expr->type_entry = cast_node->after_type;
3049 }
3050 */
3051
3052 Cast *cast_node = &expr->implicit_maybe_cast;
3053 if (cast_node->after_type) {
3054 eval_const_expr_implicit_cast(g, import, context, node, cast_node, node);
3055 expr->type_entry = cast_node->after_type;
3056 }
3057
3058 return expr->type_entry;
3073}3059}
30743060
3075static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNode *node) {3061static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNode *node) {
src/codegen.cpp+19-14
...@@ -73,11 +73,13 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b...@@ -73,11 +73,13 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
73 TypeTableEntry *op1_type, TypeTableEntry *op2_type);73 TypeTableEntry *op1_type, TypeTableEntry *op2_type);
74static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_val,74static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_val,
75 TypeTableEntry *actual_type, TypeTableEntry *wanted_type, Cast *cast_node);75 TypeTableEntry *actual_type, TypeTableEntry *wanted_type, Cast *cast_node);
76 76
77static TypeTableEntry *get_type_for_type_node(AstNode *node) {77static TypeTableEntry *get_type_for_type_node(AstNode *node) {
78 TypeTableEntry *meta_type_entry = get_resolved_expr(node)->type_entry;78 Expr *expr = get_resolved_expr(node);
79 assert(meta_type_entry->id == TypeTableEntryIdMetaType);79 assert(expr->type_entry->id == TypeTableEntryIdMetaType);
80 return meta_type_entry->data.meta_type.child_type;80 ConstExprValue *const_val = &expr->const_val;
81 assert(const_val->ok);
82 return const_val->data.x_type;
81}83}
8284
83static TypeTableEntry *fn_proto_type_from_type_node(CodeGen *g, AstNode *type_node) {85static TypeTableEntry *fn_proto_type_from_type_node(CodeGen *g, AstNode *type_node) {
...@@ -434,10 +436,8 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -434,10 +436,8 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
434 } else if (struct_type->id == TypeTableEntryIdPointer) {436 } else if (struct_type->id == TypeTableEntryIdPointer) {
435 assert(struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct);437 assert(struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct);
436 fn_table_entry = node->data.fn_call_expr.fn_entry;438 fn_table_entry = node->data.fn_call_expr.fn_entry;
437 } else if (struct_type->id == TypeTableEntryIdMetaType &&439 } else if (struct_type->id == TypeTableEntryIdMetaType) {
438 struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum)440 TypeTableEntry *enum_type = get_type_for_type_node(first_param_expr);
439 {
440 TypeTableEntry *enum_type = struct_type->data.meta_type.child_type;
441 int param_count = node->data.fn_call_expr.params.length;441 int param_count = node->data.fn_call_expr.params.length;
442 AstNode *arg1_node;442 AstNode *arg1_node;
443 if (param_count == 1) {443 if (param_count == 1) {
...@@ -681,7 +681,8 @@ static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lva...@@ -681,7 +681,8 @@ static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lva
681static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {681static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
682 assert(node->type == NodeTypeFieldAccessExpr);682 assert(node->type == NodeTypeFieldAccessExpr);
683683
684 TypeTableEntry *struct_type = get_expr_type(node->data.field_access_expr.struct_expr);684 AstNode *struct_expr = node->data.field_access_expr.struct_expr;
685 TypeTableEntry *struct_type = get_expr_type(struct_expr);
685 Buf *name = &node->data.field_access_expr.field_name;686 Buf *name = &node->data.field_access_expr.field_name;
686687
687 if (struct_type->id == TypeTableEntryIdArray) {688 if (struct_type->id == TypeTableEntryIdArray) {
...@@ -710,14 +711,12 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva...@@ -710,14 +711,12 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva
710 add_debug_source_node(g, node);711 add_debug_source_node(g, node);
711 return LLVMBuildLoad(g->builder, ptr, "");712 return LLVMBuildLoad(g->builder, ptr, "");
712 }713 }
713 } else if (struct_type->id == TypeTableEntryIdMetaType &&714 } else if (struct_type->id == TypeTableEntryIdMetaType) {
714 struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum)
715 {
716 assert(!is_lvalue);715 assert(!is_lvalue);
717 TypeTableEntry *enum_type = struct_type->data.meta_type.child_type;716 TypeTableEntry *enum_type = get_type_for_type_node(struct_expr);
718 return gen_enum_value_expr(g, node, enum_type, nullptr);717 return gen_enum_value_expr(g, node, enum_type, nullptr);
719 } else {718 } else {
720 zig_panic("gen_field_access_expr bad struct type");719 zig_unreachable();
721 }720 }
722}721}
723722
...@@ -2392,6 +2391,12 @@ static void define_builtin_types(CodeGen *g) {...@@ -2392,6 +2391,12 @@ static void define_builtin_types(CodeGen *g) {
2392 g->builtin_types.entry_unreachable = entry;2391 g->builtin_types.entry_unreachable = entry;
2393 g->primitive_type_table.put(&entry->name, entry);2392 g->primitive_type_table.put(&entry->name, entry);
2394 }2393 }
2394 {
2395 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdMetaType);
2396 buf_init_from_str(&entry->name, "type");
2397 g->builtin_types.entry_type = entry;
2398 g->primitive_type_table.put(&entry->name, entry);
2399 }
23952400
2396 g->builtin_types.entry_c_string_literal = get_pointer_to_type(g, get_int_type(g, false, 8), true);2401 g->builtin_types.entry_c_string_literal = get_pointer_to_type(g, get_int_type(g, false, 8), true);
23972402