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")
88endif
99
1010syn keyword zigStorage const var extern volatile export pub noalias
11syn keyword zigStructure struct enum type
11syn keyword zigStructure struct enum
1212syn keyword zigStatement goto break return continue asm
1313syn keyword zigConditional if else switch
1414syn keyword zigRepeat while for
1515
1616syn keyword zigConstant null
17syn keyword zigKeyword fn use
18syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 string void unreachable
17syn keyword zigKeyword fn import
18syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 string void unreachable type
1919
2020syn keyword zigBoolean true false
2121
src/all_types.hpp+18-27
......@@ -57,6 +57,21 @@ struct Cast {
5757 AstNode *source_node;
5858};
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
6075struct Expr {
6176 TypeTableEntry *type_entry;
6277 // the context in which this expression is evaluated.
......@@ -66,6 +81,8 @@ struct Expr {
6681 // may be null for no cast
6782 Cast implicit_cast; // happens first
6883 Cast implicit_maybe_cast; // happens second
84
85 ConstExprValue const_val;
6986};
7087
7188struct NumLitCodeGen {
......@@ -490,7 +507,6 @@ struct AstNodeNumberLiteral {
490507
491508 union {
492509 uint64_t x_uint;
493 int64_t x_int;
494510 double x_float;
495511 } data;
496512
......@@ -534,8 +550,6 @@ struct AstNodeSymbolExpr {
534550 // populated by semantic analyzer
535551 Expr resolved_expr;
536552 VariableTableEntry *variable;
537 TypeTableEntry *meta_type;
538 FnTableEntry *fn_entry;
539553};
540554
541555struct AstNodeBoolLiteral {
......@@ -670,10 +684,6 @@ struct TypeTableEntryMaybe {
670684 TypeTableEntry *child_type;
671685};
672686
673struct TypeTableEntryMetaType {
674 TypeTableEntry *child_type;
675};
676
677687struct TypeTableEntryEnum {
678688 AstNode *decl_node;
679689 uint32_t field_count;
......@@ -731,7 +741,6 @@ struct TypeTableEntry {
731741 TypeTableEntryNumLit num_lit;
732742 TypeTableEntryMaybe maybe;
733743 TypeTableEntryEnum enumeration;
734 TypeTableEntryMetaType meta_type;
735744 TypeTableEntryFn fn;
736745 } data;
737746
......@@ -740,7 +749,6 @@ struct TypeTableEntry {
740749 TypeTableEntry *unknown_size_array_parent[2];
741750 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;
742751 TypeTableEntry *maybe_parent;
743 TypeTableEntry *meta_parent;
744752};
745753
746754struct ImporterInfo {
......@@ -852,6 +860,7 @@ struct CodeGen {
852860 TypeTableEntry *entry_c_string_literal;
853861 TypeTableEntry *entry_void;
854862 TypeTableEntry *entry_unreachable;
863 TypeTableEntry *entry_type;
855864 TypeTableEntry *entry_invalid;
856865 } builtin_types;
857866
......@@ -923,22 +932,4 @@ struct BlockContext {
923932 LLVMZigDIScope *di_scope;
924933};
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
944935#endif
src/analyze.cpp+563-577
......@@ -13,8 +13,6 @@
1313
1414static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1515 TypeTableEntry *expected_type, AstNode *node);
16static void eval_const_expr(CodeGen *g, BlockContext *context,
17 AstNode *node, ConstExprValue *out_val);
1816static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,
1917 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);
2018static 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) {
158156 return get_int_type(g, false, num_lit_bit_count(get_number_literal_kind_unsigned(x)));
159157}
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
175159TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
176160 assert(child_type->id != TypeTableEntryIdInvalid);
177161 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
327311 }
328312}
329313
330// like analyze expression, but expects a type. creates an error if resulting type is
331// not a meta type. unwraps it if it is.
332static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
333 AstNode *node)
334{
335 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, node);
336 if (type_entry->id == TypeTableEntryIdInvalid) {
337 return type_entry;
338 } else if (type_entry->id == TypeTableEntryIdMetaType) {
339 return type_entry->data.meta_type.child_type;
314// If the node does not have a constant expression value with a metatype, generates an error
315// and returns invalid type. Otherwise, returns the type of the constant expression value.
316// Must be called after analyze_expression on the same node.
317static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {
318 Expr *expr = get_resolved_expr(node);
319 assert(expr->type_entry);
320 if (expr->type_entry->id == TypeTableEntryIdInvalid) {
321 return g->builtin_types.entry_invalid;
322 } else if (expr->type_entry->id == TypeTableEntryIdMetaType) {
323 // OK
340324 } else {
341 add_node_error(g, first_executing_node(node),
342 buf_sprintf("expected type, found expression"));
343 get_resolved_expr(node)->type_entry = g->builtin_types.entry_invalid;
325 add_node_error(g, node, buf_sprintf("expected type, found expression"));
344326 return g->builtin_types.entry_invalid;
345327 }
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;
363 TypeTableEntry *op2_type = get_resolved_expr(op2_node)->type_entry;
364
365 // TODO complete more of this function instead of returning 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");
329 ConstExprValue *const_val = &expr->const_val;
330 if (!const_val->ok) {
331 add_node_error(g, node, buf_sprintf("unable to resolve constant expression"));
332 return g->builtin_types.entry_invalid;
518333 }
519}
520334
521static void eval_const_expr_fn_call(CodeGen *g, BlockContext *context,
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);
335 return const_val->data.x_type;
531336}
532337
533static void eval_const_expr_prefix_op_expr(CodeGen *g, BlockContext *context, AstNode *node,
534 ConstExprValue *out_val)
338// Calls analyze_expression on node, and then resolve_type.
339static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
340 AstNode *node)
535341{
536 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
537 switch (node->data.prefix_op_expr.prefix_op) {
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 }
342 analyze_expression(g, import, context, nullptr, node);
343 return resolve_type(g, node);
625344}
626345
627346static 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
662381
663382 fn_table_entry->type_entry = fn_type;
664383
665 Buf *name = &node->data.fn_proto.name;
666384 buf_resize(&fn_type->name, 0);
667 buf_appendf(&fn_type->name, "fn %s(", buf_ptr(name));
385 buf_appendf(&fn_type->name, "fn(");
668386 for (int i = 0; i < param_count; i += 1) {
669387 AstNode *child = node->data.fn_proto.params.at(i);
670388 assert(child->type == NodeTypeParamDecl);
......@@ -672,8 +390,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
672390 child->data.param_decl.type);
673391 fn_table_entry->type_entry->data.fn.param_types[i] = type_entry;
674392
675 buf_appendf(&fn_type->name, "%s : %s",
676 buf_ptr(&child->data.param_decl.name), buf_ptr(&type_entry->name));
393 buf_appendf(&fn_type->name, "%s", buf_ptr(&type_entry->name));
677394
678395 if (i + 1 < param_count) {
679396 buf_appendf(&fn_type->name, ", ");
......@@ -1212,13 +929,14 @@ static FnTableEntry *get_context_fn_entry(BlockContext *context) {
1212929}
1213930
1214931static TypeTableEntry *unwrapped_node_type(AstNode *node) {
1215 TypeTableEntry *meta_type_entry = get_resolved_expr(node)->type_entry;
1216 if (meta_type_entry->id == TypeTableEntryIdInvalid) {
1217 return meta_type_entry;
1218 } else {
1219 assert(meta_type_entry->id == TypeTableEntryIdMetaType);
1220 return meta_type_entry->data.meta_type.child_type;
932 Expr *expr = get_resolved_expr(node);
933 if (expr->type_entry->id == TypeTableEntryIdInvalid) {
934 return expr->type_entry;
1221935 }
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;
1222940}
1223941
1224942static TypeTableEntry *get_return_type(BlockContext *context) {
......@@ -1704,8 +1422,6 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
17041422 AstNode *struct_expr_node = node->data.field_access_expr.struct_expr;
17051423 TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, struct_expr_node);
17061424
1707 TypeTableEntry *return_type;
1708
17091425 if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
17101426 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
17111427 {
......@@ -1716,40 +1432,45 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
17161432
17171433 node->data.field_access_expr.type_struct_field = get_struct_field(bare_struct_type, field_name);
17181434 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;
17201436 } else {
17211437 add_node_error(g, node,
17221438 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;
17241440 }
17251441 } else if (struct_type->id == TypeTableEntryIdArray) {
17261442 Buf *name = &node->data.field_access_expr.field_name;
17271443 if (buf_eql_str(name, "len")) {
1728 return_type = g->builtin_types.entry_usize;
1444 return g->builtin_types.entry_usize;
17291445 } else if (buf_eql_str(name, "ptr")) {
17301446 // 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);
17321448 } else {
17331449 add_node_error(g, node,
17341450 buf_sprintf("no member named '%s' in '%s'", buf_ptr(name),
17351451 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;
17371466 }
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);
17441467 } else {
17451468 if (struct_type->id != TypeTableEntryIdInvalid) {
17461469 add_node_error(g, node,
17471470 buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name)));
17481471 }
1749 return_type = g->builtin_types.entry_invalid;
1472 return g->builtin_types.entry_invalid;
17501473 }
1751
1752 return return_type;
17531474}
17541475
17551476static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
......@@ -1826,6 +1547,52 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i
18261547 return return_type;
18271548}
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
18291596static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
18301597 TypeTableEntry *expected_type, AstNode *node)
18311598{
......@@ -1833,28 +1600,33 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
18331600
18341601 auto primitive_table_entry = g->primitive_type_table.maybe_get(variable_name);
18351602 if (primitive_table_entry) {
1836 TypeTableEntry *meta_type = get_meta_type(g, primitive_table_entry->value);
1837 node->data.symbol_expr.meta_type = meta_type;
1838 return meta_type;
1603 return resolve_expr_const_val_as_type(g, node, primitive_table_entry->value);
18391604 }
18401605
18411606 VariableTableEntry *var = find_variable(context, variable_name);
18421607 if (var) {
18431608 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 }
18441619 return var->type;
18451620 }
18461621
18471622 TypeTableEntry *container_type = find_container(context, variable_name);
18481623 if (container_type) {
1849 TypeTableEntry *meta_type = get_meta_type(g, container_type);
1850 node->data.symbol_expr.meta_type = meta_type;
1851 return meta_type;
1624 return resolve_expr_const_val_as_type(g, node, container_type);
18521625 }
18531626
18541627 auto fn_table_entry = import->fn_table.maybe_get(variable_name);
18551628 if (fn_table_entry) {
1856 node->data.symbol_expr.fn_entry = fn_table_entry->value;
1857 return node->data.symbol_expr.fn_entry->type_entry;
1629 return resolve_expr_const_val_as_fn(g, node, fn_table_entry->value);
18581630 }
18591631
18601632 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
19901762 return expected_rhs_type;
19911763}
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
19931902static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
19941903 TypeTableEntry *expected_type, AstNode *node)
19951904{
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) {
19971907 case BinOpTypeAssign:
19981908 case BinOpTypeAssignTimes:
19991909 case BinOpTypeAssignDiv:
......@@ -2025,25 +1935,14 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
20251935 }
20261936 case BinOpTypeBoolOr:
20271937 case BinOpTypeBoolAnd:
2028 analyze_expression(g, import, context, g->builtin_types.entry_bool, node->data.bin_op_expr.op1);
2029 analyze_expression(g, import, context, g->builtin_types.entry_bool, node->data.bin_op_expr.op2);
2030 return g->builtin_types.entry_bool;
1938 return analyze_logic_bin_op_expr(g, import, context, node);
20311939 case BinOpTypeCmpEq:
20321940 case BinOpTypeCmpNotEq:
20331941 case BinOpTypeCmpLessThan:
20341942 case BinOpTypeCmpGreaterThan:
20351943 case BinOpTypeCmpLessOrEq:
20361944 case BinOpTypeCmpGreaterOrEq:
2037 {
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 }
1945 return analyze_bool_bin_op_expr(g, import, context, node);
20471946 case BinOpTypeBinOr:
20481947 case BinOpTypeBinXor:
20491948 case BinOpTypeBinAnd:
......@@ -2178,30 +2077,41 @@ static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *i
21782077{
21792078 assert(node->type == NodeTypeNullLiteral);
21802079
2181 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 {
2080 if (!expected_type) {
21902081 add_node_error(g, node,
21912082 buf_sprintf("unable to determine null type"));
21922083 return g->builtin_types.entry_invalid;
21932084 }
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);
21942093}
21952094
21962095static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import,
21972096 BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node)
21982097{
2199 TypeTableEntry *num_lit_type = g->num_lit_types[node->data.number_literal.kind];
22002098 if (node->data.number_literal.overflow) {
2201 add_node_error(g, node,
2202 buf_sprintf("number literal too large to be represented in any type"));
2099 add_node_error(g, node, buf_sprintf("number literal too large to be represented in any type"));
22032100 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) {
22052115 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
22062116 assert(!codegen_num_lit->resolved_type);
22072117 TypeTableEntry *after_implicit_cast_resolved_type =
......@@ -2235,18 +2145,17 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,
22352145 return g->builtin_types.entry_invalid;
22362146 }
22372147
2238 ConstExprValue const_val = {0};
2239 eval_const_expr(g, context, size_node, &const_val);
2240
2241 if (const_val.ok) {
2242 return get_meta_type(g, get_array_type(g, import, child_type, const_val.data.x_uint));
2148 ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
2149 if (const_val->ok) {
2150 return resolve_expr_const_val_as_type(g, node,
2151 get_array_type(g, import, child_type, const_val->data.x_uint));
22432152 } else {
2244 add_node_error(g, size_node,
2245 buf_create_from_str("unable to resolve constant expression"));
2153 add_node_error(g, size_node, buf_create_from_str("unable to resolve constant expression"));
22462154 return g->builtin_types.entry_invalid;
22472155 }
22482156 } 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));
22502159 }
22512160}
22522161
......@@ -2271,11 +2180,9 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,
22712180 } else {
22722181 // if the condition is a simple constant expression and there are no break statements
22732182 // then the return type is unreachable
2274 ConstExprValue const_val = {0};
2275 eval_const_expr(g, context, condition_node, &const_val);
2276
2277 if (const_val.ok) {
2278 if (const_val.data.x_bool) {
2183 ConstExprValue *const_val = &get_resolved_expr(condition_node)->const_val;
2184 if (const_val->ok) {
2185 if (const_val->data.x_bool) {
22792186 node->data.while_expr.condition_always_true = true;
22802187 if (!node->data.while_expr.contains_break) {
22812188 expr_return_type = g->builtin_types.entry_unreachable;
......@@ -2360,19 +2267,23 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,
23602267}
23612268
23622269static 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)
23642271{
23652272 assert(node->type == NodeTypeFnCallExpr);
23662273 assert(node->data.fn_call_expr.params.length == 1);
23672274
23682275 AstNode *type_node = node->data.fn_call_expr.params.at(0);
23692276 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
2370 if (type_entry->id == TypeTableEntryIdInt ||
2371 type_entry->id == TypeTableEntryIdFloat ||
2372 type_entry->id == TypeTableEntryIdBool ||
2373 type_entry->id == TypeTableEntryIdInvalid)
2374 {
2277 if (type_entry->id == TypeTableEntryIdInvalid) {
2278 return g->builtin_types.entry_invalid;
2279 } else if (type_entry->id == TypeTableEntryIdInt) {
2280 // TODO const expr eval for min/max int
23752281 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);
23762287 } else {
23772288 add_node_error(g, node,
23782289 buf_sprintf(err_format, buf_ptr(&type_entry->name)));
......@@ -2380,8 +2291,46 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor
23802291 }
23812292}
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
23832332static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2384 AstNode *node, TypeTableEntry *invoke_type_entry)
2333 AstNode *node)
23852334{
23862335 assert(node->type == NodeTypeFnCallExpr);
23872336
......@@ -2394,7 +2343,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
23942343 }
23952344
23962345 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);
23982347 TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, expr_node);
23992348
24002349 if (wanted_type->id == TypeTableEntryIdInvalid ||
......@@ -2411,11 +2360,13 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
24112360 actual_type->id == TypeTableEntryIdPointer)
24122361 {
24132362 cast->op = CastOpPtrToInt;
2363 eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node);
24142364 return wanted_type;
24152365 } else if (wanted_type->id == TypeTableEntryIdInt &&
24162366 actual_type->id == TypeTableEntryIdInt)
24172367 {
24182368 cast->op = CastOpIntWidenOrShorten;
2369 eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node);
24192370 return wanted_type;
24202371 } else if (wanted_type->id == TypeTableEntryIdStruct &&
24212372 wanted_type->data.structure.is_unknown_size_array &&
......@@ -2424,6 +2375,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
24242375 {
24252376 cast->op = CastOpToUnknownSizeArray;
24262377 context->cast_expr_alloca_list.append(cast);
2378 eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node);
24272379 return wanted_type;
24282380 } else if (actual_type->id == TypeTableEntryIdNumberLiteral &&
24292381 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
24322384 assert(!codegen_num_lit->resolved_type);
24332385 codegen_num_lit->resolved_type = wanted_type;
24342386 cast->op = CastOpNothing;
2387 eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node);
24352388 return wanted_type;
24362389 } else if (actual_type->id == TypeTableEntryIdPointer &&
24372390 wanted_type->id == TypeTableEntryIdPointer)
24382391 {
24392392 cast->op = CastOpPointerReinterpret;
2393 eval_const_expr_implicit_cast(g, import, context, node, cast, expr_node);
24402394 return wanted_type;
24412395 } else {
24422396 add_node_error(g, node,
......@@ -2457,165 +2411,160 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
24572411
24582412 auto entry = g->builtin_fn_table.maybe_get(name);
24592413
2460 if (entry) {
2461 BuiltinFnEntry *builtin_fn = entry->value;
2462 int actual_param_count = node->data.fn_call_expr.params.length;
2414 if (!entry) {
2415 add_node_error(g, node,
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) {
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 }
2423 node->data.fn_call_expr.builtin_fn = builtin_fn;
24722424
2473 switch (builtin_fn->id) {
2474 case BuiltinFnIdInvalid:
2475 zig_unreachable();
2476 case BuiltinFnIdAddWithOverflow:
2477 case BuiltinFnIdSubWithOverflow:
2478 case BuiltinFnIdMulWithOverflow:
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 }
2425 if (builtin_fn->param_count != actual_param_count) {
2426 add_node_error(g, node,
2427 buf_sprintf("expected %d arguments, got %d",
2428 builtin_fn->param_count, actual_param_count));
2429 return g->builtin_types.entry_invalid;
2430 }
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) {
24982442 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)));
24992455 }
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 &&
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 }
2457 // TODO constant expression evaluation
25352458
2536 return builtin_fn->return_type;
2537 }
2538 case BuiltinFnIdMemset:
2459 return g->builtin_types.entry_bool;
2460 }
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)
25392472 {
2540 AstNode *dest_node = node->data.fn_call_expr.params.at(0);
2541 AstNode *char_node = node->data.fn_call_expr.params.at(1);
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;
2473 add_node_error(g, dest_node,
2474 buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
25552475 }
2556 case BuiltinFnIdSizeof:
2476
2477 if (src_type->id != TypeTableEntryIdInvalid &&
2478 src_type->id != TypeTableEntryIdPointer)
25572479 {
2558 AstNode *type_node = node->data.fn_call_expr.params.at(0);
2559 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
2560 if (type_entry->id == TypeTableEntryIdInvalid) {
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;
2480 add_node_error(g, src_node,
2481 buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&src_type->name)));
2482 }
25682483
2569 TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, size_in_bytes);
2570 TypeTableEntry *resolved_type = resolve_rhs_number_literal(g, nullptr, expected_type, node, num_lit_type);
2571 return resolved_type ? resolved_type : num_lit_type;
2484 if (dest_type->id == TypeTableEntryIdPointer &&
2485 src_type->id == TypeTableEntryIdPointer)
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));
25722494 }
25732495 }
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) {
2584 return type_entry;
2585 } else if (type_entry->id == TypeTableEntryIdEnum) {
2586 uint64_t value_count = type_entry->data.enumeration.field_count;
2497 return builtin_fn->return_type;
2498 }
2499 case BuiltinFnIdMemset:
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);
2589 TypeTableEntry *resolved_type = resolve_rhs_number_literal(g, nullptr, expected_type, node, num_lit_type);
2590 return resolved_type ? resolved_type : num_lit_type;
2515 return builtin_fn->return_type;
2516 }
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 {
2593 add_node_error(g, node,
2594 buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name)));
2595 return g->builtin_types.entry_invalid;
2596 }
2543 if (type_entry->id == TypeTableEntryIdInvalid) {
2544 return type_entry;
2545 } else if (type_entry->id == TypeTableEntryIdEnum) {
2546 uint64_t value_count = type_entry->data.enumeration.field_count;
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;
25972552 }
2598 case BuiltinFnIdTypeof:
2599 {
2600 AstNode *expr_node = node->data.fn_call_expr.params.at(0);
2601 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
2553 }
2554 case BuiltinFnIdTypeof:
2555 {
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) {
2604 return g->builtin_types.entry_invalid;
2605 } else if (type_entry->id == TypeTableEntryIdMetaType) {
2606 add_node_error(g, node, buf_sprintf("expected expression, got type"));
2607 } else {
2608 return get_meta_type(g, type_entry);
2609 }
2559 if (type_entry->id == TypeTableEntryIdInvalid) {
2560 return g->builtin_types.entry_invalid;
2561 } else {
2562 return resolve_expr_const_val_as_type(g, node, type_entry);
26102563 }
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;
26182566 }
2567 zig_unreachable();
26192568}
26202569
26212570static 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
27072656 }
27082657 } else if (struct_type->id == TypeTableEntryIdInvalid) {
27092658 return struct_type;
2710 } else if (struct_type->id == TypeTableEntryIdMetaType &&
2711 struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum)
2712 {
2713 TypeTableEntry *enum_type = struct_type->data.meta_type.child_type;
2714 Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name;
2715 int param_count = node->data.fn_call_expr.params.length;
2716 if (param_count > 1) {
2717 add_node_error(g, first_executing_node(node->data.fn_call_expr.params.at(1)),
2718 buf_sprintf("enum values accept only one parameter"));
2719 return enum_type;
2720 } else {
2721 AstNode *value_node;
2722 if (param_count == 1) {
2723 value_node = node->data.fn_call_expr.params.at(0);
2659 } else if (struct_type->id == TypeTableEntryIdMetaType) {
2660 TypeTableEntry *enum_type = resolve_type(g, first_param_expr);
2661
2662 if (enum_type->id == TypeTableEntryIdInvalid) {
2663 return g->builtin_types.entry_invalid;
2664 } else if (enum_type->id == TypeTableEntryIdEnum) {
2665 Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name;
2666 int param_count = node->data.fn_call_expr.params.length;
2667 if (param_count > 1) {
2668 add_node_error(g, first_executing_node(node->data.fn_call_expr.params.at(1)),
2669 buf_sprintf("enum values accept only one parameter"));
2670 return enum_type;
27242671 } else {
2725 value_node = nullptr;
2726 }
2672 AstNode *value_node;
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,
2729 enum_type, field_name);
2679 return analyze_enum_value_expr(g, import, context, fn_ref_expr, value_node,
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;
27302685 }
27312686 } else {
2732 add_node_error(g, fn_ref_expr->data.field_access_expr.struct_expr,
2733 buf_sprintf("member reference base type not struct or enum"));
2687 add_node_error(g, first_param_expr, buf_sprintf("member reference base type not struct or enum"));
27342688 return g->builtin_types.entry_invalid;
27352689 }
27362690 }
......@@ -2742,18 +2696,17 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
27422696
27432697 // use constant expression evaluator to figure out the function at compile time.
27442698 // otherwise we treat this as a function pointer.
2745 ConstExprValue const_val = {0};
2746 eval_const_expr(g, context, fn_ref_expr, &const_val);
2699 ConstExprValue *const_val = &get_resolved_expr(fn_ref_expr)->const_val;
27472700
2748 if (!const_val.ok) {
2701 if (!const_val->ok) {
27492702 add_node_error(g, node, buf_sprintf("function pointers not yet supported"));
27502703 return g->builtin_types.entry_invalid;
27512704 }
27522705
27532706 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);
27552708 } 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);
27572710 } else {
27582711 add_node_error(g, fn_ref_expr,
27592712 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
27642717static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
27652718 TypeTableEntry *expected_type, AstNode *node)
27662719{
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) {
27682723 case PrefixOpInvalid:
27692724 zig_unreachable();
27702725 case PrefixOpBoolNot:
2771 analyze_expression(g, import, context, g->builtin_types.entry_bool,
2772 node->data.prefix_op_expr.primary_expr);
2773 return g->builtin_types.entry_bool;
2726 {
2727 TypeTableEntry *type_entry = analyze_expression(g, import, context, 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 }
27742741 case PrefixOpBinNot:
27752742 {
2776 AstNode *operand_node = node->data.prefix_op_expr.primary_expr;
27772743 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
2778 operand_node);
2744 expr_node);
27792745 if (expr_type->id == TypeTableEntryIdInvalid) {
27802746 return expr_type;
27812747 } else if (expr_type->id == TypeTableEntryIdInt ||
......@@ -2784,16 +2750,15 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
27842750 {
27852751 return expr_type;
27862752 } 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'",
27882754 buf_ptr(&expr_type->name)));
27892755 return g->builtin_types.entry_invalid;
27902756 }
27912757 }
27922758 case PrefixOpNegation:
27932759 {
2794 AstNode *operand_node = node->data.prefix_op_expr.primary_expr;
27952760 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
2796 operand_node);
2761 expr_node);
27972762 if (expr_type->id == TypeTableEntryIdInvalid) {
27982763 return expr_type;
27992764 } else if (expr_type->id == TypeTableEntryIdInt &&
......@@ -2805,7 +2770,6 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
28052770 } else if (expr_type->id == TypeTableEntryIdNumberLiteral) {
28062771 return expr_type;
28072772 } else {
2808 BREAKPOINT;
28092773 add_node_error(g, node, buf_sprintf("invalid negation type: '%s'",
28102774 buf_ptr(&expr_type->name)));
28112775 return g->builtin_types.entry_invalid;
......@@ -2814,20 +2778,23 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
28142778 case PrefixOpAddressOf:
28152779 case PrefixOpConstAddressOf:
28162780 {
2817 bool is_const = (node->data.prefix_op_expr.prefix_op == PrefixOpConstAddressOf);
2781 bool is_const = (prefix_op == PrefixOpConstAddressOf);
28182782
28192783 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
28222786 if (child_type->id == TypeTableEntryIdInvalid) {
28232787 return g->builtin_types.entry_invalid;
28242788 } else if (child_type->id == TypeTableEntryIdMetaType) {
2825 TypeTableEntry *meta_child_type = child_type->data.meta_type.child_type;
2826 if (meta_child_type->id == TypeTableEntryIdUnreachable) {
2827 add_node_error(g, node,
2828 buf_create_from_str("pointer to unreachable not allowed"));
2789 TypeTableEntry *meta_type = analyze_type_expr(g, import, context, expr_node);
2790 if (meta_type->id == TypeTableEntryIdInvalid) {
2791 return g->builtin_types.entry_invalid;
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;
28292795 } 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));
28312798 }
28322799 } else {
28332800 return get_pointer_to_type(g, child_type, is_const);
......@@ -2835,14 +2802,13 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
28352802 }
28362803 case PrefixOpDereference:
28372804 {
2838 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr,
2839 node->data.prefix_op_expr.primary_expr);
2805 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
28402806 if (type_entry->id == TypeTableEntryIdInvalid) {
28412807 return type_entry;
28422808 } else if (type_entry->id == TypeTableEntryIdPointer) {
28432809 return type_entry->data.pointer.child_type;
28442810 } else {
2845 add_node_error(g, node->data.prefix_op_expr.primary_expr,
2811 add_node_error(g, expr_node,
28462812 buf_sprintf("indirection requires pointer operand ('%s' invalid)",
28472813 buf_ptr(&type_entry->name)));
28482814 return g->builtin_types.entry_invalid;
......@@ -2850,24 +2816,25 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
28502816 }
28512817 case PrefixOpMaybe:
28522818 {
2853 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr,
2854 node->data.prefix_op_expr.primary_expr);
2819 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
28552820
28562821 if (type_entry->id == TypeTableEntryIdInvalid) {
28572822 return type_entry;
28582823 } else if (type_entry->id == TypeTableEntryIdMetaType) {
2859 TypeTableEntry *child_type = type_entry->data.meta_type.child_type;
2860 if (child_type->id == TypeTableEntryIdUnreachable) {
2824 TypeTableEntry *meta_type = resolve_type(g, expr_node);
2825 if (meta_type->id == TypeTableEntryIdInvalid) {
2826 return g->builtin_types.entry_invalid;
2827 } else if (meta_type->id == TypeTableEntryIdUnreachable) {
28612828 add_node_error(g, node, buf_create_from_str("maybe unreachable type not allowed"));
28622829 return g->builtin_types.entry_invalid;
28632830 } 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));
28652832 }
28662833 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
2867 add_node_error(g, node->data.prefix_op_expr.primary_expr,
2868 buf_sprintf("unable to wrap unreachable in maybe type"));
2834 add_node_error(g, expr_node, buf_sprintf("unable to wrap unreachable in maybe type"));
28692835 return g->builtin_types.entry_invalid;
28702836 } else {
2837 // TODO eval const expr
28712838 return get_maybe_type(g, type_entry);
28722839 }
28732840 }
......@@ -3023,7 +2990,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
30232990 return_type = g->builtin_types.entry_u8;
30242991 break;
30252992 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);
30272994 break;
30282995
30292996 case NodeTypeNullLiteral:
......@@ -3066,10 +3033,29 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
30663033 assert(return_type);
30673034 resolve_type_compatibility(g, context, node, expected_type, return_type);
30683035
3069 get_resolved_expr(node)->type_entry = return_type;
3070 get_resolved_expr(node)->block_context = context;
3036 Expr *expr = get_resolved_expr(node);
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;
30733059}
30743060
30753061static 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
7373 TypeTableEntry *op1_type, TypeTableEntry *op2_type);
7474static LLVMValueRef gen_bare_cast(CodeGen *g, AstNode *node, LLVMValueRef expr_val,
7575 TypeTableEntry *actual_type, TypeTableEntry *wanted_type, Cast *cast_node);
76
76
7777static TypeTableEntry *get_type_for_type_node(AstNode *node) {
78 TypeTableEntry *meta_type_entry = get_resolved_expr(node)->type_entry;
79 assert(meta_type_entry->id == TypeTableEntryIdMetaType);
80 return meta_type_entry->data.meta_type.child_type;
78 Expr *expr = get_resolved_expr(node);
79 assert(expr->type_entry->id == TypeTableEntryIdMetaType);
80 ConstExprValue *const_val = &expr->const_val;
81 assert(const_val->ok);
82 return const_val->data.x_type;
8183}
8284
8385static 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) {
434436 } else if (struct_type->id == TypeTableEntryIdPointer) {
435437 assert(struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct);
436438 fn_table_entry = node->data.fn_call_expr.fn_entry;
437 } else if (struct_type->id == TypeTableEntryIdMetaType &&
438 struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum)
439 {
440 TypeTableEntry *enum_type = struct_type->data.meta_type.child_type;
439 } else if (struct_type->id == TypeTableEntryIdMetaType) {
440 TypeTableEntry *enum_type = get_type_for_type_node(first_param_expr);
441441 int param_count = node->data.fn_call_expr.params.length;
442442 AstNode *arg1_node;
443443 if (param_count == 1) {
......@@ -681,7 +681,8 @@ static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lva
681681static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
682682 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);
685686 Buf *name = &node->data.field_access_expr.field_name;
686687
687688 if (struct_type->id == TypeTableEntryIdArray) {
......@@ -710,14 +711,12 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva
710711 add_debug_source_node(g, node);
711712 return LLVMBuildLoad(g->builder, ptr, "");
712713 }
713 } else if (struct_type->id == TypeTableEntryIdMetaType &&
714 struct_type->data.meta_type.child_type->id == TypeTableEntryIdEnum)
715 {
714 } else if (struct_type->id == TypeTableEntryIdMetaType) {
716715 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);
718717 return gen_enum_value_expr(g, node, enum_type, nullptr);
719718 } else {
720 zig_panic("gen_field_access_expr bad struct type");
719 zig_unreachable();
721720 }
722721}
723722
......@@ -2392,6 +2391,12 @@ static void define_builtin_types(CodeGen *g) {
23922391 g->builtin_types.entry_unreachable = entry;
23932392 g->primitive_type_table.put(&entry->name, entry);
23942393 }
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
23962401 g->builtin_types.entry_c_string_literal = get_pointer_to_type(g, get_int_type(g, false, 8), true);
23972402