authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-04 15:36:30-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-04 15:36:30-04:00
loga2e32939305e470ce3d32c9d2667d3083158ddb3
treefef679349a0c2d2e25072e2960e39b2ec257fa07
parentbc6c33b1b64822b0667ab88b73f4b5c4b302154f

WIP moving all analysis to IR


8 files changed, 4012 insertions(+), 4677 deletions(-)

src/all_types.hpp+8-10
...@@ -738,8 +738,6 @@ struct AstNodeSymbolExpr {...@@ -738,8 +738,6 @@ struct AstNodeSymbolExpr {
738738
739 // populated by semantic analyzer739 // populated by semantic analyzer
740 Expr resolved_expr;740 Expr resolved_expr;
741 // set this to instead of analyzing the node, pretend it's a type entry and it's this one.
742 TypeTableEntry *override_type_entry;
743 TypeEnumField *enum_field;741 TypeEnumField *enum_field;
744 uint32_t err_value;742 uint32_t err_value;
745};743};
...@@ -1439,7 +1437,6 @@ enum IrInstructionId {...@@ -1439,7 +1437,6 @@ enum IrInstructionId {
1439 IrInstructionIdElemPtr,1437 IrInstructionIdElemPtr,
1440 IrInstructionIdVarPtr,1438 IrInstructionIdVarPtr,
1441 IrInstructionIdCall,1439 IrInstructionIdCall,
1442 IrInstructionIdBuiltinCall,
1443 IrInstructionIdConst,1440 IrInstructionIdConst,
1444 IrInstructionIdReturn,1441 IrInstructionIdReturn,
1445 IrInstructionIdCast,1442 IrInstructionIdCast,
...@@ -1449,6 +1446,7 @@ enum IrInstructionId {...@@ -1449,6 +1446,7 @@ enum IrInstructionId {
1449 IrInstructionIdTypeOf,1446 IrInstructionIdTypeOf,
1450 IrInstructionIdToPtrType,1447 IrInstructionIdToPtrType,
1451 IrInstructionIdPtrTypeChild,1448 IrInstructionIdPtrTypeChild,
1449 IrInstructionIdSetFnTest,
1452};1450};
14531451
1454struct IrInstruction {1452struct IrInstruction {
...@@ -1630,13 +1628,6 @@ struct IrInstructionCall {...@@ -1630,13 +1628,6 @@ struct IrInstructionCall {
1630 IrInstruction **args;1628 IrInstruction **args;
1631};1629};
16321630
1633struct IrInstructionBuiltinCall {
1634 IrInstruction base;
1635
1636 BuiltinFnEntry *fn;
1637 IrInstruction **args;
1638};
1639
1640struct IrInstructionConst {1631struct IrInstructionConst {
1641 IrInstruction base;1632 IrInstruction base;
1642};1633};
...@@ -1698,6 +1689,13 @@ struct IrInstructionPtrTypeChild {...@@ -1698,6 +1689,13 @@ struct IrInstructionPtrTypeChild {
1698 IrInstruction *value;1689 IrInstruction *value;
1699};1690};
17001691
1692struct IrInstructionSetFnTest {
1693 IrInstruction base;
1694
1695 IrInstruction *fn_value;
1696 IrInstruction *is_test;
1697};
1698
1701enum LValPurpose {1699enum LValPurpose {
1702 LValPurposeNone,1700 LValPurposeNone,
1703 LValPurposeAssign,1701 LValPurposeAssign,
src/analyze.cpp+353-3258
...@@ -17,41 +17,9 @@...@@ -17,41 +17,9 @@
17#include "parser.hpp"17#include "parser.hpp"
18#include "zig_llvm.hpp"18#include "zig_llvm.hpp"
1919
20static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,20static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *enum_type);
21 TypeTableEntry *expected_type, AstNode *node);
22static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEntry *import,
23 BlockContext *context, TypeTableEntry *expected_type, AstNode *node, bool pointer_only);
24static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,
25 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);
26static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);21static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);
27static TypeTableEntry *unwrapped_node_type(AstNode *node);
28static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
29 BlockContext *context, AstNode *node, Buf *err_name);
30static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
31 TypeTableEntry *expected_type, AstNode *node);
32static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn,
33 bool depends_on_compile_var);
34static TypeTableEntry *resolve_expr_const_val_as_generic_fn(CodeGen *g, AstNode *node,
35 TypeTableEntry *type_entry, bool depends_on_compile_var);
36static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type,
37 bool depends_on_compile_var);
38static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,
39 TypeTableEntry *expected_type, uint64_t x, bool depends_on_compile_var);
40static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node, bool value,
41 bool depends_on_compile_var);
42static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node,
43 bool pointer_only, BlockContext *block_context, bool depends_on_compile_var);
44static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,
45 BlockContext *context, AstNode *source_node,
46 AstNodeVariableDeclaration *variable_declaration,
47 bool expr_is_maybe, AstNode *decl_node, bool var_is_ptr);
48static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node);22static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node);
49static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry);
50static void resolve_use_decl(CodeGen *g, AstNode *node);
51static void preview_use_decl(CodeGen *g, AstNode *node);
52static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, ImportTableEntry *import,
53 BlockContext *context, Buf *name, TypeTableEntry *type_entry, bool is_const,
54 AstNode *val_node);
5523
56AstNode *first_executing_node(AstNode *node) {24AstNode *first_executing_node(AstNode *node) {
57 switch (node->type) {25 switch (node->type) {
...@@ -868,39 +836,52 @@ TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry) {...@@ -868,39 +836,52 @@ TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry) {
868 }836 }
869}837}
870838
871// If the node does not have a constant expression value with a metatype, generates an error839static IrInstruction *analyze_const_value(CodeGen *g, BlockContext *scope, AstNode *node,
872// and returns invalid type. Otherwise, returns the type of the constant expression value.840 TypeTableEntry *expected_type)
873// Must be called after analyze_expression on the same node.841{
874static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {842 IrExecutable ir_executable = {0};
875 if (node->type == NodeTypeSymbol && node->data.symbol_expr.override_type_entry) {843 IrExecutable analyzed_executable = {0};
876 return node->data.symbol_expr.override_type_entry;844 IrInstruction *pass1 = ir_gen(g, node, scope, &ir_executable);
845
846 if (pass1->type_entry->id == TypeTableEntryIdInvalid)
847 return g->invalid_instruction;
848
849 if (g->verbose) {
850 fprintf(stderr, "{\n");
851 ir_print(stderr, &ir_executable, 4);
852 fprintf(stderr, "}\n");
877 }853 }
878 Expr *expr = get_resolved_expr(node);854 TypeTableEntry *result_type = ir_analyze(g, &ir_executable, &analyzed_executable, expected_type, node);
879 assert(expr->type_entry);855 if (result_type->id == TypeTableEntryIdInvalid)
880 if (expr->type_entry->id == TypeTableEntryIdInvalid) {856 return g->invalid_instruction;
881 return g->builtin_types.entry_invalid;857
882 } else if (expr->type_entry->id == TypeTableEntryIdMetaType) {858 if (g->verbose) {
883 // OK859 fprintf(stderr, "{ // (analyzed)\n");
884 } else {860 ir_print(stderr, &analyzed_executable, 4);
885 add_node_error(g, node, buf_sprintf("expected type, found expression"));861 fprintf(stderr, "}\n");
886 return g->builtin_types.entry_invalid;
887 }862 }
888863
889 ConstExprValue *const_val = &expr->const_val;864 IrInstruction *result = ir_exec_const_result(&analyzed_executable);
890 if (!const_val->ok) {865 if (!result) {
891 add_node_error(g, node, buf_sprintf("unable to evaluate constant expression"));866 add_node_error(g, node, buf_sprintf("unable to evaluate constant expression"));
892 return g->builtin_types.entry_invalid;867 return g->invalid_instruction;
893 }868 }
894869
895 return const_val->data.x_type;870 return result;
896}871}
897872
898static TypeTableEntry *analyze_type_expr_pointer_only(CodeGen *g, ImportTableEntry *import,873static TypeTableEntry *analyze_type_expr_pointer_only(CodeGen *g, ImportTableEntry *import,
899 BlockContext *context, AstNode *node, bool pointer_only)874 BlockContext *context, AstNode *node, bool pointer_only)
900{875{
901 AstNode **node_ptr = node->parent_field;876 if (pointer_only)
902 analyze_expression_pointer_only(g, import, context, nullptr, *node_ptr, pointer_only);877 zig_panic("TODO");
903 return resolve_type(g, *node_ptr);878
879 IrInstruction *result = analyze_const_value(g, context, node, g->builtin_types.entry_type);
880 if (result->type_entry->id == TypeTableEntryIdInvalid)
881 return g->builtin_types.entry_invalid;
882
883 assert(result->static_value.ok);
884 return result->static_value.data.x_type;
904}885}
905886
906// Calls analyze_expression on node, and then resolve_type.887// Calls analyze_expression on node, and then resolve_type.
...@@ -1607,6 +1588,34 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN...@@ -1607,6 +1588,34 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN
1607 }1588 }
1608}1589}
16091590
1591static void add_top_level_decl(CodeGen *g, ImportTableEntry *import, BlockContext *block_context,
1592 AstNode *node, Buf *name)
1593{
1594 assert(import);
1595
1596 TopLevelDecl *tld = get_as_top_level_decl(node);
1597 tld->import = import;
1598 tld->name = name;
1599
1600 bool want_to_resolve = (g->check_unused || g->is_test_build || tld->visib_mod == VisibModExport);
1601 bool is_generic_container = (node->type == NodeTypeContainerDecl &&
1602 node->data.struct_decl.generic_params.length > 0);
1603 if (want_to_resolve && !is_generic_container) {
1604 g->resolve_queue.append(node);
1605 }
1606
1607 node->block_context = block_context;
1608
1609 auto entry = block_context->decl_table.maybe_get(name);
1610 if (entry) {
1611 AstNode *other_decl_node = entry->value;
1612 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(name)));
1613 add_error_note(g, msg, other_decl_node, buf_sprintf("previous definition is here"));
1614 } else {
1615 block_context->decl_table.put(name, node);
1616 }
1617}
1618
1610static void scan_struct_decl(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) {1619static void scan_struct_decl(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) {
1611 assert(node->type == NodeTypeContainerDecl);1620 assert(node->type == NodeTypeContainerDecl);
16121621
...@@ -1629,30 +1638,27 @@ static void scan_struct_decl(CodeGen *g, ImportTableEntry *import, BlockContext...@@ -1629,30 +1638,27 @@ static void scan_struct_decl(CodeGen *g, ImportTableEntry *import, BlockContext
1629 }1638 }
1630}1639}
16311640
1632static void resolve_struct_instance(CodeGen *g, ImportTableEntry *import, AstNode *node) {1641static void count_inline_and_var_args(AstNode *proto_node) {
1633 TypeTableEntry *type_entry = node->data.struct_decl.type_entry;1642 assert(proto_node->type == NodeTypeFnProto);
1634 assert(type_entry);
16351643
1636 // struct/enum member fns will get resolved independently1644 size_t *inline_arg_count = &proto_node->data.fn_proto.inline_arg_count;
1645 size_t *inline_or_var_type_arg_count = &proto_node->data.fn_proto.inline_or_var_type_arg_count;
16371646
1638 switch (node->data.struct_decl.kind) {1647 *inline_arg_count = 0;
1639 case ContainerKindStruct:1648 *inline_or_var_type_arg_count = 0;
1640 resolve_struct_type(g, import, type_entry);
1641 break;
1642 case ContainerKindEnum:
1643 resolve_enum_type(g, import, type_entry);
1644 break;
1645 case ContainerKindUnion:
1646 resolve_union_type(g, import, type_entry);
1647 break;
1648 }
1649}
16501649
1651static void resolve_struct_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {1650 // TODO run these nodes through the type analysis system rather than looking for
1652 if (node->data.struct_decl.generic_params.length > 0) {1651 // specialized ast nodes. this would get fooled by `{var}` instead of `var` which
1653 return preview_generic_fn_proto(g, import, node);1652 // is supposed to be equivalent
1654 } else {1653 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
1655 return resolve_struct_instance(g, import, node);1654 AstNode *param_node = proto_node->data.fn_proto.params.at(i);
1655 assert(param_node->type == NodeTypeParamDecl);
1656 if (param_node->data.param_decl.is_inline) {
1657 *inline_arg_count += 1;
1658 *inline_or_var_type_arg_count += 1;
1659 } else if (param_node->data.param_decl.type->type == NodeTypeVarLiteral) {
1660 *inline_or_var_type_arg_count += 1;
1661 }
1656 }1662 }
1657}1663}
16581664
...@@ -1680,6 +1686,137 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) {...@@ -1680,6 +1686,137 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) {
1680 node->data.error_value_decl.top_level_decl.resolution = TldResolutionOk;1686 node->data.error_value_decl.top_level_decl.resolution = TldResolutionOk;
1681}1687}
16821688
1689static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) {
1690 switch (node->type) {
1691 case NodeTypeRoot:
1692 for (size_t i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {
1693 AstNode *child = import->root->data.root.top_level_decls.at(i);
1694 scan_decls(g, import, context, child);
1695 }
1696 break;
1697 case NodeTypeContainerDecl:
1698 {
1699 Buf *name = node->data.struct_decl.name;
1700 add_top_level_decl(g, import, context, node, name);
1701 if (node->data.struct_decl.generic_params.length == 0) {
1702 scan_struct_decl(g, import, context, node);
1703 }
1704 }
1705 break;
1706 case NodeTypeFnDef:
1707 node->data.fn_def.fn_proto->data.fn_proto.fn_def_node = node;
1708 scan_decls(g, import, context, node->data.fn_def.fn_proto);
1709 break;
1710 case NodeTypeVariableDeclaration:
1711 {
1712 Buf *name = node->data.variable_declaration.symbol;
1713 add_top_level_decl(g, import, context, node, name);
1714 break;
1715 }
1716 case NodeTypeTypeDecl:
1717 {
1718 Buf *name = node->data.type_decl.symbol;
1719 add_top_level_decl(g, import, context, node, name);
1720 break;
1721 }
1722 case NodeTypeFnProto:
1723 {
1724 // if the name is missing, we immediately announce an error
1725 Buf *fn_name = node->data.fn_proto.name;
1726 if (buf_len(fn_name) == 0) {
1727 node->data.fn_proto.skip = true;
1728 add_node_error(g, node, buf_sprintf("missing function name"));
1729 break;
1730 }
1731 count_inline_and_var_args(node);
1732
1733 add_top_level_decl(g, import, context, node, fn_name);
1734 break;
1735 }
1736 case NodeTypeUse:
1737 {
1738 TopLevelDecl *tld = get_as_top_level_decl(node);
1739 tld->import = import;
1740 node->block_context = context;
1741 g->use_queue.append(node);
1742 tld->import->use_decls.append(node);
1743 break;
1744 }
1745 case NodeTypeErrorValueDecl:
1746 // error value declarations do not depend on other top level decls
1747 preview_error_value_decl(g, node);
1748 break;
1749 case NodeTypeParamDecl:
1750 case NodeTypeFnDecl:
1751 case NodeTypeReturnExpr:
1752 case NodeTypeDefer:
1753 case NodeTypeBlock:
1754 case NodeTypeBinOpExpr:
1755 case NodeTypeUnwrapErrorExpr:
1756 case NodeTypeFnCallExpr:
1757 case NodeTypeArrayAccessExpr:
1758 case NodeTypeSliceExpr:
1759 case NodeTypeNumberLiteral:
1760 case NodeTypeStringLiteral:
1761 case NodeTypeCharLiteral:
1762 case NodeTypeBoolLiteral:
1763 case NodeTypeNullLiteral:
1764 case NodeTypeUndefinedLiteral:
1765 case NodeTypeZeroesLiteral:
1766 case NodeTypeThisLiteral:
1767 case NodeTypeSymbol:
1768 case NodeTypePrefixOpExpr:
1769 case NodeTypeIfBoolExpr:
1770 case NodeTypeIfVarExpr:
1771 case NodeTypeWhileExpr:
1772 case NodeTypeForExpr:
1773 case NodeTypeSwitchExpr:
1774 case NodeTypeSwitchProng:
1775 case NodeTypeSwitchRange:
1776 case NodeTypeLabel:
1777 case NodeTypeGoto:
1778 case NodeTypeBreak:
1779 case NodeTypeContinue:
1780 case NodeTypeAsmExpr:
1781 case NodeTypeFieldAccessExpr:
1782 case NodeTypeStructField:
1783 case NodeTypeContainerInitExpr:
1784 case NodeTypeStructValueField:
1785 case NodeTypeArrayType:
1786 case NodeTypeErrorType:
1787 case NodeTypeTypeLiteral:
1788 case NodeTypeVarLiteral:
1789 zig_unreachable();
1790 }
1791}
1792
1793static void resolve_struct_instance(CodeGen *g, ImportTableEntry *import, AstNode *node) {
1794 TypeTableEntry *type_entry = node->data.struct_decl.type_entry;
1795 assert(type_entry);
1796
1797 // struct/enum member fns will get resolved independently
1798
1799 switch (node->data.struct_decl.kind) {
1800 case ContainerKindStruct:
1801 resolve_struct_type(g, import, type_entry);
1802 break;
1803 case ContainerKindEnum:
1804 resolve_enum_type(g, import, type_entry);
1805 break;
1806 case ContainerKindUnion:
1807 resolve_union_type(g, import, type_entry);
1808 break;
1809 }
1810}
1811
1812static void resolve_struct_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
1813 if (node->data.struct_decl.generic_params.length > 0) {
1814 return preview_generic_fn_proto(g, import, node);
1815 } else {
1816 return resolve_struct_instance(g, import, node);
1817 }
1818}
1819
1683TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) {1820TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) {
1684 TypeTableEntry *underlying_type = get_underlying_type(type_entry);1821 TypeTableEntry *underlying_type = get_underlying_type(type_entry);
1685 switch (underlying_type->id) {1822 switch (underlying_type->id) {
...@@ -1718,75 +1855,116 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt...@@ -1718,75 +1855,116 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt
1718 zig_unreachable();1855 zig_unreachable();
1719}1856}
17201857
1721static void resolve_var_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {1858// Set name to nullptr to make the variable anonymous (not visible to programmer).
1722 assert(node->type == NodeTypeVariableDeclaration);1859// TODO merge with definition of add_local_var in ir.cpp
17231860static VariableTableEntry *add_local_var_shadowable(CodeGen *g, AstNode *source_node, ImportTableEntry *import,
1724 AstNodeVariableDeclaration *var_decl = &node->data.variable_declaration;1861 BlockContext *context, Buf *name, TypeTableEntry *type_entry, bool is_const, AstNode *val_node,
1725 BlockContext *scope = node->block_context;1862 bool shadowable)
1726 bool is_const = var_decl->is_const;1863{
1727 bool is_export = (var_decl->top_level_decl.visib_mod == VisibModExport);1864 VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1);
1728 bool is_extern = var_decl->is_extern;1865 variable_entry->type = type_entry;
17291866 variable_entry->block_context = context;
1730 assert(!scope->fn_entry);1867 variable_entry->import = import;
17311868 variable_entry->shadowable = shadowable;
1732 TypeTableEntry *explicit_type = nullptr;1869 variable_entry->mem_slot_index = SIZE_MAX;
1733 if (var_decl->type) {
1734 TypeTableEntry *proposed_type = analyze_type_expr(g, import, scope, var_decl->type);
1735 explicit_type = validate_var_type(g, var_decl->type, proposed_type);
1736 }
17371870
1738 TypeTableEntry *implicit_type = nullptr;1871 if (name) {
1739 if (explicit_type && explicit_type->id == TypeTableEntryIdInvalid) {1872 buf_init_from_buf(&variable_entry->name, name);
1740 implicit_type = explicit_type;
1741 } else if (var_decl->expr) {
1742 IrExecutable ir_executable = {0};
1743 IrExecutable analyzed_executable = {0};
1744 IrInstruction *result = ir_gen(g, var_decl->expr, scope, &ir_executable);
1745 if (result == g->invalid_instruction) {
1746 // ignore the poison value
1747 implicit_type = g->builtin_types.entry_invalid;
1748 } else {
1749 if (g->verbose) {
1750 fprintf(stderr, "var %s = {\n", buf_ptr(var_decl->symbol));
1751 ir_print(stderr, &ir_executable, 4);
1752 fprintf(stderr, "}\n");
1753 }
1754 implicit_type = ir_analyze(g, &ir_executable, &analyzed_executable,
1755 explicit_type, var_decl->type);
1756 if (g->verbose) {
1757 fprintf(stderr, "var %s = { // (analyzed)\n", buf_ptr(var_decl->symbol));
1758 ir_print(stderr, &analyzed_executable, 4);
1759 fprintf(stderr, "}\n");
1760 }
17611873
1762 if (implicit_type->id == TypeTableEntryIdUnreachable) {1874 if (type_entry->id != TypeTableEntryIdInvalid) {
1763 add_node_error(g, node,1875 VariableTableEntry *existing_var = find_variable(g, context, name);
1764 buf_sprintf("variable initialization is unreachable"));1876 if (existing_var && !existing_var->shadowable) {
1765 implicit_type = g->builtin_types.entry_invalid;1877 ErrorMsg *msg = add_node_error(g, source_node,
1766 } else if ((!is_const || is_export) &&1878 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
1767 (implicit_type->id == TypeTableEntryIdNumLitFloat ||1879 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
1768 implicit_type->id == TypeTableEntryIdNumLitInt))1880 variable_entry->type = g->builtin_types.entry_invalid;
1769 {1881 } else {
1770 add_node_error(g, node, buf_sprintf("unable to infer variable type"));1882 auto primitive_table_entry = g->primitive_type_table.maybe_get(name);
1771 implicit_type = g->builtin_types.entry_invalid;1883 if (primitive_table_entry) {
1772 } else if (implicit_type->id == TypeTableEntryIdMetaType && !is_const) {1884 TypeTableEntry *type = primitive_table_entry->value;
1773 add_node_error(g, node, buf_sprintf("variable of type 'type' must be constant"));1885 add_node_error(g, source_node,
1774 implicit_type = g->builtin_types.entry_invalid;1886 buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));
1775 }1887 variable_entry->type = g->builtin_types.entry_invalid;
1776 if (implicit_type->id != TypeTableEntryIdInvalid) {
1777 Expr *expr = get_resolved_expr(var_decl->expr);
1778 IrInstruction *result = ir_exec_const_result(&analyzed_executable);
1779 if (result) {
1780 assert(result->static_value.ok);
1781 expr->const_val = result->static_value;
1782 expr->type_entry = result->type_entry;
1783 } else {1888 } else {
1784 add_node_error(g, first_executing_node(var_decl->expr),1889 AstNode *decl_node = find_decl(context, name);
1785 buf_sprintf("global variable initializer requires constant expression"));1890 if (decl_node && decl_node->type != NodeTypeVariableDeclaration) {
1786 implicit_type = g->builtin_types.entry_invalid;1891 ErrorMsg *msg = add_node_error(g, source_node,
1892 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
1893 add_error_note(g, msg, decl_node, buf_sprintf("previous definition is here"));
1894 variable_entry->type = g->builtin_types.entry_invalid;
1895 }
1787 }1896 }
1788 }1897 }
1789 }1898 }
1899
1900 context->var_table.put(&variable_entry->name, variable_entry);
1901 } else {
1902 // TODO replace _anon with @anon and make sure all tests still pass
1903 buf_init_from_str(&variable_entry->name, "_anon");
1904 }
1905 if (context->fn_entry) {
1906 context->fn_entry->variable_list.append(variable_entry);
1907 }
1908
1909 variable_entry->src_is_const = is_const;
1910 variable_entry->gen_is_const = is_const;
1911 variable_entry->decl_node = source_node;
1912 variable_entry->val_node = val_node;
1913
1914
1915 return variable_entry;
1916}
1917
1918static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, ImportTableEntry *import,
1919 BlockContext *context, Buf *name, TypeTableEntry *type_entry, bool is_const, AstNode *val_node)
1920{
1921 return add_local_var_shadowable(g, source_node, import, context, name, type_entry, is_const, val_node, false);
1922}
1923
1924static void resolve_var_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
1925 assert(node->type == NodeTypeVariableDeclaration);
1926
1927 AstNodeVariableDeclaration *var_decl = &node->data.variable_declaration;
1928 BlockContext *scope = node->block_context;
1929 bool is_const = var_decl->is_const;
1930 bool is_export = (var_decl->top_level_decl.visib_mod == VisibModExport);
1931 bool is_extern = var_decl->is_extern;
1932
1933 assert(!scope->fn_entry);
1934
1935 TypeTableEntry *explicit_type = nullptr;
1936 if (var_decl->type) {
1937 TypeTableEntry *proposed_type = analyze_type_expr(g, import, scope, var_decl->type);
1938 explicit_type = validate_var_type(g, var_decl->type, proposed_type);
1939 }
1940
1941 TypeTableEntry *implicit_type = nullptr;
1942 if (explicit_type && explicit_type->id == TypeTableEntryIdInvalid) {
1943 implicit_type = explicit_type;
1944 } else if (var_decl->expr) {
1945 IrInstruction *result = analyze_const_value(g, scope, var_decl->expr, explicit_type);
1946 assert(result);
1947 implicit_type = result->type_entry;
1948
1949 if (implicit_type->id == TypeTableEntryIdUnreachable) {
1950 add_node_error(g, node, buf_sprintf("variable initialization is unreachable"));
1951 implicit_type = g->builtin_types.entry_invalid;
1952 } else if ((!is_const || is_export) &&
1953 (implicit_type->id == TypeTableEntryIdNumLitFloat ||
1954 implicit_type->id == TypeTableEntryIdNumLitInt))
1955 {
1956 add_node_error(g, node, buf_sprintf("unable to infer variable type"));
1957 implicit_type = g->builtin_types.entry_invalid;
1958 } else if (implicit_type->id == TypeTableEntryIdMetaType && !is_const) {
1959 add_node_error(g, node, buf_sprintf("variable of type 'type' must be constant"));
1960 implicit_type = g->builtin_types.entry_invalid;
1961 }
1962 if (implicit_type->id != TypeTableEntryIdInvalid) {
1963 Expr *expr = get_resolved_expr(var_decl->expr);
1964 assert(result->static_value.ok);
1965 expr->const_val = result->static_value;
1966 expr->type_entry = result->type_entry;
1967 }
1790 } else if (!is_extern) {1968 } else if (!is_extern) {
1791 add_node_error(g, node, buf_sprintf("variables must be initialized"));1969 add_node_error(g, node, buf_sprintf("variables must be initialized"));
1792 implicit_type = g->builtin_types.entry_invalid;1970 implicit_type = g->builtin_types.entry_invalid;
...@@ -1906,30 +2084,6 @@ void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only) {...@@ -1906,30 +2084,6 @@ void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only) {
1906 tld->dep_loop_flag = false;2084 tld->dep_loop_flag = false;
1907}2085}
19082086
1909static FnTableEntry *get_context_fn_entry(BlockContext *context) {
1910 assert(context->fn_entry);
1911 return context->fn_entry;
1912}
1913
1914static TypeTableEntry *unwrapped_node_type(AstNode *node) {
1915 Expr *expr = get_resolved_expr(node);
1916 if (expr->type_entry->id == TypeTableEntryIdInvalid) {
1917 return expr->type_entry;
1918 }
1919 assert(expr->type_entry->id == TypeTableEntryIdMetaType);
1920 ConstExprValue *const_val = &expr->const_val;
1921 assert(const_val->ok);
1922 return const_val->data.x_type;
1923}
1924
1925static TypeTableEntry *get_return_type(BlockContext *context) {
1926 FnTableEntry *fn_entry = get_context_fn_entry(context);
1927 AstNode *fn_proto_node = fn_entry->proto_node;
1928 assert(fn_proto_node->type == NodeTypeFnProto);
1929 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
1930 return unwrapped_node_type(return_type_node);
1931}
1932
1933static bool type_has_codegen_value(TypeTableEntry *type_entry) {2087static bool type_has_codegen_value(TypeTableEntry *type_entry) {
1934 switch (type_entry->id) {2088 switch (type_entry->id) {
1935 case TypeTableEntryIdInvalid:2089 case TypeTableEntryIdInvalid:
...@@ -1968,18 +2122,6 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {...@@ -1968,18 +2122,6 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {
1968 zig_unreachable();2122 zig_unreachable();
1969}2123}
19702124
1971static void add_global_const_expr(CodeGen *g, AstNode *expr_node) {
1972 Expr *expr = get_resolved_expr(expr_node);
1973 if (expr->const_val.ok &&
1974 type_has_codegen_value(expr->type_entry) &&
1975 !expr->has_global_const &&
1976 type_has_bits(expr->type_entry))
1977 {
1978 g->global_const_list.append(expr_node);
1979 expr->has_global_const = true;
1980 }
1981}
1982
1983static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTableEntry *other_type) {2125static bool num_lit_fits_in_other_type(CodeGen *g, AstNode *literal_node, TypeTableEntry *other_type) {
1984 TypeTableEntry *other_type_underlying = get_underlying_type(other_type);2126 TypeTableEntry *other_type_underlying = get_underlying_type(other_type);
19852127
...@@ -2105,85 +2247,6 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *...@@ -2105,85 +2247,6 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *
2105 return false;2247 return false;
2106}2248}
21072249
2108static TypeTableEntry *determine_peer_type_compatibility(CodeGen *g, AstNode *parent_source_node,
2109 AstNode **child_nodes, TypeTableEntry **child_types, size_t child_count)
2110{
2111 TypeTableEntry *prev_type = child_types[0];
2112 AstNode *prev_node = child_nodes[0];
2113 if (prev_type->id == TypeTableEntryIdInvalid) {
2114 return prev_type;
2115 }
2116 for (size_t i = 1; i < child_count; i += 1) {
2117 TypeTableEntry *cur_type = child_types[i];
2118 AstNode *cur_node = child_nodes[i];
2119 if (cur_type->id == TypeTableEntryIdInvalid) {
2120 return cur_type;
2121 } else if (types_match_const_cast_only(prev_type, cur_type)) {
2122 continue;
2123 } else if (types_match_const_cast_only(cur_type, prev_type)) {
2124 prev_type = cur_type;
2125 prev_node = cur_node;
2126 continue;
2127 } else if (prev_type->id == TypeTableEntryIdUnreachable) {
2128 prev_type = cur_type;
2129 prev_node = cur_node;
2130 } else if (cur_type->id == TypeTableEntryIdUnreachable) {
2131 continue;
2132 } else if (prev_type->id == TypeTableEntryIdInt &&
2133 cur_type->id == TypeTableEntryIdInt &&
2134 prev_type->data.integral.is_signed == cur_type->data.integral.is_signed)
2135 {
2136 if (cur_type->data.integral.bit_count > prev_type->data.integral.bit_count) {
2137 prev_type = cur_type;
2138 prev_node = cur_node;
2139 }
2140 continue;
2141 } else if (prev_type->id == TypeTableEntryIdFloat &&
2142 cur_type->id == TypeTableEntryIdFloat)
2143 {
2144 if (cur_type->data.floating.bit_count > prev_type->data.floating.bit_count) {
2145 prev_type = cur_type;
2146 prev_node = cur_node;
2147 }
2148 } else if (prev_type->id == TypeTableEntryIdErrorUnion &&
2149 types_match_const_cast_only(prev_type->data.error.child_type, cur_type))
2150 {
2151 continue;
2152 } else if (cur_type->id == TypeTableEntryIdErrorUnion &&
2153 types_match_const_cast_only(cur_type->data.error.child_type, prev_type))
2154 {
2155 prev_type = cur_type;
2156 prev_node = cur_node;
2157 continue;
2158 } else if (prev_type->id == TypeTableEntryIdNumLitInt ||
2159 prev_type->id == TypeTableEntryIdNumLitFloat)
2160 {
2161 if (num_lit_fits_in_other_type(g, prev_node, cur_type)) {
2162 prev_type = cur_type;
2163 prev_node = cur_node;
2164 continue;
2165 } else {
2166 return g->builtin_types.entry_invalid;
2167 }
2168 } else if (cur_type->id == TypeTableEntryIdNumLitInt ||
2169 cur_type->id == TypeTableEntryIdNumLitFloat)
2170 {
2171 if (num_lit_fits_in_other_type(g, cur_node, prev_type)) {
2172 continue;
2173 } else {
2174 return g->builtin_types.entry_invalid;
2175 }
2176 } else {
2177 add_node_error(g, parent_source_node,
2178 buf_sprintf("incompatible types: '%s' and '%s'",
2179 buf_ptr(&prev_type->name), buf_ptr(&cur_type->name)));
2180
2181 return g->builtin_types.entry_invalid;
2182 }
2183 }
2184 return prev_type;
2185}
2186
2187static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_type,2250static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_type,
2188 TypeTableEntry *actual_type, AstNode *literal_node, bool *reported_err)2251 TypeTableEntry *actual_type, AstNode *literal_node, bool *reported_err)
2189{2252{
...@@ -2272,104 +2335,6 @@ static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_...@@ -2272,104 +2335,6 @@ static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_
2272 return false;2335 return false;
2273}2336}
22742337
2275static AstNode *create_ast_node(CodeGen *g, ImportTableEntry *import, NodeType kind, AstNode *source_node) {
2276 AstNode *node = allocate<AstNode>(1);
2277 node->type = kind;
2278 node->owner = import;
2279 node->create_index = g->next_node_index;
2280 g->next_node_index += 1;
2281 node->line = source_node->line;
2282 node->column = source_node->column;
2283 return node;
2284}
2285
2286static AstNode *create_ast_type_node(CodeGen *g, ImportTableEntry *import, TypeTableEntry *type_entry,
2287 AstNode *source_node)
2288{
2289 AstNode *node = create_ast_node(g, import, NodeTypeSymbol, source_node);
2290 node->data.symbol_expr.override_type_entry = type_entry;
2291 return node;
2292}
2293
2294static AstNode *create_ast_void_node(CodeGen *g, ImportTableEntry *import, AstNode *source_node) {
2295 AstNode *node = create_ast_node(g, import, NodeTypeContainerInitExpr, source_node);
2296 node->data.container_init_expr.kind = ContainerInitKindArray;
2297 node->data.container_init_expr.type = create_ast_type_node(g, import, g->builtin_types.entry_void,
2298 source_node);
2299 normalize_parent_ptrs(node);
2300 return node;
2301}
2302
2303static TypeTableEntry *create_and_analyze_cast_node(CodeGen *g, ImportTableEntry *import,
2304 BlockContext *context, TypeTableEntry *cast_to_type, AstNode *node)
2305{
2306 AstNode *new_parent_node = create_ast_node(g, import, NodeTypeFnCallExpr, node);
2307 *node->parent_field = new_parent_node;
2308 new_parent_node->parent_field = node->parent_field;
2309
2310 new_parent_node->data.fn_call_expr.fn_ref_expr = create_ast_type_node(g, import, cast_to_type, node);
2311 new_parent_node->data.fn_call_expr.params.append(node);
2312 normalize_parent_ptrs(new_parent_node);
2313
2314 return analyze_expression(g, import, context, cast_to_type, new_parent_node);
2315}
2316
2317static TypeTableEntry *resolve_type_compatibility(CodeGen *g, ImportTableEntry *import,
2318 BlockContext *context, AstNode *node,
2319 TypeTableEntry *expected_type, TypeTableEntry *actual_type)
2320{
2321 if (expected_type == nullptr)
2322 return actual_type; // anything will do
2323 if (expected_type == actual_type)
2324 return expected_type; // match
2325 if (expected_type->id == TypeTableEntryIdInvalid || actual_type->id == TypeTableEntryIdInvalid)
2326 return g->builtin_types.entry_invalid;
2327 if (actual_type->id == TypeTableEntryIdUnreachable)
2328 return actual_type;
2329
2330 bool reported_err = false;
2331 if (types_match_with_implicit_cast(g, expected_type, actual_type, node, &reported_err)) {
2332 return create_and_analyze_cast_node(g, import, context, expected_type, node);
2333 }
2334
2335 if (!reported_err) {
2336 add_node_error(g, first_executing_node(node),
2337 buf_sprintf("expected type '%s', got '%s'",
2338 buf_ptr(&expected_type->name),
2339 buf_ptr(&actual_type->name)));
2340 }
2341
2342 return g->builtin_types.entry_invalid;
2343}
2344
2345TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, ImportTableEntry *import,
2346 BlockContext *block_context, AstNode *parent_source_node,
2347 AstNode **child_nodes, TypeTableEntry **child_types, size_t child_count)
2348{
2349 assert(child_count > 0);
2350
2351 TypeTableEntry *expected_type = determine_peer_type_compatibility(g, parent_source_node,
2352 child_nodes, child_types, child_count);
2353
2354 if (expected_type->id == TypeTableEntryIdInvalid) {
2355 return expected_type;
2356 }
2357
2358 for (size_t i = 0; i < child_count; i += 1) {
2359 if (!child_nodes[i]) {
2360 continue;
2361 }
2362 AstNode **child_node = child_nodes[i]->parent_field;
2363 TypeTableEntry *resolved_type = resolve_type_compatibility(g, import, block_context,
2364 *child_node, expected_type, child_types[i]);
2365 Expr *expr = get_resolved_expr(*child_node);
2366 expr->type_entry = resolved_type;
2367 add_global_const_expr(g, *child_node);
2368 }
2369
2370 return expected_type;
2371}
2372
2373BlockContext *new_block_context(AstNode *node, BlockContext *parent) {2338BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
2374 BlockContext *context = allocate<BlockContext>(1);2339 BlockContext *context = allocate<BlockContext>(1);
2375 context->node = node;2340 context->node = node;
...@@ -2432,67 +2397,6 @@ TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name) {...@@ -2432,67 +2397,6 @@ TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name) {
2432 return nullptr;2397 return nullptr;
2433}2398}
24342399
2435static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2436 AstNode *field_access_node, AstNode *value_node, TypeTableEntry *enum_type, Buf *field_name,
2437 AstNode *out_node)
2438{
2439 assert(field_access_node->type == NodeTypeFieldAccessExpr);
2440
2441 TypeEnumField *type_enum_field = find_enum_type_field(enum_type, field_name);
2442 if (type_enum_field->type_entry->id == TypeTableEntryIdInvalid) {
2443 return g->builtin_types.entry_invalid;
2444 }
2445
2446 field_access_node->data.field_access_expr.type_enum_field = type_enum_field;
2447
2448 if (type_enum_field) {
2449 if (value_node) {
2450 AstNode **value_node_ptr = value_node->parent_field;
2451 TypeTableEntry *value_type = analyze_expression(g, import, context,
2452 type_enum_field->type_entry, value_node);
2453
2454 if (value_type->id == TypeTableEntryIdInvalid) {
2455 return g->builtin_types.entry_invalid;
2456 }
2457
2458 StructValExprCodeGen *codegen = &field_access_node->data.field_access_expr.resolved_struct_val_expr;
2459 codegen->type_entry = enum_type;
2460 codegen->source_node = field_access_node;
2461
2462 ConstExprValue *value_const_val = &get_resolved_expr(*value_node_ptr)->const_val;
2463 if (value_const_val->ok) {
2464 ConstExprValue *const_val = &get_resolved_expr(out_node)->const_val;
2465 const_val->ok = true;
2466 const_val->data.x_enum.tag = type_enum_field->value;
2467 const_val->data.x_enum.payload = value_const_val;
2468 } else {
2469 if (context->fn_entry) {
2470 context->fn_entry->struct_val_expr_alloca_list.append(codegen);
2471 } else {
2472 add_node_error(g, *value_node_ptr, buf_sprintf("unable to evaluate constant expression"));
2473 return g->builtin_types.entry_invalid;
2474 }
2475 }
2476 } else if (type_enum_field->type_entry->id != TypeTableEntryIdVoid) {
2477 add_node_error(g, field_access_node,
2478 buf_sprintf("enum value '%s.%s' requires parameter of type '%s'",
2479 buf_ptr(&enum_type->name),
2480 buf_ptr(field_name),
2481 buf_ptr(&type_enum_field->type_entry->name)));
2482 } else {
2483 Expr *expr = get_resolved_expr(out_node);
2484 expr->const_val.ok = true;
2485 expr->const_val.data.x_enum.tag = type_enum_field->value;
2486 expr->const_val.data.x_enum.payload = nullptr;
2487 }
2488 } else {
2489 add_node_error(g, field_access_node,
2490 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
2491 buf_ptr(&enum_type->name)));
2492 }
2493 return enum_type;
2494}
2495
2496TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name) {2400TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name) {
2497 assert(type_entry->id == TypeTableEntryIdStruct);2401 assert(type_entry->id == TypeTableEntryIdStruct);
2498 assert(type_entry->data.structure.complete);2402 assert(type_entry->data.structure.complete);
...@@ -2587,2703 +2491,50 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {...@@ -2587,2703 +2491,50 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
2587 }2491 }
2588}2492}
25892493
2590static TypeTableEntry *analyze_container_member_access_inner(CodeGen *g,2494bool type_is_codegen_pointer(TypeTableEntry *type) {
2591 TypeTableEntry *bare_struct_type, Buf *field_name, AstNode *node, TypeTableEntry *struct_type)2495 if (type->id == TypeTableEntryIdPointer) return true;
2592{2496 if (type->id == TypeTableEntryIdFn) return true;
2593 assert(node->type == NodeTypeFieldAccessExpr);2497 if (type->id == TypeTableEntryIdMaybe) {
2594 if (!is_slice(bare_struct_type)) {2498 if (type->data.maybe.child_type->id == TypeTableEntryIdPointer) return true;
2595 BlockContext *container_block_context = get_container_block_context(bare_struct_type);2499 if (type->data.maybe.child_type->id == TypeTableEntryIdFn) return true;
2596 assert(container_block_context);
2597 auto entry = container_block_context->decl_table.maybe_get(field_name);
2598 AstNode *fn_decl_node = entry ? entry->value : nullptr;
2599 if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) {
2600 resolve_top_level_decl(g, fn_decl_node, false);
2601 TopLevelDecl *tld = get_as_top_level_decl(fn_decl_node);
2602 if (tld->resolution == TldResolutionInvalid) {
2603 return g->builtin_types.entry_invalid;
2604 }
2605
2606 node->data.field_access_expr.is_member_fn = true;
2607 FnTableEntry *fn_entry = fn_decl_node->data.fn_proto.fn_table_entry;
2608 if (fn_entry->type_entry->id == TypeTableEntryIdGenericFn) {
2609 return resolve_expr_const_val_as_generic_fn(g, node, fn_entry->type_entry, false);
2610 } else {
2611 return resolve_expr_const_val_as_fn(g, node, fn_entry, false);
2612 }
2613 }
2614 }2500 }
2615 add_node_error(g, node,2501 return false;
2616 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&bare_struct_type->name)));
2617 return g->builtin_types.entry_invalid;
2618}2502}
26192503
2620static TypeTableEntry *analyze_container_member_access(CodeGen *g,
2621 Buf *field_name, AstNode *node, TypeTableEntry *struct_type)
2622{
2623 TypeTableEntry *bare_type = container_ref_type(struct_type);
2624 if (!type_is_complete(bare_type)) {
2625 resolve_container_type(g, bare_type);
2626 }
26272504
2628 node->data.field_access_expr.bare_container_type = bare_type;
26292505
2630 if (bare_type->id == TypeTableEntryIdStruct) {2506static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
2631 node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_type, field_name);2507 ImportTableEntry *import = fn_table_entry->import_entry;
2632 if (node->data.field_access_expr.type_struct_field) {2508 AstNode *node = fn_table_entry->fn_def_node;
2633 return node->data.field_access_expr.type_struct_field->type_entry;2509 assert(node->type == NodeTypeFnDef);
2634 } else {
2635 return analyze_container_member_access_inner(g, bare_type, field_name,
2636 node, struct_type);
2637 }
2638 } else if (bare_type->id == TypeTableEntryIdEnum) {
2639 node->data.field_access_expr.type_enum_field = find_enum_type_field(bare_type, field_name);
2640 if (node->data.field_access_expr.type_enum_field) {
2641 return node->data.field_access_expr.type_enum_field->type_entry;
2642 } else {
2643 return analyze_container_member_access_inner(g, bare_type, field_name,
2644 node, struct_type);
2645 }
2646 } else if (bare_type->id == TypeTableEntryIdUnion) {
2647 zig_panic("TODO");
2648 } else {
2649 zig_unreachable();
2650 }
2651}
26522510
2653static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,2511 AstNode *fn_proto_node = node->data.fn_def.fn_proto;
2654 TypeTableEntry *expected_type, AstNode *node)2512 assert(fn_proto_node->type == NodeTypeFnProto);
2655{
2656 assert(node->type == NodeTypeFieldAccessExpr);
2657
2658 AstNode **struct_expr_node = &node->data.field_access_expr.struct_expr;
2659 TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, *struct_expr_node);
2660 Buf *field_name = node->data.field_access_expr.field_name;
2661
2662 if (struct_type->id == TypeTableEntryIdInvalid) {
2663 return struct_type;
2664 } else if (is_container_ref(struct_type)) {
2665 return analyze_container_member_access(g, field_name, node, struct_type);
2666 } else if (struct_type->id == TypeTableEntryIdArray) {
2667 if (buf_eql_str(field_name, "len")) {
2668 return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
2669 struct_type->data.array.len, false);
2670 } else {
2671 add_node_error(g, node,
2672 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
2673 buf_ptr(&struct_type->name)));
2674 return g->builtin_types.entry_invalid;
2675 }
2676 } else if (struct_type->id == TypeTableEntryIdMetaType) {
2677 TypeTableEntry *child_type = resolve_type(g, *struct_expr_node);
26782513
2679 if (child_type->id == TypeTableEntryIdInvalid) {2514 if (fn_proto_node->data.fn_proto.skip) {
2680 return g->builtin_types.entry_invalid;2515 // we detected an error with this function definition which prevents us
2681 } else if (child_type->id == TypeTableEntryIdEnum) {2516 // from further analyzing it.
2682 AstNode *container_init_node = node->data.field_access_expr.container_init_expr_node;2517 fn_table_entry->anal_state = FnAnalStateSkipped;
2683 AstNode *value_node;2518 return;
2684 if (container_init_node) {
2685 assert(container_init_node->type == NodeTypeContainerInitExpr);
2686 size_t param_count = container_init_node->data.container_init_expr.entries.length;
2687 if (param_count > 1) {
2688 AstNode *first_invalid_node = container_init_node->data.container_init_expr.entries.at(1);
2689 add_node_error(g, first_executing_node(first_invalid_node),
2690 buf_sprintf("enum values accept only one parameter"));
2691 return child_type;
2692 } else {
2693 if (param_count == 1) {
2694 value_node = container_init_node->data.container_init_expr.entries.at(0);
2695 } else {
2696 value_node = nullptr;
2697 }
2698 container_init_node->data.container_init_expr.enum_type = child_type;
2699 }
2700 } else {
2701 value_node = nullptr;
2702 }
2703 return analyze_enum_value_expr(g, import, context, node, value_node, child_type, field_name, node);
2704 } else if (child_type->id == TypeTableEntryIdStruct) {
2705 BlockContext *container_block_context = get_container_block_context(child_type);
2706 auto entry = container_block_context->decl_table.maybe_get(field_name);
2707 AstNode *decl_node = entry ? entry->value : nullptr;
2708 if (decl_node) {
2709 bool pointer_only = false;
2710 return analyze_decl_ref(g, node, decl_node, pointer_only, context, false);
2711 } else {
2712 add_node_error(g, node,
2713 buf_sprintf("container '%s' has no member called '%s'",
2714 buf_ptr(&child_type->name), buf_ptr(field_name)));
2715 return g->builtin_types.entry_invalid;
2716 }
2717 } else if (child_type->id == TypeTableEntryIdPureError) {
2718 return analyze_error_literal_expr(g, import, context, node, field_name);
2719 } else if (child_type->id == TypeTableEntryIdInt) {
2720 bool depends_on_compile_var =
2721 get_resolved_expr(*struct_expr_node)->const_val.depends_on_compile_var;
2722 if (buf_eql_str(field_name, "bit_count")) {
2723 return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
2724 child_type->data.integral.bit_count, depends_on_compile_var);
2725 } else if (buf_eql_str(field_name, "is_signed")) {
2726 return resolve_expr_const_val_as_bool(g, node, child_type->data.integral.is_signed,
2727 depends_on_compile_var);
2728 } else {
2729 add_node_error(g, node,
2730 buf_sprintf("type '%s' has no member called '%s'",
2731 buf_ptr(&child_type->name), buf_ptr(field_name)));
2732 return g->builtin_types.entry_invalid;
2733 }
2734 } else {
2735 add_node_error(g, node,
2736 buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name)));
2737 return g->builtin_types.entry_invalid;
2738 }
2739 } else if (struct_type->id == TypeTableEntryIdNamespace) {
2740 ConstExprValue *const_val = &get_resolved_expr(*struct_expr_node)->const_val;
2741 assert(const_val->ok);
2742 ImportTableEntry *namespace_import = const_val->data.x_import;
2743 AstNode *decl_node = find_decl(namespace_import->block_context, field_name);
2744 if (!decl_node) {
2745 // we must now resolve all the use decls
2746 for (size_t i = 0; i < namespace_import->use_decls.length; i += 1) {
2747 AstNode *use_decl_node = namespace_import->use_decls.at(i);
2748 if (!get_resolved_expr(use_decl_node->data.use.expr)->type_entry) {
2749 preview_use_decl(g, use_decl_node);
2750 }
2751 resolve_use_decl(g, use_decl_node);
2752 }
2753 decl_node = find_decl(namespace_import->block_context, field_name);
2754 }
2755 if (decl_node) {
2756 TopLevelDecl *tld = get_as_top_level_decl(decl_node);
2757 if (tld->visib_mod == VisibModPrivate && decl_node->owner != import) {
2758 ErrorMsg *msg = add_node_error(g, node,
2759 buf_sprintf("'%s' is private", buf_ptr(field_name)));
2760 add_error_note(g, msg, decl_node, buf_sprintf("declared here"));
2761 }
2762 bool pointer_only = false;
2763 return analyze_decl_ref(g, node, decl_node, pointer_only, context,
2764 const_val->depends_on_compile_var);
2765 } else {
2766 const char *import_name = namespace_import->path ? buf_ptr(namespace_import->path) : "(C import)";
2767 add_node_error(g, node,
2768 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), import_name));
2769 return g->builtin_types.entry_invalid;
2770 }
2771 } else {
2772 add_node_error(g, node,
2773 buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name)));
2774 return g->builtin_types.entry_invalid;
2775 }2519 }
2776}2520 fn_table_entry->anal_state = FnAnalStateProbing;
27772521
2778static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,2522 BlockContext *context = node->data.fn_def.block_context;
2779 AstNode *node)
2780{
2781 assert(node->type == NodeTypeSliceExpr);
2782
2783 TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr,
2784 node->data.slice_expr.array_ref_expr);
2785
2786 TypeTableEntry *return_type;
2787
2788 if (array_type->id == TypeTableEntryIdInvalid) {
2789 return_type = g->builtin_types.entry_invalid;
2790 } else if (array_type->id == TypeTableEntryIdArray) {
2791 return_type = get_slice_type(g, array_type->data.array.child_type,
2792 node->data.slice_expr.is_const);
2793 } else if (array_type->id == TypeTableEntryIdPointer) {
2794 return_type = get_slice_type(g, array_type->data.pointer.child_type,
2795 node->data.slice_expr.is_const);
2796 } else if (array_type->id == TypeTableEntryIdStruct &&
2797 array_type->data.structure.is_slice)
2798 {
2799 return_type = get_slice_type(g,
2800 array_type->data.structure.fields[0].type_entry->data.pointer.child_type,
2801 node->data.slice_expr.is_const);
2802 } else {
2803 add_node_error(g, node,
2804 buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name)));
2805 return_type = g->builtin_types.entry_invalid;
2806 }
28072523
2808 if (return_type->id != TypeTableEntryIdInvalid) {2524 TypeTableEntry *fn_type = fn_table_entry->type_entry;
2809 node->data.slice_expr.resolved_struct_val_expr.type_entry = return_type;2525 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
2810 node->data.slice_expr.resolved_struct_val_expr.source_node = node;2526 AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto;
2811 context->fn_entry->struct_val_expr_alloca_list.append(&node->data.slice_expr.resolved_struct_val_expr);2527 for (size_t i = 0; i < fn_proto->params.length; i += 1) {
2812 }2528 AstNode *param_decl_node = fn_proto->params.at(i);
2529 assert(param_decl_node->type == NodeTypeParamDecl);
28132530
2814 analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.slice_expr.start);2531 // define local variables for parameters
2532 AstNodeParamDecl *param_decl = &param_decl_node->data.param_decl;
2533 TypeTableEntry *type = fn_type_id->param_info[i].type;
28152534
2816 if (node->data.slice_expr.end) {2535 if (param_decl->is_noalias && !type_is_codegen_pointer(type)) {
2817 analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.slice_expr.end);2536 add_node_error(g, param_decl_node, buf_sprintf("noalias on non-pointer parameter"));
2818 }2537 }
2819
2820 return return_type;
2821}
2822
2823static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2824 AstNode *node, LValPurpose purpose)
2825{
2826 TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr,
2827 node->data.array_access_expr.array_ref_expr);
2828
2829 TypeTableEntry *return_type;
2830
2831 if (array_type->id == TypeTableEntryIdInvalid) {
2832 return_type = g->builtin_types.entry_invalid;
2833 } else if (array_type->id == TypeTableEntryIdArray) {
2834 if (array_type->data.array.len == 0) {
2835 add_node_error(g, node, buf_sprintf("out of bounds array access"));
2836 }
2837 return_type = array_type->data.array.child_type;
2838 } else if (array_type->id == TypeTableEntryIdPointer) {
2839 if (array_type->data.pointer.is_const && purpose == LValPurposeAssign) {
2840 add_node_error(g, node, buf_sprintf("cannot assign to constant"));
2841 return g->builtin_types.entry_invalid;
2842 }
2843 return_type = array_type->data.pointer.child_type;
2844 } else if (array_type->id == TypeTableEntryIdStruct &&
2845 array_type->data.structure.is_slice)
2846 {
2847 TypeTableEntry *pointer_type = array_type->data.structure.fields[0].type_entry;
2848 if (pointer_type->data.pointer.is_const && purpose == LValPurposeAssign) {
2849 add_node_error(g, node, buf_sprintf("cannot assign to constant"));
2850 return g->builtin_types.entry_invalid;
2851 }
2852 return_type = pointer_type->data.pointer.child_type;
2853 } else {
2854 add_node_error(g, node,
2855 buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));
2856 return_type = g->builtin_types.entry_invalid;
2857 }
2858
2859 analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.array_access_expr.subscript);
2860
2861 return return_type;
2862}
2863
2864static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type,
2865 bool depends_on_compile_var)
2866{
2867 Expr *expr = get_resolved_expr(node);
2868 expr->const_val.ok = true;
2869 expr->const_val.data.x_type = type;
2870 expr->const_val.depends_on_compile_var = depends_on_compile_var;
2871 return g->builtin_types.entry_type;
2872}
2873
2874static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode *node, AstNode *other,
2875 bool depends_on_compile_var)
2876{
2877 Expr *expr = get_resolved_expr(node);
2878 Expr *other_expr = get_resolved_expr(other);
2879 expr->const_val = other_expr->const_val;
2880 expr->const_val.depends_on_compile_var = expr->const_val.depends_on_compile_var ||
2881 depends_on_compile_var;
2882 return other_expr->type_entry;
2883}
2884
2885static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn,
2886 bool depends_on_compile_var)
2887{
2888 Expr *expr = get_resolved_expr(node);
2889 expr->const_val.ok = true;
2890 expr->const_val.data.x_fn = fn;
2891 expr->const_val.depends_on_compile_var = depends_on_compile_var;
2892 return fn->type_entry;
2893}
2894
2895static TypeTableEntry *resolve_expr_const_val_as_generic_fn(CodeGen *g, AstNode *node,
2896 TypeTableEntry *type_entry, bool depends_on_compile_var)
2897{
2898 Expr *expr = get_resolved_expr(node);
2899 expr->const_val.ok = true;
2900 expr->const_val.data.x_type = type_entry;
2901 expr->const_val.depends_on_compile_var = depends_on_compile_var;
2902 return type_entry;
2903}
2904
2905
2906static TypeTableEntry *resolve_expr_const_val_as_err(CodeGen *g, AstNode *node, ErrorTableEntry *err) {
2907 Expr *expr = get_resolved_expr(node);
2908 expr->const_val.ok = true;
2909 expr->const_val.data.x_err.err = err;
2910 return g->builtin_types.entry_pure_error;
2911}
2912
2913static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node, bool value,
2914 bool depends_on_compile_var)
2915{
2916 Expr *expr = get_resolved_expr(node);
2917 expr->const_val.ok = true;
2918 expr->const_val.depends_on_compile_var = depends_on_compile_var;
2919 expr->const_val.data.x_bool = value;
2920 return g->builtin_types.entry_bool;
2921}
2922
2923static TypeTableEntry *resolve_expr_const_val_as_c_string_lit(CodeGen *g, AstNode *node, Buf *str) {
2924 Expr *expr = get_resolved_expr(node);
2925 expr->const_val.ok = true;
2926
2927 size_t len_with_null = buf_len(str) + 1;
2928 expr->const_val.data.x_ptr.ptr = allocate<ConstExprValue*>(len_with_null);
2929 expr->const_val.data.x_ptr.len = len_with_null;
2930 expr->const_val.data.x_ptr.is_c_str = true;
2931
2932 ConstExprValue *all_chars = allocate<ConstExprValue>(len_with_null);
2933 for (size_t i = 0; i < buf_len(str); i += 1) {
2934 ConstExprValue *this_char = &all_chars[i];
2935 this_char->ok = true;
2936 bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);
2937 expr->const_val.data.x_ptr.ptr[i] = this_char;
2938 }
2939
2940 ConstExprValue *null_char = &all_chars[len_with_null - 1];
2941 null_char->ok = true;
2942 bignum_init_unsigned(&null_char->data.x_bignum, 0);
2943 expr->const_val.data.x_ptr.ptr[len_with_null - 1] = null_char;
2944
2945 return get_pointer_to_type(g, g->builtin_types.entry_u8, true);
2946}
2947
2948static TypeTableEntry *resolve_expr_const_val_as_string_lit(CodeGen *g, AstNode *node, Buf *str) {
2949 Expr *expr = get_resolved_expr(node);
2950 expr->const_val.ok = true;
2951 expr->const_val.data.x_array.fields = allocate<ConstExprValue*>(buf_len(str));
2952
2953 ConstExprValue *all_chars = allocate<ConstExprValue>(buf_len(str));
2954 for (size_t i = 0; i < buf_len(str); i += 1) {
2955 ConstExprValue *this_char = &all_chars[i];
2956 this_char->ok = true;
2957 bignum_init_unsigned(&this_char->data.x_bignum, buf_ptr(str)[i]);
2958 expr->const_val.data.x_array.fields[i] = this_char;
2959 }
2960 return get_array_type(g, g->builtin_types.entry_u8, buf_len(str));
2961}
2962
2963static TypeTableEntry *resolve_expr_const_val_as_bignum(CodeGen *g, AstNode *node,
2964 TypeTableEntry *expected_type, BigNum *bignum, bool depends_on_compile_var)
2965{
2966 Expr *expr = get_resolved_expr(node);
2967 expr->const_val.ok = true;
2968 expr->const_val.depends_on_compile_var = depends_on_compile_var;
2969
2970 bignum_init_bignum(&expr->const_val.data.x_bignum, bignum);
2971 if (bignum->kind == BigNumKindInt) {
2972 return g->builtin_types.entry_num_lit_int;
2973 } else if (bignum->kind == BigNumKindFloat) {
2974 return g->builtin_types.entry_num_lit_float;
2975 } else {
2976 zig_unreachable();
2977 }
2978}
2979
2980static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,
2981 TypeTableEntry *expected_type, uint64_t x, bool depends_on_compile_var)
2982{
2983 Expr *expr = get_resolved_expr(node);
2984 expr->const_val.ok = true;
2985 expr->const_val.depends_on_compile_var = depends_on_compile_var;
2986
2987 bignum_init_unsigned(&expr->const_val.data.x_bignum, x);
2988
2989 return g->builtin_types.entry_num_lit_int;
2990}
2991
2992static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
2993 BlockContext *context, AstNode *node, Buf *err_name)
2994{
2995 auto err_table_entry = g->error_table.maybe_get(err_name);
2996
2997 if (err_table_entry) {
2998 return resolve_expr_const_val_as_err(g, node, err_table_entry->value);
2999 }
3000
3001 add_node_error(g, node,
3002 buf_sprintf("use of undeclared error value '%s'", buf_ptr(err_name)));
3003
3004 return g->builtin_types.entry_invalid;
3005}
3006
3007static bool var_is_pure(VariableTableEntry *var, BlockContext *context) {
3008 if (var->block_context->fn_entry == context->fn_entry) {
3009 // variable was declared in the current function, so it's OK.
3010 return true;
3011 }
3012 return var->src_is_const && var->type->deep_const;
3013}
3014
3015static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, VariableTableEntry *var,
3016 BlockContext *context, bool depends_on_compile_var)
3017{
3018 get_resolved_expr(source_node)->variable = var;
3019 if (!var_is_pure(var, context)) {
3020 mark_impure_fn(g, context, source_node);
3021 }
3022 if (var->src_is_const && var->val_node) {
3023 ConstExprValue *other_const_val = &get_resolved_expr(var->val_node)->const_val;
3024 if (other_const_val->ok) {
3025 return resolve_expr_const_val_as_other_expr(g, source_node, var->val_node,
3026 depends_on_compile_var || var->force_depends_on_compile_var);
3027 }
3028 }
3029 return var->type;
3030}
3031
3032static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node,
3033 bool pointer_only, BlockContext *block_context, bool depends_on_compile_var)
3034{
3035 resolve_top_level_decl(g, decl_node, pointer_only);
3036 TopLevelDecl *tld = get_as_top_level_decl(decl_node);
3037 if (tld->resolution == TldResolutionInvalid) {
3038 return g->builtin_types.entry_invalid;
3039 }
3040
3041 if (decl_node->type == NodeTypeVariableDeclaration) {
3042 VariableTableEntry *var = decl_node->data.variable_declaration.variable;
3043 return analyze_var_ref(g, source_node, var, block_context, depends_on_compile_var);
3044 } else if (decl_node->type == NodeTypeFnProto) {
3045 FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry;
3046 assert(fn_entry->type_entry);
3047 if (fn_entry->type_entry->id == TypeTableEntryIdGenericFn) {
3048 return resolve_expr_const_val_as_generic_fn(g, source_node, fn_entry->type_entry, depends_on_compile_var);
3049 } else {
3050 return resolve_expr_const_val_as_fn(g, source_node, fn_entry, depends_on_compile_var);
3051 }
3052 } else if (decl_node->type == NodeTypeContainerDecl) {
3053 if (decl_node->data.struct_decl.generic_params.length > 0) {
3054 TypeTableEntry *type_entry = decl_node->data.struct_decl.generic_fn_type;
3055 assert(type_entry);
3056 return resolve_expr_const_val_as_generic_fn(g, source_node, type_entry, depends_on_compile_var);
3057 } else {
3058 return resolve_expr_const_val_as_type(g, source_node, decl_node->data.struct_decl.type_entry,
3059 depends_on_compile_var);
3060 }
3061 } else if (decl_node->type == NodeTypeTypeDecl) {
3062 return resolve_expr_const_val_as_type(g, source_node, decl_node->data.type_decl.child_type_entry,
3063 depends_on_compile_var);
3064 } else {
3065 zig_unreachable();
3066 }
3067}
3068
3069static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3070 TypeTableEntry *expected_type, AstNode *node, bool pointer_only)
3071{
3072 Buf *variable_name = node->data.symbol_expr.symbol;
3073
3074 auto primitive_table_entry = g->primitive_type_table.maybe_get(variable_name);
3075 if (primitive_table_entry) {
3076 return resolve_expr_const_val_as_type(g, node, primitive_table_entry->value, false);
3077 }
3078
3079 VariableTableEntry *var = find_variable(g, context, variable_name);
3080 if (var) {
3081 TypeTableEntry *var_type = analyze_var_ref(g, node, var, context, false);
3082 return var_type;
3083 }
3084
3085 AstNode *decl_node = find_decl(context, variable_name);
3086 if (decl_node) {
3087 return analyze_decl_ref(g, node, decl_node, pointer_only, context, false);
3088 }
3089
3090 if (import->any_imports_failed) {
3091 // skip the error message since we had a failing import in this file
3092 // if an import breaks we don't need 9999 undeclared identifier errors
3093 return g->builtin_types.entry_invalid;
3094 }
3095
3096 mark_impure_fn(g, context, node);
3097 add_node_error(g, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
3098 return g->builtin_types.entry_invalid;
3099}
3100
3101static bool is_op_allowed(TypeTableEntry *type, BinOpType op) {
3102 switch (op) {
3103 case BinOpTypeAssign:
3104 return true;
3105 case BinOpTypeAssignTimes:
3106 case BinOpTypeAssignTimesWrap:
3107 case BinOpTypeAssignDiv:
3108 case BinOpTypeAssignMod:
3109 return type->id == TypeTableEntryIdInt || type->id == TypeTableEntryIdFloat;
3110 case BinOpTypeAssignPlus:
3111 case BinOpTypeAssignPlusWrap:
3112 case BinOpTypeAssignMinus:
3113 case BinOpTypeAssignMinusWrap:
3114 return type->id == TypeTableEntryIdInt ||
3115 type->id == TypeTableEntryIdFloat ||
3116 type->id == TypeTableEntryIdPointer;
3117 case BinOpTypeAssignBitShiftLeft:
3118 case BinOpTypeAssignBitShiftLeftWrap:
3119 case BinOpTypeAssignBitShiftRight:
3120 case BinOpTypeAssignBitAnd:
3121 case BinOpTypeAssignBitXor:
3122 case BinOpTypeAssignBitOr:
3123 return type->id == TypeTableEntryIdInt;
3124 case BinOpTypeAssignBoolAnd:
3125 case BinOpTypeAssignBoolOr:
3126 return type->id == TypeTableEntryIdBool;
3127
3128 case BinOpTypeInvalid:
3129 case BinOpTypeBoolOr:
3130 case BinOpTypeBoolAnd:
3131 case BinOpTypeCmpEq:
3132 case BinOpTypeCmpNotEq:
3133 case BinOpTypeCmpLessThan:
3134 case BinOpTypeCmpGreaterThan:
3135 case BinOpTypeCmpLessOrEq:
3136 case BinOpTypeCmpGreaterOrEq:
3137 case BinOpTypeBinOr:
3138 case BinOpTypeBinXor:
3139 case BinOpTypeBinAnd:
3140 case BinOpTypeBitShiftLeft:
3141 case BinOpTypeBitShiftLeftWrap:
3142 case BinOpTypeBitShiftRight:
3143 case BinOpTypeAdd:
3144 case BinOpTypeAddWrap:
3145 case BinOpTypeSub:
3146 case BinOpTypeSubWrap:
3147 case BinOpTypeMult:
3148 case BinOpTypeMultWrap:
3149 case BinOpTypeDiv:
3150 case BinOpTypeMod:
3151 case BinOpTypeUnwrapMaybe:
3152 case BinOpTypeArrayCat:
3153 case BinOpTypeArrayMult:
3154 zig_unreachable();
3155 }
3156 zig_unreachable();
3157}
3158
3159static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, BlockContext *block_context,
3160 AstNode *lhs_node, LValPurpose purpose, bool is_ptr_const)
3161{
3162 TypeTableEntry *expected_rhs_type = nullptr;
3163 lhs_node->block_context = block_context;
3164 if (lhs_node->type == NodeTypeSymbol) {
3165 bool pointer_only = purpose == LValPurposeAddressOf;
3166 expected_rhs_type = analyze_symbol_expr(g, import, block_context, nullptr, lhs_node, pointer_only);
3167 if (expected_rhs_type->id == TypeTableEntryIdInvalid) {
3168 return g->builtin_types.entry_invalid;
3169 }
3170 if (purpose != LValPurposeAddressOf) {
3171 Buf *name = lhs_node->data.symbol_expr.symbol;
3172 VariableTableEntry *var = find_variable(g, block_context, name);
3173 if (var) {
3174 if (var->src_is_const) {
3175 add_node_error(g, lhs_node, buf_sprintf("cannot assign to constant"));
3176 expected_rhs_type = g->builtin_types.entry_invalid;
3177 } else {
3178 expected_rhs_type = var->type;
3179 get_resolved_expr(lhs_node)->variable = var;
3180 }
3181 } else {
3182 add_node_error(g, lhs_node,
3183 buf_sprintf("use of undeclared identifier '%s'", buf_ptr(name)));
3184 expected_rhs_type = g->builtin_types.entry_invalid;
3185 }
3186 }
3187 } else if (lhs_node->type == NodeTypeArrayAccessExpr) {
3188 expected_rhs_type = analyze_array_access_expr(g, import, block_context, lhs_node, purpose);
3189 } else if (lhs_node->type == NodeTypeFieldAccessExpr) {
3190 expected_rhs_type = analyze_field_access_expr(g, import, block_context, nullptr, lhs_node);
3191 } else if (lhs_node->type == NodeTypePrefixOpExpr &&
3192 lhs_node->data.prefix_op_expr.prefix_op == PrefixOpDereference)
3193 {
3194 assert(purpose == LValPurposeAssign);
3195 AstNode *target_node = lhs_node->data.prefix_op_expr.primary_expr;
3196 TypeTableEntry *type_entry = analyze_expression(g, import, block_context, nullptr, target_node);
3197 if (type_entry->id == TypeTableEntryIdInvalid) {
3198 expected_rhs_type = type_entry;
3199 } else if (type_entry->id == TypeTableEntryIdPointer) {
3200 expected_rhs_type = type_entry->data.pointer.child_type;
3201 } else {
3202 add_node_error(g, target_node,
3203 buf_sprintf("indirection requires pointer operand ('%s' invalid)",
3204 buf_ptr(&type_entry->name)));
3205 expected_rhs_type = g->builtin_types.entry_invalid;
3206 }
3207 } else {
3208 if (purpose == LValPurposeAssign) {
3209 add_node_error(g, lhs_node, buf_sprintf("invalid assignment target"));
3210 expected_rhs_type = g->builtin_types.entry_invalid;
3211 } else if (purpose == LValPurposeAddressOf) {
3212 TypeTableEntry *type_entry = analyze_expression(g, import, block_context, nullptr, lhs_node);
3213 if (type_entry->id == TypeTableEntryIdInvalid) {
3214 expected_rhs_type = g->builtin_types.entry_invalid;
3215 } else if (type_entry->id == TypeTableEntryIdMetaType) {
3216 expected_rhs_type = type_entry;
3217 } else {
3218 add_node_error(g, lhs_node, buf_sprintf("invalid addressof target"));
3219 expected_rhs_type = g->builtin_types.entry_invalid;
3220 }
3221 }
3222 }
3223 assert(expected_rhs_type);
3224 return expected_rhs_type;
3225}
3226
3227static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3228 AstNode *node)
3229{
3230 assert(node->type == NodeTypeBinOpExpr);
3231 BinOpType bin_op_type = node->data.bin_op_expr.bin_op;
3232
3233 AstNode **op1 = &node->data.bin_op_expr.op1;
3234 AstNode **op2 = &node->data.bin_op_expr.op2;
3235 TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1);
3236 TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2);
3237
3238 AstNode *op_nodes[] = {*op1, *op2};
3239 TypeTableEntry *op_types[] = {op1_type, op2_type};
3240
3241 TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, import, context, node,
3242 op_nodes, op_types, 2);
3243
3244 bool is_equality_cmp = (bin_op_type == BinOpTypeCmpEq || bin_op_type == BinOpTypeCmpNotEq);
3245
3246 switch (resolved_type->id) {
3247 case TypeTableEntryIdInvalid:
3248 return g->builtin_types.entry_invalid;
3249
3250 case TypeTableEntryIdNumLitFloat:
3251 case TypeTableEntryIdNumLitInt:
3252 case TypeTableEntryIdInt:
3253 case TypeTableEntryIdFloat:
3254 break;
3255
3256 case TypeTableEntryIdBool:
3257 case TypeTableEntryIdMetaType:
3258 case TypeTableEntryIdVoid:
3259 case TypeTableEntryIdPointer:
3260 case TypeTableEntryIdPureError:
3261 case TypeTableEntryIdFn:
3262 case TypeTableEntryIdTypeDecl:
3263 case TypeTableEntryIdNamespace:
3264 case TypeTableEntryIdBlock:
3265 case TypeTableEntryIdGenericFn:
3266 if (!is_equality_cmp) {
3267 add_node_error(g, node,
3268 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
3269 return g->builtin_types.entry_invalid;
3270 }
3271 break;
3272
3273 case TypeTableEntryIdEnum:
3274 if (!is_equality_cmp || resolved_type->data.enumeration.gen_field_count != 0) {
3275 add_node_error(g, node,
3276 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
3277 return g->builtin_types.entry_invalid;
3278 }
3279 break;
3280
3281 case TypeTableEntryIdUnreachable:
3282 case TypeTableEntryIdArray:
3283 case TypeTableEntryIdStruct:
3284 case TypeTableEntryIdUndefLit:
3285 case TypeTableEntryIdNullLit:
3286 case TypeTableEntryIdMaybe:
3287 case TypeTableEntryIdErrorUnion:
3288 case TypeTableEntryIdUnion:
3289 add_node_error(g, node,
3290 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
3291 return g->builtin_types.entry_invalid;
3292
3293 case TypeTableEntryIdVar:
3294 zig_unreachable();
3295 }
3296
3297 ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;
3298 ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;
3299 if (!op1_val->ok || !op2_val->ok) {
3300 return g->builtin_types.entry_bool;
3301 }
3302
3303
3304 ConstExprValue *out_val = &get_resolved_expr(node)->const_val;
3305 eval_const_expr_bin_op(op1_val, op1_type, bin_op_type, op2_val, op2_type, out_val);
3306 return g->builtin_types.entry_bool;
3307
3308}
3309
3310static TypeTableEntry *analyze_logic_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3311 AstNode *node)
3312{
3313 assert(node->type == NodeTypeBinOpExpr);
3314 BinOpType bin_op_type = node->data.bin_op_expr.bin_op;
3315
3316 AstNode *op1 = node->data.bin_op_expr.op1;
3317 AstNode *op2 = node->data.bin_op_expr.op2;
3318 TypeTableEntry *op1_type = analyze_expression(g, import, context, g->builtin_types.entry_bool, op1);
3319 TypeTableEntry *op2_type = analyze_expression(g, import, context, g->builtin_types.entry_bool, op2);
3320
3321 if (op1_type->id == TypeTableEntryIdInvalid ||
3322 op2_type->id == TypeTableEntryIdInvalid)
3323 {
3324 return g->builtin_types.entry_invalid;
3325 }
3326
3327 ConstExprValue *op1_val = &get_resolved_expr(op1)->const_val;
3328 ConstExprValue *op2_val = &get_resolved_expr(op2)->const_val;
3329 if (!op1_val->ok || !op2_val->ok) {
3330 return g->builtin_types.entry_bool;
3331 }
3332
3333 ConstExprValue *out_val = &get_resolved_expr(node)->const_val;
3334 eval_const_expr_bin_op(op1_val, op1_type, bin_op_type, op2_val, op2_type, out_val);
3335 return g->builtin_types.entry_bool;
3336}
3337
3338static TypeTableEntry *analyze_array_mult(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3339 TypeTableEntry *expected_type, AstNode *node)
3340{
3341 assert(node->type == NodeTypeBinOpExpr);
3342 assert(node->data.bin_op_expr.bin_op == BinOpTypeArrayMult);
3343
3344 AstNode **op1 = node->data.bin_op_expr.op1->parent_field;
3345 AstNode **op2 = node->data.bin_op_expr.op2->parent_field;
3346
3347 TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1);
3348 TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2);
3349
3350 if (op1_type->id == TypeTableEntryIdInvalid ||
3351 op2_type->id == TypeTableEntryIdInvalid)
3352 {
3353 return g->builtin_types.entry_invalid;
3354 }
3355
3356 ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;
3357 ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;
3358
3359 AstNode *bad_node;
3360 if (!op1_val->ok) {
3361 bad_node = *op1;
3362 } else if (!op2_val->ok) {
3363 bad_node = *op2;
3364 } else {
3365 bad_node = nullptr;
3366 }
3367 if (bad_node) {
3368 add_node_error(g, bad_node, buf_sprintf("array multiplication requires constant expression"));
3369 return g->builtin_types.entry_invalid;
3370 }
3371
3372 if (op1_type->id != TypeTableEntryIdArray) {
3373 add_node_error(g, *op1,
3374 buf_sprintf("expected array type, got '%s'", buf_ptr(&op1_type->name)));
3375 return g->builtin_types.entry_invalid;
3376 }
3377
3378 if (op2_type->id != TypeTableEntryIdNumLitInt &&
3379 op2_type->id != TypeTableEntryIdInt)
3380 {
3381 add_node_error(g, *op2, buf_sprintf("expected integer type, got '%s'", buf_ptr(&op2_type->name)));
3382 return g->builtin_types.entry_invalid;
3383 }
3384
3385 if (op2_val->data.x_bignum.is_negative) {
3386 add_node_error(g, *op2, buf_sprintf("expected positive number"));
3387 return g->builtin_types.entry_invalid;
3388 }
3389
3390 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
3391 const_val->ok = true;
3392 const_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
3393
3394 TypeTableEntry *child_type = op1_type->data.array.child_type;
3395 BigNum old_array_len;
3396 bignum_init_unsigned(&old_array_len, op1_type->data.array.len);
3397
3398 BigNum new_array_len;
3399 if (bignum_mul(&new_array_len, &old_array_len, &op2_val->data.x_bignum)) {
3400 add_node_error(g, node, buf_sprintf("operation results in overflow"));
3401 return g->builtin_types.entry_invalid;
3402 }
3403
3404 uint64_t old_array_len_bare = op1_type->data.array.len;
3405 uint64_t operand_amt = op2_val->data.x_bignum.data.x_uint;
3406
3407 uint64_t new_array_len_bare = new_array_len.data.x_uint;
3408 const_val->data.x_array.fields = allocate<ConstExprValue*>(new_array_len_bare);
3409
3410 uint64_t i = 0;
3411 for (uint64_t x = 0; x < operand_amt; x += 1) {
3412 for (uint64_t y = 0; y < old_array_len_bare; y += 1) {
3413 const_val->data.x_array.fields[i] = op1_val->data.x_array.fields[y];
3414 i += 1;
3415 }
3416 }
3417
3418 return get_array_type(g, child_type, new_array_len_bare);
3419}
3420
3421static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3422 TypeTableEntry *expected_type, AstNode *node)
3423{
3424 assert(node->type == NodeTypeBinOpExpr);
3425 BinOpType bin_op_type = node->data.bin_op_expr.bin_op;
3426 switch (bin_op_type) {
3427 case BinOpTypeAssign:
3428 case BinOpTypeAssignTimes:
3429 case BinOpTypeAssignTimesWrap:
3430 case BinOpTypeAssignDiv:
3431 case BinOpTypeAssignMod:
3432 case BinOpTypeAssignPlus:
3433 case BinOpTypeAssignPlusWrap:
3434 case BinOpTypeAssignMinus:
3435 case BinOpTypeAssignMinusWrap:
3436 case BinOpTypeAssignBitShiftLeft:
3437 case BinOpTypeAssignBitShiftLeftWrap:
3438 case BinOpTypeAssignBitShiftRight:
3439 case BinOpTypeAssignBitAnd:
3440 case BinOpTypeAssignBitXor:
3441 case BinOpTypeAssignBitOr:
3442 case BinOpTypeAssignBoolAnd:
3443 case BinOpTypeAssignBoolOr:
3444 {
3445 AstNode *lhs_node = node->data.bin_op_expr.op1;
3446
3447 TypeTableEntry *expected_rhs_type = analyze_lvalue(g, import, context, lhs_node,
3448 LValPurposeAssign, false);
3449 if (expected_rhs_type->id == TypeTableEntryIdInvalid) {
3450 return g->builtin_types.entry_invalid;
3451 } else if (!is_op_allowed(expected_rhs_type, node->data.bin_op_expr.bin_op)) {
3452 if (expected_rhs_type->id != TypeTableEntryIdInvalid) {
3453 add_node_error(g, lhs_node,
3454 buf_sprintf("operator not allowed for type '%s'",
3455 buf_ptr(&expected_rhs_type->name)));
3456 }
3457 }
3458
3459 analyze_expression(g, import, context, expected_rhs_type, node->data.bin_op_expr.op2);
3460 // not const ok because expression has side effects
3461 return g->builtin_types.entry_void;
3462 }
3463 case BinOpTypeBoolOr:
3464 case BinOpTypeBoolAnd:
3465 return analyze_logic_bin_op_expr(g, import, context, node);
3466 case BinOpTypeCmpEq:
3467 case BinOpTypeCmpNotEq:
3468 case BinOpTypeCmpLessThan:
3469 case BinOpTypeCmpGreaterThan:
3470 case BinOpTypeCmpLessOrEq:
3471 case BinOpTypeCmpGreaterOrEq:
3472 return analyze_bool_bin_op_expr(g, import, context, node);
3473 case BinOpTypeBinOr:
3474 case BinOpTypeBinXor:
3475 case BinOpTypeBinAnd:
3476 case BinOpTypeBitShiftLeft:
3477 case BinOpTypeBitShiftLeftWrap:
3478 case BinOpTypeBitShiftRight:
3479 case BinOpTypeAdd:
3480 case BinOpTypeAddWrap:
3481 case BinOpTypeSub:
3482 case BinOpTypeSubWrap:
3483 case BinOpTypeMult:
3484 case BinOpTypeMultWrap:
3485 case BinOpTypeDiv:
3486 case BinOpTypeMod:
3487 {
3488 AstNode **op1 = node->data.bin_op_expr.op1->parent_field;
3489 AstNode **op2 = node->data.bin_op_expr.op2->parent_field;
3490 TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, *op1);
3491 TypeTableEntry *rhs_type = analyze_expression(g, import, context, nullptr, *op2);
3492
3493 AstNode *op_nodes[] = {*op1, *op2};
3494 TypeTableEntry *op_types[] = {lhs_type, rhs_type};
3495
3496 TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, import, context, node,
3497 op_nodes, op_types, 2);
3498
3499 if (resolved_type->id == TypeTableEntryIdInvalid) {
3500 return resolved_type;
3501 }
3502
3503 if (resolved_type->id == TypeTableEntryIdInt ||
3504 resolved_type->id == TypeTableEntryIdNumLitInt)
3505 {
3506 // int
3507 } else if ((resolved_type->id == TypeTableEntryIdFloat ||
3508 resolved_type->id == TypeTableEntryIdNumLitFloat) &&
3509 (bin_op_type == BinOpTypeAdd ||
3510 bin_op_type == BinOpTypeSub ||
3511 bin_op_type == BinOpTypeMult ||
3512 bin_op_type == BinOpTypeDiv ||
3513 bin_op_type == BinOpTypeMod))
3514 {
3515 // float
3516 } else {
3517 add_node_error(g, node, buf_sprintf("invalid operands to binary expression: '%s' and '%s'",
3518 buf_ptr(&lhs_type->name), buf_ptr(&rhs_type->name)));
3519 return g->builtin_types.entry_invalid;
3520 }
3521
3522 ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;
3523 ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;
3524 if (!op1_val->ok || !op2_val->ok) {
3525 return resolved_type;
3526 }
3527
3528 ConstExprValue *out_val = &get_resolved_expr(node)->const_val;
3529 int err;
3530 if ((err = eval_const_expr_bin_op(op1_val, resolved_type, bin_op_type,
3531 op2_val, resolved_type, out_val)))
3532 {
3533 if (err == ErrorDivByZero) {
3534 add_node_error(g, node, buf_sprintf("division by zero is undefined"));
3535 return g->builtin_types.entry_invalid;
3536 } else if (err == ErrorOverflow) {
3537 add_node_error(g, node, buf_sprintf("value cannot be represented in any integer type"));
3538 return g->builtin_types.entry_invalid;
3539 }
3540 return g->builtin_types.entry_invalid;
3541 }
3542
3543 num_lit_fits_in_other_type(g, node, resolved_type);
3544 return resolved_type;
3545 }
3546 case BinOpTypeUnwrapMaybe:
3547 {
3548 AstNode *op1 = node->data.bin_op_expr.op1;
3549 AstNode *op2 = node->data.bin_op_expr.op2;
3550 TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, op1);
3551
3552 if (lhs_type->id == TypeTableEntryIdInvalid) {
3553 return lhs_type;
3554 } else if (lhs_type->id == TypeTableEntryIdMaybe) {
3555 TypeTableEntry *child_type = lhs_type->data.maybe.child_type;
3556 analyze_expression(g, import, context, child_type, op2);
3557 return child_type;
3558 } else {
3559 add_node_error(g, op1,
3560 buf_sprintf("expected maybe type, got '%s'",
3561 buf_ptr(&lhs_type->name)));
3562 return g->builtin_types.entry_invalid;
3563 }
3564 }
3565 case BinOpTypeArrayCat:
3566 {
3567 AstNode **op1 = node->data.bin_op_expr.op1->parent_field;
3568 AstNode **op2 = node->data.bin_op_expr.op2->parent_field;
3569
3570 TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1);
3571 TypeTableEntry *child_type;
3572 if (op1_type->id == TypeTableEntryIdInvalid) {
3573 return g->builtin_types.entry_invalid;
3574 } else if (op1_type->id == TypeTableEntryIdArray) {
3575 child_type = op1_type->data.array.child_type;
3576 } else if (op1_type->id == TypeTableEntryIdPointer &&
3577 op1_type->data.pointer.child_type == g->builtin_types.entry_u8) {
3578 child_type = op1_type->data.pointer.child_type;
3579 } else {
3580 add_node_error(g, *op1, buf_sprintf("expected array or C string literal, got '%s'",
3581 buf_ptr(&op1_type->name)));
3582 return g->builtin_types.entry_invalid;
3583 }
3584
3585 TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2);
3586
3587 if (op2_type->id == TypeTableEntryIdInvalid) {
3588 return g->builtin_types.entry_invalid;
3589 } else if (op2_type->id == TypeTableEntryIdArray) {
3590 if (op2_type->data.array.child_type != child_type) {
3591 add_node_error(g, *op2, buf_sprintf("expected array of type '%s', got '%s'",
3592 buf_ptr(&child_type->name),
3593 buf_ptr(&op2_type->name)));
3594 return g->builtin_types.entry_invalid;
3595 }
3596 } else if (op2_type->id == TypeTableEntryIdPointer &&
3597 op2_type->data.pointer.child_type == g->builtin_types.entry_u8) {
3598 } else {
3599 add_node_error(g, *op2, buf_sprintf("expected array or C string literal, got '%s'",
3600 buf_ptr(&op2_type->name)));
3601 return g->builtin_types.entry_invalid;
3602 }
3603
3604 ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;
3605 ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;
3606
3607 AstNode *bad_node;
3608 if (!op1_val->ok) {
3609 bad_node = *op1;
3610 } else if (!op2_val->ok) {
3611 bad_node = *op2;
3612 } else {
3613 bad_node = nullptr;
3614 }
3615 if (bad_node) {
3616 add_node_error(g, bad_node, buf_sprintf("array concatenation requires constant expression"));
3617 return g->builtin_types.entry_invalid;
3618 }
3619
3620 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
3621 const_val->ok = true;
3622 const_val->depends_on_compile_var = op1_val->depends_on_compile_var ||
3623 op2_val->depends_on_compile_var;
3624
3625 if (op1_type->id == TypeTableEntryIdArray) {
3626 uint64_t new_len = op1_type->data.array.len + op2_type->data.array.len;
3627 const_val->data.x_array.fields = allocate<ConstExprValue*>(new_len);
3628 uint64_t next_index = 0;
3629 for (uint64_t i = 0; i < op1_type->data.array.len; i += 1, next_index += 1) {
3630 const_val->data.x_array.fields[next_index] = op1_val->data.x_array.fields[i];
3631 }
3632 for (uint64_t i = 0; i < op2_type->data.array.len; i += 1, next_index += 1) {
3633 const_val->data.x_array.fields[next_index] = op2_val->data.x_array.fields[i];
3634 }
3635 return get_array_type(g, child_type, new_len);
3636 } else if (op1_type->id == TypeTableEntryIdPointer) {
3637 if (!op1_val->data.x_ptr.is_c_str) {
3638 add_node_error(g, *op1,
3639 buf_sprintf("expected array or C string literal, got '%s'",
3640 buf_ptr(&op1_type->name)));
3641 return g->builtin_types.entry_invalid;
3642 } else if (!op2_val->data.x_ptr.is_c_str) {
3643 add_node_error(g, *op2,
3644 buf_sprintf("expected array or C string literal, got '%s'",
3645 buf_ptr(&op2_type->name)));
3646 return g->builtin_types.entry_invalid;
3647 }
3648 const_val->data.x_ptr.is_c_str = true;
3649 const_val->data.x_ptr.len = op1_val->data.x_ptr.len + op2_val->data.x_ptr.len - 1;
3650 const_val->data.x_ptr.ptr = allocate<ConstExprValue*>(const_val->data.x_ptr.len);
3651 uint64_t next_index = 0;
3652 for (uint64_t i = 0; i < op1_val->data.x_ptr.len - 1; i += 1, next_index += 1) {
3653 const_val->data.x_ptr.ptr[next_index] = op1_val->data.x_ptr.ptr[i];
3654 }
3655 for (uint64_t i = 0; i < op2_val->data.x_ptr.len; i += 1, next_index += 1) {
3656 const_val->data.x_ptr.ptr[next_index] = op2_val->data.x_ptr.ptr[i];
3657 }
3658 return op1_type;
3659 } else {
3660 zig_unreachable();
3661 }
3662 }
3663 case BinOpTypeArrayMult:
3664 return analyze_array_mult(g, import, context, expected_type, node);
3665 case BinOpTypeInvalid:
3666 zig_unreachable();
3667 }
3668 zig_unreachable();
3669}
3670
3671// Set name to nullptr to make the variable anonymous (not visible to programmer).
3672// TODO merge with definition of add_local_var in ir.cpp
3673static VariableTableEntry *add_local_var_shadowable(CodeGen *g, AstNode *source_node, ImportTableEntry *import,
3674 BlockContext *context, Buf *name, TypeTableEntry *type_entry, bool is_const, AstNode *val_node,
3675 bool shadowable)
3676{
3677 VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1);
3678 variable_entry->type = type_entry;
3679 variable_entry->block_context = context;
3680 variable_entry->import = import;
3681 variable_entry->shadowable = shadowable;
3682 variable_entry->mem_slot_index = SIZE_MAX;
3683
3684 if (name) {
3685 buf_init_from_buf(&variable_entry->name, name);
3686
3687 if (type_entry->id != TypeTableEntryIdInvalid) {
3688 VariableTableEntry *existing_var = find_variable(g, context, name);
3689 if (existing_var && !existing_var->shadowable) {
3690 ErrorMsg *msg = add_node_error(g, source_node,
3691 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
3692 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
3693 variable_entry->type = g->builtin_types.entry_invalid;
3694 } else {
3695 auto primitive_table_entry = g->primitive_type_table.maybe_get(name);
3696 if (primitive_table_entry) {
3697 TypeTableEntry *type = primitive_table_entry->value;
3698 add_node_error(g, source_node,
3699 buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));
3700 variable_entry->type = g->builtin_types.entry_invalid;
3701 } else {
3702 AstNode *decl_node = find_decl(context, name);
3703 if (decl_node && decl_node->type != NodeTypeVariableDeclaration) {
3704 ErrorMsg *msg = add_node_error(g, source_node,
3705 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
3706 add_error_note(g, msg, decl_node, buf_sprintf("previous definition is here"));
3707 variable_entry->type = g->builtin_types.entry_invalid;
3708 }
3709 }
3710 }
3711 }
3712
3713 context->var_table.put(&variable_entry->name, variable_entry);
3714 } else {
3715 // TODO replace _anon with @anon and make sure all tests still pass
3716 buf_init_from_str(&variable_entry->name, "_anon");
3717 }
3718 if (context->fn_entry) {
3719 context->fn_entry->variable_list.append(variable_entry);
3720 }
3721
3722 variable_entry->src_is_const = is_const;
3723 variable_entry->gen_is_const = is_const;
3724 variable_entry->decl_node = source_node;
3725 variable_entry->val_node = val_node;
3726
3727
3728 return variable_entry;
3729}
3730
3731static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, ImportTableEntry *import,
3732 BlockContext *context, Buf *name, TypeTableEntry *type_entry, bool is_const, AstNode *val_node)
3733{
3734 return add_local_var_shadowable(g, source_node, import, context, name, type_entry, is_const, val_node, false);
3735}
3736
3737static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *import,
3738 BlockContext *parent_context, TypeTableEntry *expected_type, AstNode *node)
3739{
3740 AstNode *op1 = node->data.unwrap_err_expr.op1;
3741 AstNode *op2 = node->data.unwrap_err_expr.op2;
3742 AstNode *var_node = node->data.unwrap_err_expr.symbol;
3743
3744 TypeTableEntry *lhs_type = analyze_expression(g, import, parent_context, nullptr, op1);
3745 if (lhs_type->id == TypeTableEntryIdInvalid) {
3746 return lhs_type;
3747 } else if (lhs_type->id == TypeTableEntryIdErrorUnion) {
3748 TypeTableEntry *child_type = lhs_type->data.error.child_type;
3749 BlockContext *child_context;
3750 if (var_node) {
3751 child_context = new_block_context(node, parent_context);
3752 var_node->block_context = child_context;
3753 Buf *var_name = var_node->data.symbol_expr.symbol;
3754 node->data.unwrap_err_expr.var = add_local_var(g, var_node, import, child_context, var_name,
3755 g->builtin_types.entry_pure_error, true, nullptr);
3756 } else {
3757 child_context = parent_context;
3758 }
3759
3760 analyze_expression(g, import, child_context, child_type, op2);
3761 return child_type;
3762 } else {
3763 add_node_error(g, op1,
3764 buf_sprintf("expected error type, got '%s'", buf_ptr(&lhs_type->name)));
3765 return g->builtin_types.entry_invalid;
3766 }
3767}
3768
3769
3770static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,
3771 BlockContext *context, AstNode *source_node,
3772 AstNodeVariableDeclaration *variable_declaration,
3773 bool expr_is_maybe, AstNode *decl_node, bool var_is_ptr)
3774{
3775 bool is_const = variable_declaration->is_const;
3776 bool is_export = (variable_declaration->top_level_decl.visib_mod == VisibModExport);
3777 bool is_extern = variable_declaration->is_extern;
3778
3779 TypeTableEntry *explicit_type = nullptr;
3780 if (variable_declaration->type != nullptr) {
3781 explicit_type = analyze_type_expr(g, import, context, variable_declaration->type);
3782 if (explicit_type->id == TypeTableEntryIdUnreachable) {
3783 add_node_error(g, variable_declaration->type,
3784 buf_sprintf("variable of type 'unreachable' not allowed"));
3785 explicit_type = g->builtin_types.entry_invalid;
3786 }
3787 }
3788
3789 TypeTableEntry *implicit_type = nullptr;
3790 if (explicit_type && explicit_type->id == TypeTableEntryIdInvalid) {
3791 implicit_type = explicit_type;
3792 } else if (variable_declaration->expr) {
3793 implicit_type = analyze_expression(g, import, context, explicit_type, variable_declaration->expr);
3794 if (implicit_type->id == TypeTableEntryIdInvalid) {
3795 // ignore the poison value
3796 } else if (expr_is_maybe) {
3797 if (implicit_type->id == TypeTableEntryIdMaybe) {
3798 if (var_is_ptr) {
3799 // TODO if the expression is constant, can't get pointer to it
3800 implicit_type = get_pointer_to_type(g, implicit_type->data.maybe.child_type, false);
3801 } else {
3802 implicit_type = implicit_type->data.maybe.child_type;
3803 }
3804 } else {
3805 add_node_error(g, variable_declaration->expr, buf_sprintf("expected maybe type"));
3806 implicit_type = g->builtin_types.entry_invalid;
3807 }
3808 } else if (implicit_type->id == TypeTableEntryIdUnreachable) {
3809 add_node_error(g, source_node,
3810 buf_sprintf("variable initialization is unreachable"));
3811 implicit_type = g->builtin_types.entry_invalid;
3812 } else if ((!is_const || is_export) &&
3813 (implicit_type->id == TypeTableEntryIdNumLitFloat ||
3814 implicit_type->id == TypeTableEntryIdNumLitInt))
3815 {
3816 add_node_error(g, source_node, buf_sprintf("unable to infer variable type"));
3817 implicit_type = g->builtin_types.entry_invalid;
3818 } else if (implicit_type->id == TypeTableEntryIdMetaType && !is_const) {
3819 add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));
3820 implicit_type = g->builtin_types.entry_invalid;
3821 }
3822 if (implicit_type->id != TypeTableEntryIdInvalid && !context->fn_entry) {
3823 ConstExprValue *const_val = &get_resolved_expr(variable_declaration->expr)->const_val;
3824 if (!const_val->ok) {
3825 add_node_error(g, first_executing_node(variable_declaration->expr),
3826 buf_sprintf("global variable initializer requires constant expression"));
3827 }
3828 }
3829 } else if (!is_extern) {
3830 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
3831 implicit_type = g->builtin_types.entry_invalid;
3832 }
3833
3834 TypeTableEntry *type = explicit_type != nullptr ? explicit_type : implicit_type;
3835 assert(type != nullptr); // should have been caught by the parser
3836
3837 VariableTableEntry *var = add_local_var(g, source_node, import, context,
3838 variable_declaration->symbol, type, is_const,
3839 expr_is_maybe ? nullptr : variable_declaration->expr);
3840
3841 variable_declaration->variable = var;
3842
3843 return var;
3844}
3845
3846static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,
3847 BlockContext *context, TypeTableEntry *expected_type, AstNode *node)
3848{
3849 AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration;
3850 return analyze_variable_declaration_raw(g, import, context, node, variable_declaration,
3851 false, nullptr, false);
3852}
3853
3854static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *import,
3855 BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node)
3856{
3857 assert(node->type == NodeTypeNullLiteral);
3858
3859 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
3860 const_val->ok = true;
3861
3862 return g->builtin_types.entry_null;
3863}
3864
3865static TypeTableEntry *analyze_undefined_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3866 TypeTableEntry *expected_type, AstNode *node)
3867{
3868 assert(node->type == NodeTypeUndefinedLiteral);
3869
3870 Expr *expr = get_resolved_expr(node);
3871 ConstExprValue *const_val = &expr->const_val;
3872
3873 const_val->ok = true;
3874 const_val->special = ConstValSpecialUndef;
3875
3876 return expected_type ? expected_type : g->builtin_types.entry_undef;
3877}
3878
3879static TypeTableEntry *analyze_zeroes_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3880 TypeTableEntry *expected_type, AstNode *node)
3881{
3882 Expr *expr = get_resolved_expr(node);
3883 ConstExprValue *const_val = &expr->const_val;
3884
3885 const_val->ok = true;
3886 const_val->special = ConstValSpecialZeroes;
3887
3888 return expected_type ? expected_type : g->builtin_types.entry_undef;
3889}
3890
3891static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import,
3892 BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node)
3893{
3894 return resolve_expr_const_val_as_bignum(g, node, expected_type, node->data.number_literal.bignum, false);
3895}
3896
3897static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3898 TypeTableEntry *expected_type, AstNode *node)
3899{
3900 AstNode *size_node = node->data.array_type.size;
3901
3902 TypeTableEntry *child_type = analyze_type_expr_pointer_only(g, import, context,
3903 node->data.array_type.child_type, true);
3904
3905 if (child_type->id == TypeTableEntryIdUnreachable) {
3906 add_node_error(g, node, buf_create_from_str("array of unreachable not allowed"));
3907 return g->builtin_types.entry_invalid;
3908 } else if (child_type->id == TypeTableEntryIdInvalid) {
3909 return g->builtin_types.entry_invalid;
3910 }
3911
3912 if (size_node) {
3913 child_type = analyze_type_expr(g, import, context, node->data.array_type.child_type);
3914 TypeTableEntry *size_type = analyze_expression(g, import, context,
3915 g->builtin_types.entry_usize, size_node);
3916 if (size_type->id == TypeTableEntryIdInvalid) {
3917 return g->builtin_types.entry_invalid;
3918 }
3919
3920 ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
3921 if (const_val->ok) {
3922 if (const_val->data.x_bignum.is_negative) {
3923 add_node_error(g, size_node,
3924 buf_sprintf("array size %s is negative",
3925 buf_ptr(bignum_to_buf(&const_val->data.x_bignum))));
3926 return g->builtin_types.entry_invalid;
3927 } else {
3928 return resolve_expr_const_val_as_type(g, node,
3929 get_array_type(g, child_type, const_val->data.x_bignum.data.x_uint), false);
3930 }
3931 } else if (context->fn_entry) {
3932 return resolve_expr_const_val_as_type(g, node,
3933 get_slice_type(g, child_type, node->data.array_type.is_const), false);
3934 } else {
3935 add_node_error(g, first_executing_node(size_node),
3936 buf_sprintf("unable to evaluate constant expression"));
3937 return g->builtin_types.entry_invalid;
3938 }
3939 } else {
3940 TypeTableEntry *slice_type = get_slice_type(g, child_type, node->data.array_type.is_const);
3941 return resolve_expr_const_val_as_type(g, node, slice_type, false);
3942 }
3943}
3944
3945static TypeTableEntry *analyze_fn_proto_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3946 TypeTableEntry *expected_type, AstNode *node)
3947{
3948 TypeTableEntry *type_entry = analyze_fn_proto_type(g, import, context, expected_type, node,
3949 false, false, nullptr);
3950
3951 if (type_entry->id == TypeTableEntryIdInvalid) {
3952 return type_entry;
3953 }
3954
3955 return resolve_expr_const_val_as_type(g, node, type_entry, false);
3956}
3957
3958static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3959 TypeTableEntry *expected_type, AstNode *node)
3960{
3961 assert(node->type == NodeTypeWhileExpr);
3962
3963 AstNode **condition_node = &node->data.while_expr.condition;
3964 AstNode *while_body_node = node->data.while_expr.body;
3965 AstNode **continue_expr_node = &node->data.while_expr.continue_expr;
3966
3967 TypeTableEntry *condition_type = analyze_expression(g, import, context,
3968 g->builtin_types.entry_bool, *condition_node);
3969
3970 if (*continue_expr_node) {
3971 analyze_expression(g, import, context, g->builtin_types.entry_void, *continue_expr_node);
3972 }
3973
3974 BlockContext *child_context = new_block_context(node, context);
3975 child_context->parent_loop_node = node;
3976
3977 analyze_expression(g, import, child_context, g->builtin_types.entry_void, while_body_node);
3978
3979
3980 TypeTableEntry *expr_return_type = g->builtin_types.entry_void;
3981
3982 if (condition_type->id == TypeTableEntryIdInvalid) {
3983 expr_return_type = g->builtin_types.entry_invalid;
3984 } else {
3985 // if the condition is a simple constant expression and there are no break statements
3986 // then the return type is unreachable
3987 ConstExprValue *const_val = &get_resolved_expr(*condition_node)->const_val;
3988 if (const_val->ok) {
3989 if (const_val->data.x_bool) {
3990 node->data.while_expr.condition_always_true = true;
3991 if (!node->data.while_expr.contains_break) {
3992 expr_return_type = g->builtin_types.entry_unreachable;
3993 }
3994 }
3995 }
3996 }
3997
3998 return expr_return_type;
3999}
4000
4001static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4002 TypeTableEntry *expected_type, AstNode *node)
4003{
4004 assert(node->type == NodeTypeBreak);
4005
4006 AstNode *loop_node = context->parent_loop_node;
4007 if (loop_node) {
4008 if (loop_node->type == NodeTypeWhileExpr) {
4009 loop_node->data.while_expr.contains_break = true;
4010 } else if (loop_node->type == NodeTypeForExpr) {
4011 loop_node->data.for_expr.contains_break = true;
4012 } else {
4013 zig_unreachable();
4014 }
4015 } else {
4016 add_node_error(g, node, buf_sprintf("'break' expression outside loop"));
4017 }
4018 return g->builtin_types.entry_unreachable;
4019}
4020
4021static TypeTableEntry *analyze_continue_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4022 TypeTableEntry *expected_type, AstNode *node)
4023{
4024 AstNode *loop_node = context->parent_loop_node;
4025 if (loop_node) {
4026 if (loop_node->type == NodeTypeWhileExpr) {
4027 loop_node->data.while_expr.contains_continue = true;
4028 } else if (loop_node->type == NodeTypeForExpr) {
4029 loop_node->data.for_expr.contains_continue = true;
4030 } else {
4031 zig_unreachable();
4032 }
4033 } else {
4034 add_node_error(g, node, buf_sprintf("'continue' expression outside loop"));
4035 }
4036 return g->builtin_types.entry_unreachable;
4037}
4038
4039static TypeTableEntry *add_error_if_type_is_num_lit(CodeGen *g, TypeTableEntry *type_entry, AstNode *source_node) {
4040 if (type_entry->id == TypeTableEntryIdNumLitInt ||
4041 type_entry->id == TypeTableEntryIdNumLitFloat)
4042 {
4043 add_node_error(g, source_node, buf_sprintf("unable to infer expression type"));
4044 return g->builtin_types.entry_invalid;
4045 } else {
4046 return type_entry;
4047 }
4048}
4049
4050static TypeTableEntry *analyze_if(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context,
4051 TypeTableEntry *expected_type, AstNode *node,
4052 AstNode **then_node, AstNode **else_node, bool cond_is_const, bool cond_bool_val)
4053{
4054 if (!*else_node) {
4055 *else_node = create_ast_void_node(g, import, node);
4056 normalize_parent_ptrs(node);
4057 }
4058
4059 BlockContext *then_context;
4060 BlockContext *else_context;
4061 if (cond_is_const) {
4062 if (cond_bool_val) {
4063 then_context = parent_context;
4064 else_context = new_block_context(node, parent_context);
4065
4066 else_context->codegen_excluded = true;
4067 } else {
4068 then_context = new_block_context(node, parent_context);
4069 else_context = parent_context;
4070
4071 then_context->codegen_excluded = true;
4072 }
4073 } else {
4074 then_context = parent_context;
4075 else_context = parent_context;
4076 }
4077
4078 TypeTableEntry *then_type = nullptr;
4079 TypeTableEntry *else_type = nullptr;
4080
4081 if (!then_context->codegen_excluded) {
4082 then_type = analyze_expression(g, import, then_context, expected_type, *then_node);
4083 if (then_type->id == TypeTableEntryIdInvalid) {
4084 return g->builtin_types.entry_invalid;
4085 }
4086 }
4087 if (!else_context->codegen_excluded) {
4088 else_type = analyze_expression(g, import, else_context, expected_type, *else_node);
4089 if (else_type->id == TypeTableEntryIdInvalid) {
4090 return g->builtin_types.entry_invalid;
4091 }
4092 }
4093
4094 TypeTableEntry *result_type;
4095 if (then_context->codegen_excluded) {
4096 result_type = else_type;
4097 } else if (else_context->codegen_excluded) {
4098 result_type = then_type;
4099 } else if (expected_type) {
4100 result_type = (then_type->id == TypeTableEntryIdUnreachable) ? else_type : then_type;
4101 } else {
4102 AstNode *op_nodes[] = {*then_node, *else_node};
4103 TypeTableEntry *op_types[] = {then_type, else_type};
4104 result_type = resolve_peer_type_compatibility(g, import, parent_context, node, op_nodes, op_types, 2);
4105 }
4106
4107 if (!cond_is_const) {
4108 return add_error_if_type_is_num_lit(g, result_type, node);
4109 }
4110
4111 ConstExprValue *other_const_val;
4112 if (cond_bool_val) {
4113 other_const_val = &get_resolved_expr(*then_node)->const_val;
4114 } else {
4115 other_const_val = &get_resolved_expr(*else_node)->const_val;
4116 }
4117 if (!other_const_val->ok) {
4118 return add_error_if_type_is_num_lit(g, result_type, node);
4119 }
4120
4121 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
4122 *const_val = *other_const_val;
4123 // the condition depends on a compile var, so the entire if statement does too
4124 const_val->depends_on_compile_var = true;
4125 return result_type;
4126}
4127
4128static TypeTableEntry *analyze_if_bool_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4129 TypeTableEntry *expected_type, AstNode *node)
4130{
4131 AstNode **cond = &node->data.if_bool_expr.condition;
4132 TypeTableEntry *cond_type = analyze_expression(g, import, context, g->builtin_types.entry_bool, *cond);
4133
4134 if (cond_type->id == TypeTableEntryIdInvalid) {
4135 return cond_type;
4136 }
4137
4138 ConstExprValue *cond_val = &get_resolved_expr(*cond)->const_val;
4139 if (cond_val->special == ConstValSpecialUndef) {
4140 add_node_error(g, first_executing_node(*cond), buf_sprintf("branch on undefined value"));
4141 return cond_type;
4142 }
4143 if (cond_val->ok && !cond_val->depends_on_compile_var) {
4144 const char *str_val = cond_val->data.x_bool ? "true" : "false";
4145 add_node_error(g, first_executing_node(*cond),
4146 buf_sprintf("condition is always %s; unnecessary if statement", str_val));
4147 }
4148
4149 bool cond_is_const = cond_val->ok;
4150 bool cond_bool_val = cond_val->data.x_bool;
4151
4152 AstNode **then_node = &node->data.if_bool_expr.then_block;
4153 AstNode **else_node = &node->data.if_bool_expr.else_node;
4154
4155 return analyze_if(g, import, context, expected_type, node,
4156 then_node, else_node, cond_is_const, cond_bool_val);
4157}
4158
4159static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context,
4160 TypeTableEntry *expected_type, AstNode *node)
4161{
4162 assert(node->type == NodeTypeIfVarExpr);
4163
4164 BlockContext *child_context = new_block_context(node, parent_context);
4165
4166 analyze_variable_declaration_raw(g, import, child_context, node, &node->data.if_var_expr.var_decl, true,
4167 nullptr, node->data.if_var_expr.var_is_ptr);
4168 VariableTableEntry *var = node->data.if_var_expr.var_decl.variable;
4169 if (var->type->id == TypeTableEntryIdInvalid) {
4170 return g->builtin_types.entry_invalid;
4171 }
4172 AstNode *var_expr_node = node->data.if_var_expr.var_decl.expr;
4173 ConstExprValue *var_const_val = &get_resolved_expr(var_expr_node)->const_val;
4174 bool cond_is_const = var_const_val->ok;
4175 bool cond_bool_val = cond_is_const ? (var_const_val->data.x_maybe != nullptr) : false;
4176
4177
4178 AstNode **then_node = &node->data.if_var_expr.then_block;
4179 AstNode **else_node = &node->data.if_var_expr.else_node;
4180
4181 return analyze_if(g, import, child_context, expected_type,
4182 node, then_node, else_node, cond_is_const, cond_bool_val);
4183}
4184
4185bool type_is_codegen_pointer(TypeTableEntry *type) {
4186 if (type->id == TypeTableEntryIdPointer) return true;
4187 if (type->id == TypeTableEntryIdFn) return true;
4188 if (type->id == TypeTableEntryIdMaybe) {
4189 if (type->data.maybe.child_type->id == TypeTableEntryIdPointer) return true;
4190 if (type->data.maybe.child_type->id == TypeTableEntryIdFn) return true;
4191 }
4192 return false;
4193}
4194
4195static TypeTableEntry *bad_method_call(CodeGen *g, AstNode *node, TypeTableEntry *container_type,
4196 TypeTableEntry *expected_param_type, FnTableEntry *fn_table_entry)
4197{
4198 ErrorMsg *msg = add_node_error(g, node,
4199 buf_sprintf("function called as method of '%s', but first parameter is of type '%s'",
4200 buf_ptr(&container_type->name),
4201 buf_ptr(&expected_param_type->name)));
4202 if (fn_table_entry) {
4203 add_error_note(g, msg, fn_table_entry->proto_node, buf_sprintf("function declared here"));
4204 }
4205 return g->builtin_types.entry_invalid;
4206}
4207
4208// Before calling this function, set node->data.fn_call_expr.fn_table_entry if the function is known
4209// at compile time. Otherwise this is a function pointer call.
4210static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4211 TypeTableEntry *expected_type, AstNode *node, TypeTableEntry *fn_type,
4212 AstNode *struct_node)
4213{
4214 assert(node->type == NodeTypeFnCallExpr);
4215
4216 if (fn_type->id == TypeTableEntryIdInvalid) {
4217 return fn_type;
4218 }
4219
4220 // The function call might include inline parameters which we need to ignore according to the
4221 // fn_type.
4222 FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
4223 AstNode *generic_proto_node = fn_table_entry ?
4224 fn_table_entry->proto_node->data.fn_proto.generic_proto_node : nullptr;
4225
4226 // count parameters
4227 size_t struct_node_1_or_0 = struct_node ? 1 : 0;
4228 size_t src_param_count = fn_type->data.fn.fn_type_id.param_count +
4229 (generic_proto_node ? generic_proto_node->data.fn_proto.inline_arg_count : 0);
4230 size_t call_param_count = node->data.fn_call_expr.params.length;
4231 size_t expect_arg_count = src_param_count - struct_node_1_or_0;
4232
4233 bool ok_invocation = true;
4234
4235 if (fn_type->data.fn.fn_type_id.is_var_args) {
4236 if (call_param_count < expect_arg_count) {
4237 ok_invocation = false;
4238 add_node_error(g, node,
4239 buf_sprintf("expected at least %zu arguments, got %zu", src_param_count, call_param_count));
4240 }
4241 } else if (expect_arg_count != call_param_count) {
4242 ok_invocation = false;
4243 add_node_error(g, node,
4244 buf_sprintf("expected %zu arguments, got %zu", expect_arg_count, call_param_count));
4245 }
4246
4247 bool all_args_const_expr = true;
4248
4249 if (struct_node) {
4250 Expr *struct_expr = get_resolved_expr(struct_node);
4251 ConstExprValue *struct_const_val = &struct_expr->const_val;
4252 if (!struct_const_val->ok) {
4253 all_args_const_expr = false;
4254 }
4255
4256 FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[0];
4257 TypeTableEntry *expected_param_type = param_info->type;
4258 TypeTableEntry *container_bare_type = container_ref_type(struct_expr->type_entry);
4259 if (is_container_ref(expected_param_type)) {
4260 TypeTableEntry *param_bare_type = container_ref_type(expected_param_type);
4261 if (param_bare_type != container_bare_type) {
4262 return bad_method_call(g, node, container_bare_type, expected_param_type, fn_table_entry);
4263 }
4264 } else {
4265 return bad_method_call(g, node, container_bare_type, expected_param_type, fn_table_entry);
4266 }
4267 }
4268
4269 // analyze each parameter. in the case of a method, we already analyzed the
4270 // first parameter in order to figure out which struct we were calling a method on.
4271 size_t next_type_i = struct_node_1_or_0;
4272 for (size_t call_i = 0; call_i < call_param_count; call_i += 1) {
4273 size_t proto_i = call_i + struct_node_1_or_0;
4274 AstNode **param_node = &node->data.fn_call_expr.params.at(call_i);
4275 // determine the expected type for each parameter
4276 TypeTableEntry *expected_param_type = nullptr;
4277 if (proto_i < src_param_count) {
4278 if (generic_proto_node &&
4279 generic_proto_node->data.fn_proto.params.at(proto_i)->data.param_decl.is_inline)
4280 {
4281 continue;
4282 }
4283
4284 FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[next_type_i];
4285 next_type_i += 1;
4286
4287 expected_param_type = param_info->type;
4288 }
4289 TypeTableEntry *param_type = analyze_expression(g, import, context, expected_param_type, *param_node);
4290 if (param_type->id == TypeTableEntryIdInvalid) {
4291 return param_type;
4292 }
4293
4294 ConstExprValue *const_arg_val = &get_resolved_expr(*param_node)->const_val;
4295 if (!const_arg_val->ok) {
4296 all_args_const_expr = false;
4297 }
4298 }
4299
4300 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
4301
4302 if (return_type->id == TypeTableEntryIdInvalid) {
4303 return return_type;
4304 }
4305
4306 ConstExprValue *result_val = &get_resolved_expr(node)->const_val;
4307 if (ok_invocation && fn_table_entry && fn_table_entry->is_pure && fn_table_entry->want_pure != WantPureFalse) {
4308 if (fn_table_entry->anal_state == FnAnalStateReady) {
4309 analyze_fn_body(g, fn_table_entry);
4310 if (fn_table_entry->proto_node->data.fn_proto.skip) {
4311 return g->builtin_types.entry_invalid;
4312 }
4313 }
4314 if (all_args_const_expr) {
4315 if (fn_table_entry->is_pure && fn_table_entry->anal_state == FnAnalStateComplete) {
4316 if (eval_fn(g, node, fn_table_entry, result_val, 1000, struct_node)) {
4317 // function evaluation generated an error
4318 return g->builtin_types.entry_invalid;
4319 }
4320 return return_type;
4321 }
4322 }
4323 }
4324 if (!ok_invocation || !fn_table_entry || !fn_table_entry->is_pure || fn_table_entry->want_pure == WantPureFalse) {
4325 // calling an impure fn is impure
4326 mark_impure_fn(g, context, node);
4327 if (fn_table_entry && fn_table_entry->want_pure == WantPureTrue) {
4328 return g->builtin_types.entry_invalid;
4329 }
4330 }
4331
4332 // TODO
4333 //if (handle_is_ptr(return_type)) {
4334 // if (context->fn_entry) {
4335 // context->fn_entry->cast_alloca_list.append(node);
4336 // } else if (!result_val->ok) {
4337 // add_node_error(g, node, buf_sprintf("unable to evaluate constant expression"));
4338 // }
4339 //}
4340
4341 return return_type;
4342}
4343
4344static TypeTableEntry *analyze_fn_call_with_inline_args(CodeGen *g, ImportTableEntry *import,
4345 BlockContext *parent_context, TypeTableEntry *expected_type, AstNode *call_node,
4346 FnTableEntry *fn_table_entry, AstNode *struct_node)
4347{
4348 assert(call_node->type == NodeTypeFnCallExpr);
4349 assert(fn_table_entry);
4350
4351 AstNode *decl_node = fn_table_entry->proto_node;
4352
4353 // count parameters
4354 size_t struct_node_1_or_0 = (struct_node ? 1 : 0);
4355 size_t src_param_count = decl_node->data.fn_proto.params.length;
4356 size_t call_param_count = call_node->data.fn_call_expr.params.length;
4357
4358 if (src_param_count != call_param_count + struct_node_1_or_0) {
4359 add_node_error(g, call_node,
4360 buf_sprintf("expected %zu arguments, got %zu", src_param_count - struct_node_1_or_0, call_param_count));
4361 return g->builtin_types.entry_invalid;
4362 }
4363
4364 size_t inline_or_var_type_arg_count = decl_node->data.fn_proto.inline_or_var_type_arg_count;
4365 assert(inline_or_var_type_arg_count > 0);
4366
4367 BlockContext *child_context = decl_node->owner->block_context;
4368 size_t next_generic_param_index = 0;
4369
4370 GenericFnTypeId *generic_fn_type_id = allocate<GenericFnTypeId>(1);
4371 generic_fn_type_id->decl_node = decl_node;
4372 generic_fn_type_id->generic_param_count = inline_or_var_type_arg_count;
4373 generic_fn_type_id->generic_params = allocate<GenericParamValue>(inline_or_var_type_arg_count);
4374
4375 size_t next_impl_i = 0;
4376 for (size_t call_i = 0; call_i < call_param_count; call_i += 1) {
4377 size_t proto_i = call_i + struct_node_1_or_0;
4378 AstNode *generic_param_decl_node = decl_node->data.fn_proto.params.at(proto_i);
4379 assert(generic_param_decl_node->type == NodeTypeParamDecl);
4380
4381 AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type;
4382 TypeTableEntry *expected_param_type = analyze_type_expr(g, decl_node->owner, child_context,
4383 *generic_param_type_node);
4384 if (expected_param_type->id == TypeTableEntryIdInvalid) {
4385 return expected_param_type;
4386 }
4387
4388 bool is_var_type = (expected_param_type->id == TypeTableEntryIdVar);
4389 bool is_inline = generic_param_decl_node->data.param_decl.is_inline;
4390 if (!is_inline && !is_var_type) {
4391 next_impl_i += 1;
4392 continue;
4393 }
4394
4395
4396 AstNode **param_node = &call_node->data.fn_call_expr.params.at(call_i);
4397 TypeTableEntry *param_type = analyze_expression(g, import, parent_context,
4398 is_var_type ? nullptr : expected_param_type, *param_node);
4399 if (param_type->id == TypeTableEntryIdInvalid) {
4400 return param_type;
4401 }
4402
4403 // set child_context so that the previous param is in scope
4404 child_context = new_block_context(generic_param_decl_node, child_context);
4405
4406 ConstExprValue *const_val = &get_resolved_expr(*param_node)->const_val;
4407 if (is_inline && !const_val->ok) {
4408 add_node_error(g, *param_node,
4409 buf_sprintf("unable to evaluate constant expression for inline parameter"));
4410
4411 return g->builtin_types.entry_invalid;
4412 }
4413
4414 VariableTableEntry *var = add_local_var_shadowable(g, generic_param_decl_node, decl_node->owner, child_context,
4415 generic_param_decl_node->data.param_decl.name, param_type, true, *param_node, true);
4416 // This generic function instance could be called with anything, so when this variable is read it
4417 // needs to know that it depends on compile time variable data.
4418 var->force_depends_on_compile_var = true;
4419
4420 GenericParamValue *generic_param_value =
4421 &generic_fn_type_id->generic_params[next_generic_param_index];
4422 generic_param_value->type = param_type;
4423 generic_param_value->node = is_inline ? *param_node : nullptr;
4424 generic_param_value->impl_index = next_impl_i;
4425 next_generic_param_index += 1;
4426
4427 if (!is_inline) {
4428 next_impl_i += 1;
4429 }
4430 }
4431
4432 assert(next_generic_param_index == inline_or_var_type_arg_count);
4433
4434 auto entry = g->generic_table.maybe_get(generic_fn_type_id);
4435 FnTableEntry *impl_fn;
4436 if (entry) {
4437 AstNode *impl_decl_node = entry->value;
4438 assert(impl_decl_node->type == NodeTypeFnProto);
4439 impl_fn = impl_decl_node->data.fn_proto.fn_table_entry;
4440 } else {
4441 AstNode *decl_node = generic_fn_type_id->decl_node;
4442 AstNode *impl_fn_def_node = ast_clone_subtree_special(decl_node->data.fn_proto.fn_def_node,
4443 &g->next_node_index, AstCloneSpecialOmitInlineParams);
4444 AstNode *impl_decl_node = impl_fn_def_node->data.fn_def.fn_proto;
4445 impl_decl_node->data.fn_proto.inline_arg_count = 0;
4446 impl_decl_node->data.fn_proto.inline_or_var_type_arg_count = 0;
4447 impl_decl_node->data.fn_proto.generic_proto_node = decl_node;
4448
4449 // replace var arg types with actual types
4450 for (size_t generic_arg_i = 0; generic_arg_i < inline_or_var_type_arg_count; generic_arg_i += 1) {
4451 GenericParamValue *generic_param_value = &generic_fn_type_id->generic_params[generic_arg_i];
4452 if (!generic_param_value->node) {
4453 size_t impl_i = generic_param_value->impl_index;
4454 AstNode *impl_param_decl_node = impl_decl_node->data.fn_proto.params.at(impl_i);
4455 assert(impl_param_decl_node->type == NodeTypeParamDecl);
4456
4457 impl_param_decl_node->data.param_decl.type = create_ast_type_node(g, import,
4458 generic_param_value->type, impl_param_decl_node);
4459 normalize_parent_ptrs(impl_param_decl_node);
4460 }
4461 }
4462
4463 preview_fn_proto_instance(g, import, impl_decl_node, child_context);
4464 g->generic_table.put(generic_fn_type_id, impl_decl_node);
4465 impl_fn = impl_decl_node->data.fn_proto.fn_table_entry;
4466 }
4467
4468 call_node->data.fn_call_expr.fn_entry = impl_fn;
4469 return analyze_fn_call_ptr(g, import, parent_context, expected_type, call_node,
4470 impl_fn->type_entry, struct_node);
4471}
4472
4473static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context,
4474 TypeTableEntry *expected_type, AstNode *node, TypeTableEntry *generic_fn_type)
4475{
4476 assert(node->type == NodeTypeFnCallExpr);
4477 assert(generic_fn_type->id == TypeTableEntryIdGenericFn);
4478
4479 AstNode *decl_node = generic_fn_type->data.generic_fn.decl_node;
4480 assert(decl_node->type == NodeTypeContainerDecl);
4481 ZigList<AstNode *> *generic_params = &decl_node->data.struct_decl.generic_params;
4482
4483 size_t expected_param_count = generic_params->length;
4484 size_t actual_param_count = node->data.fn_call_expr.params.length;
4485
4486 if (actual_param_count != expected_param_count) {
4487 add_node_error(g, first_executing_node(node),
4488 buf_sprintf("expected %zu arguments, got %zu", expected_param_count, actual_param_count));
4489 return g->builtin_types.entry_invalid;
4490 }
4491
4492 GenericFnTypeId *generic_fn_type_id = allocate<GenericFnTypeId>(1);
4493 generic_fn_type_id->decl_node = decl_node;
4494 generic_fn_type_id->generic_param_count = actual_param_count;
4495 generic_fn_type_id->generic_params = allocate<GenericParamValue>(actual_param_count);
4496
4497 BlockContext *child_context = decl_node->owner->block_context;
4498 for (size_t i = 0; i < actual_param_count; i += 1) {
4499 AstNode *generic_param_decl_node = generic_params->at(i);
4500 assert(generic_param_decl_node->type == NodeTypeParamDecl);
4501
4502 AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type;
4503
4504 TypeTableEntry *expected_param_type = analyze_type_expr(g, decl_node->owner,
4505 child_context, *generic_param_type_node);
4506 if (expected_param_type->id == TypeTableEntryIdInvalid) {
4507 return expected_param_type;
4508 }
4509
4510
4511
4512 AstNode **param_node = &node->data.fn_call_expr.params.at(i);
4513
4514 TypeTableEntry *param_type = analyze_expression(g, import, parent_context, expected_param_type,
4515 *param_node);
4516 if (param_type->id == TypeTableEntryIdInvalid) {
4517 return param_type;
4518 }
4519
4520 // set child_context so that the previous param is in scope
4521 child_context = new_block_context(generic_param_decl_node, child_context);
4522
4523 ConstExprValue *const_val = &get_resolved_expr(*param_node)->const_val;
4524 if (const_val->ok) {
4525 VariableTableEntry *var = add_local_var(g, generic_param_decl_node, decl_node->owner, child_context,
4526 generic_param_decl_node->data.param_decl.name, param_type, true, *param_node);
4527 var->force_depends_on_compile_var = true;
4528 } else {
4529 add_node_error(g, *param_node, buf_sprintf("unable to evaluate constant expression"));
4530
4531 return g->builtin_types.entry_invalid;
4532 }
4533
4534 GenericParamValue *generic_param_value = &generic_fn_type_id->generic_params[i];
4535 generic_param_value->type = param_type;
4536 generic_param_value->node = *param_node;
4537 }
4538
4539 auto entry = g->generic_table.maybe_get(generic_fn_type_id);
4540 if (entry) {
4541 AstNode *impl_decl_node = entry->value;
4542 assert(impl_decl_node->type == NodeTypeContainerDecl);
4543 TypeTableEntry *type_entry = impl_decl_node->data.struct_decl.type_entry;
4544 return resolve_expr_const_val_as_type(g, node, type_entry, false);
4545 }
4546
4547 // make a type from the generic parameters supplied
4548 assert(decl_node->type == NodeTypeContainerDecl);
4549 AstNode *impl_decl_node = ast_clone_subtree(decl_node, &g->next_node_index);
4550 g->generic_table.put(generic_fn_type_id, impl_decl_node);
4551 scan_struct_decl(g, import, child_context, impl_decl_node);
4552 TypeTableEntry *type_entry = impl_decl_node->data.struct_decl.type_entry;
4553 resolve_struct_type(g, import, type_entry);
4554 return resolve_expr_const_val_as_type(g, node, type_entry, false);
4555}
4556
4557static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4558 TypeTableEntry *expected_type, AstNode *node)
4559{
4560 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
4561
4562 if (node->data.fn_call_expr.is_builtin) {
4563 zig_panic("moved builtin fn call code to ir.cpp");
4564 }
4565
4566 TypeTableEntry *invoke_type_entry = analyze_expression(g, import, context, nullptr, fn_ref_expr);
4567 if (invoke_type_entry->id == TypeTableEntryIdInvalid) {
4568 return g->builtin_types.entry_invalid;
4569 }
4570
4571 // use constant expression evaluator to figure out the function at compile time.
4572 // otherwise we treat this as a function pointer.
4573 ConstExprValue *const_val = &get_resolved_expr(fn_ref_expr)->const_val;
4574
4575 if (const_val->ok) {
4576 if (invoke_type_entry->id == TypeTableEntryIdMetaType) {
4577 zig_unreachable();
4578 } else if (invoke_type_entry->id == TypeTableEntryIdFn) {
4579 AstNode *struct_node;
4580 if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&
4581 fn_ref_expr->data.field_access_expr.is_member_fn)
4582 {
4583 struct_node = fn_ref_expr->data.field_access_expr.struct_expr;
4584 } else {
4585 struct_node = nullptr;
4586 }
4587
4588 FnTableEntry *fn_table_entry = const_val->data.x_fn;
4589 node->data.fn_call_expr.fn_entry = fn_table_entry;
4590 return analyze_fn_call_ptr(g, import, context, expected_type, node,
4591 fn_table_entry->type_entry, struct_node);
4592 } else if (invoke_type_entry->id == TypeTableEntryIdGenericFn) {
4593 TypeTableEntry *generic_fn_type = const_val->data.x_type;
4594 AstNode *decl_node = generic_fn_type->data.generic_fn.decl_node;
4595 if (decl_node->type == NodeTypeFnProto) {
4596 AstNode *struct_node;
4597 if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&
4598 fn_ref_expr->data.field_access_expr.is_member_fn)
4599 {
4600 struct_node = fn_ref_expr->data.field_access_expr.struct_expr;
4601 } else {
4602 struct_node = nullptr;
4603 }
4604
4605 FnTableEntry *fn_table_entry = decl_node->data.fn_proto.fn_table_entry;
4606 if (fn_table_entry->proto_node->data.fn_proto.skip) {
4607 return g->builtin_types.entry_invalid;
4608 }
4609 return analyze_fn_call_with_inline_args(g, import, context, expected_type, node,
4610 fn_table_entry, struct_node);
4611 } else {
4612 return analyze_generic_fn_call(g, import, context, expected_type, node, const_val->data.x_type);
4613 }
4614 } else {
4615 add_node_error(g, fn_ref_expr,
4616 buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name)));
4617 return g->builtin_types.entry_invalid;
4618 }
4619 }
4620
4621 // function pointer
4622 if (invoke_type_entry->id == TypeTableEntryIdFn) {
4623 return analyze_fn_call_ptr(g, import, context, expected_type, node, invoke_type_entry, nullptr);
4624 } else {
4625 add_node_error(g, fn_ref_expr,
4626 buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name)));
4627 return g->builtin_types.entry_invalid;
4628 }
4629}
4630
4631static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4632 TypeTableEntry *expected_type, AstNode *node)
4633{
4634 AstNode **expr_node = &node->data.switch_expr.expr;
4635 TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node);
4636 ConstExprValue *expr_val = &get_resolved_expr(*expr_node)->const_val;
4637 if (expr_val->ok && !expr_val->depends_on_compile_var) {
4638 add_node_error(g, first_executing_node(*expr_node),
4639 buf_sprintf("value is constant; unnecessary switch statement"));
4640 }
4641 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
4642
4643
4644 size_t prong_count = node->data.switch_expr.prongs.length;
4645 AstNode **peer_nodes = allocate<AstNode*>(prong_count);
4646 TypeTableEntry **peer_types = allocate<TypeTableEntry*>(prong_count);
4647
4648 bool any_errors = false;
4649 if (expr_type->id == TypeTableEntryIdInvalid) {
4650 return expr_type;
4651 } else if (expr_type->id == TypeTableEntryIdUnreachable) {
4652 add_node_error(g, first_executing_node(*expr_node),
4653 buf_sprintf("switch on unreachable expression not allowed"));
4654 return g->builtin_types.entry_invalid;
4655 }
4656
4657
4658 size_t *field_use_counts = nullptr;
4659 HashMap<int, AstNode *, int_hash, int_eq> err_use_nodes = {};
4660 if (expr_type->id == TypeTableEntryIdEnum) {
4661 field_use_counts = allocate<size_t>(expr_type->data.enumeration.src_field_count);
4662 } else if (expr_type->id == TypeTableEntryIdErrorUnion) {
4663 err_use_nodes.init(10);
4664 }
4665
4666 size_t *const_chosen_prong_index = &node->data.switch_expr.const_chosen_prong_index;
4667 *const_chosen_prong_index = SIZE_MAX;
4668 AstNode *else_prong = nullptr;
4669 for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) {
4670 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
4671
4672 TypeTableEntry *var_type;
4673 bool var_is_target_expr;
4674 if (prong_node->data.switch_prong.items.length == 0) {
4675 if (else_prong) {
4676 add_node_error(g, prong_node, buf_sprintf("multiple else prongs in switch expression"));
4677 any_errors = true;
4678 } else {
4679 else_prong = prong_node;
4680 }
4681 var_type = expr_type;
4682 var_is_target_expr = true;
4683 if (*const_chosen_prong_index == SIZE_MAX && expr_val->ok) {
4684 *const_chosen_prong_index = prong_i;
4685 }
4686 } else {
4687 bool all_agree_on_var_type = true;
4688 var_type = nullptr;
4689
4690 for (size_t item_i = 0; item_i < prong_node->data.switch_prong.items.length; item_i += 1) {
4691 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
4692 if (item_node->type == NodeTypeSwitchRange) {
4693 zig_panic("TODO range in switch statement");
4694 }
4695
4696 if (expr_type->id == TypeTableEntryIdEnum) {
4697 if (item_node->type == NodeTypeSymbol) {
4698 Buf *field_name = item_node->data.symbol_expr.symbol;
4699 TypeEnumField *type_enum_field = find_enum_type_field(expr_type, field_name);
4700 if (type_enum_field) {
4701 item_node->data.symbol_expr.enum_field = type_enum_field;
4702 if (!var_type) {
4703 var_type = type_enum_field->type_entry;
4704 }
4705 if (type_enum_field->type_entry != var_type) {
4706 all_agree_on_var_type = false;
4707 }
4708 uint32_t field_index = type_enum_field->value;
4709 assert(field_use_counts);
4710 field_use_counts[field_index] += 1;
4711 if (field_use_counts[field_index] > 1) {
4712 add_node_error(g, item_node,
4713 buf_sprintf("duplicate switch value: '%s'",
4714 buf_ptr(type_enum_field->name)));
4715 any_errors = true;
4716 }
4717 if (!any_errors && expr_val->ok) {
4718 if (expr_val->data.x_enum.tag == type_enum_field->value) {
4719 *const_chosen_prong_index = prong_i;
4720 }
4721 }
4722 } else {
4723 add_node_error(g, item_node,
4724 buf_sprintf("enum '%s' has no field '%s'",
4725 buf_ptr(&expr_type->name), buf_ptr(field_name)));
4726 any_errors = true;
4727 }
4728 } else {
4729 add_node_error(g, item_node, buf_sprintf("expected enum tag name"));
4730 any_errors = true;
4731 }
4732 } else if (expr_type->id == TypeTableEntryIdErrorUnion) {
4733 if (item_node->type == NodeTypeSymbol) {
4734 Buf *err_name = item_node->data.symbol_expr.symbol;
4735 bool is_ok_case = buf_eql_str(err_name, "Ok");
4736 auto err_table_entry = is_ok_case ? nullptr: g->error_table.maybe_get(err_name);
4737 if (is_ok_case || err_table_entry) {
4738 uint32_t err_value = is_ok_case ? 0 : err_table_entry->value->value;
4739 item_node->data.symbol_expr.err_value = err_value;
4740 TypeTableEntry *this_var_type;
4741 if (is_ok_case) {
4742 this_var_type = expr_type->data.error.child_type;
4743 } else {
4744 this_var_type = g->builtin_types.entry_pure_error;
4745 }
4746 if (!var_type) {
4747 var_type = this_var_type;
4748 }
4749 if (this_var_type != var_type) {
4750 all_agree_on_var_type = false;
4751 }
4752
4753 // detect duplicate switch values
4754 auto existing_entry = err_use_nodes.maybe_get(err_value);
4755 if (existing_entry) {
4756 add_node_error(g, existing_entry->value,
4757 buf_sprintf("duplicate switch value: '%s'", buf_ptr(err_name)));
4758 any_errors = true;
4759 } else {
4760 err_use_nodes.put(err_value, item_node);
4761 }
4762
4763 if (!any_errors && expr_val->ok) {
4764 if (expr_val->data.x_err.err->value == err_value) {
4765 *const_chosen_prong_index = prong_i;
4766 }
4767 }
4768 } else {
4769 add_node_error(g, item_node,
4770 buf_sprintf("use of undeclared error value '%s'", buf_ptr(err_name)));
4771 any_errors = true;
4772 }
4773 } else {
4774 add_node_error(g, item_node, buf_sprintf("expected error value name"));
4775 any_errors = true;
4776 }
4777 } else {
4778 if (!any_errors && expr_val->ok) {
4779 // note: there is now a function in eval.cpp for doing const expr comparison
4780 zig_panic("TODO determine if const exprs are equal");
4781 }
4782 TypeTableEntry *item_type = analyze_expression(g, import, context, expr_type, item_node);
4783 if (item_type->id != TypeTableEntryIdInvalid) {
4784 ConstExprValue *const_val = &get_resolved_expr(item_node)->const_val;
4785 if (!const_val->ok) {
4786 add_node_error(g, item_node,
4787 buf_sprintf("unable to evaluate constant expression"));
4788 any_errors = true;
4789 }
4790 }
4791 }
4792 }
4793 if (!var_type || !all_agree_on_var_type) {
4794 var_type = expr_type;
4795 var_is_target_expr = true;
4796 } else {
4797 var_is_target_expr = false;
4798 }
4799 }
4800
4801 BlockContext *child_context = new_block_context(node, context);
4802 prong_node->data.switch_prong.block_context = child_context;
4803 AstNode *var_node = prong_node->data.switch_prong.var_symbol;
4804 if (var_node) {
4805 assert(var_node->type == NodeTypeSymbol);
4806 Buf *var_name = var_node->data.symbol_expr.symbol;
4807 var_node->block_context = child_context;
4808 prong_node->data.switch_prong.var = add_local_var(g, var_node, import,
4809 child_context, var_name, var_type, true, nullptr);
4810 prong_node->data.switch_prong.var_is_target_expr = var_is_target_expr;
4811 }
4812 }
4813
4814 for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) {
4815 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
4816 BlockContext *child_context = prong_node->data.switch_prong.block_context;
4817 child_context->codegen_excluded = expr_val->ok && (*const_chosen_prong_index != prong_i);
4818
4819 if (child_context->codegen_excluded) {
4820 peer_types[prong_i] = g->builtin_types.entry_unreachable;
4821 } else {
4822 peer_types[prong_i] = analyze_expression(g, import, child_context, expected_type,
4823 prong_node->data.switch_prong.expr);
4824 }
4825 // This must go after the analyze_expression for
4826 // prong_node->data.switch_prong.expr because of AST rewriting.
4827 peer_nodes[prong_i] = prong_node->data.switch_prong.expr;
4828 }
4829
4830 if (expr_type->id == TypeTableEntryIdEnum && !else_prong) {
4831 for (uint32_t i = 0; i < expr_type->data.enumeration.src_field_count; i += 1) {
4832 if (field_use_counts[i] == 0) {
4833 add_node_error(g, node,
4834 buf_sprintf("enumeration value '%s' not handled in switch",
4835 buf_ptr(expr_type->data.enumeration.fields[i].name)));
4836 any_errors = true;
4837 }
4838 }
4839 }
4840
4841 if (any_errors) {
4842 return g->builtin_types.entry_invalid;
4843 }
4844
4845 if (prong_count == 0) {
4846 add_node_error(g, node, buf_sprintf("switch statement has no prongs"));
4847 return g->builtin_types.entry_invalid;
4848 }
4849
4850 TypeTableEntry *result_type = resolve_peer_type_compatibility(g, import, context, node,
4851 peer_nodes, peer_types, prong_count);
4852
4853 if (expr_val->ok) {
4854 assert(*const_chosen_prong_index != SIZE_MAX);
4855
4856 *const_val = get_resolved_expr(peer_nodes[*const_chosen_prong_index])->const_val;
4857 // the target expr depends on a compile var because we have an error on unnecessary
4858 // switch statement, so the entire switch statement does too
4859 const_val->depends_on_compile_var = true;
4860
4861 if (!const_val->ok) {
4862 return add_error_if_type_is_num_lit(g, result_type, node);
4863 }
4864 } else {
4865 return add_error_if_type_is_num_lit(g, result_type, node);
4866 }
4867
4868 return result_type;
4869}
4870
4871static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4872 TypeTableEntry *expected_type, AstNode *node)
4873{
4874 if (!node->data.return_expr.expr) {
4875 node->data.return_expr.expr = create_ast_void_node(g, import, node);
4876 normalize_parent_ptrs(node);
4877 }
4878
4879 TypeTableEntry *expected_return_type = get_return_type(context);
4880
4881 switch (node->data.return_expr.kind) {
4882 case ReturnKindUnconditional:
4883 zig_panic("TODO moved to ir.cpp");
4884 case ReturnKindError:
4885 {
4886 TypeTableEntry *expected_err_type;
4887 if (expected_type) {
4888 expected_err_type = get_error_type(g, expected_type);
4889 } else {
4890 expected_err_type = nullptr;
4891 }
4892 TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_err_type,
4893 node->data.return_expr.expr);
4894 if (resolved_type->id == TypeTableEntryIdInvalid) {
4895 return resolved_type;
4896 } else if (resolved_type->id == TypeTableEntryIdErrorUnion) {
4897 if (expected_return_type->id != TypeTableEntryIdErrorUnion &&
4898 expected_return_type->id != TypeTableEntryIdPureError)
4899 {
4900 ErrorMsg *msg = add_node_error(g, node,
4901 buf_sprintf("%%return statement in function with return type '%s'",
4902 buf_ptr(&expected_return_type->name)));
4903 AstNode *return_type_node = context->fn_entry->fn_def_node->data.fn_def.fn_proto->data.fn_proto.return_type;
4904 add_error_note(g, msg, return_type_node, buf_sprintf("function return type here"));
4905 }
4906
4907 return resolved_type->data.error.child_type;
4908 } else {
4909 add_node_error(g, node->data.return_expr.expr,
4910 buf_sprintf("expected error type, got '%s'", buf_ptr(&resolved_type->name)));
4911 return g->builtin_types.entry_invalid;
4912 }
4913 }
4914 case ReturnKindMaybe:
4915 {
4916 TypeTableEntry *expected_maybe_type;
4917 if (expected_type) {
4918 expected_maybe_type = get_maybe_type(g, expected_type);
4919 } else {
4920 expected_maybe_type = nullptr;
4921 }
4922 TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_maybe_type,
4923 node->data.return_expr.expr);
4924 if (resolved_type->id == TypeTableEntryIdInvalid) {
4925 return resolved_type;
4926 } else if (resolved_type->id == TypeTableEntryIdMaybe) {
4927 if (expected_return_type->id != TypeTableEntryIdMaybe) {
4928 ErrorMsg *msg = add_node_error(g, node,
4929 buf_sprintf("?return statement in function with return type '%s'",
4930 buf_ptr(&expected_return_type->name)));
4931 AstNode *return_type_node = context->fn_entry->fn_def_node->data.fn_def.fn_proto->data.fn_proto.return_type;
4932 add_error_note(g, msg, return_type_node, buf_sprintf("function return type here"));
4933 }
4934
4935 return resolved_type->data.maybe.child_type;
4936 } else {
4937 add_node_error(g, node->data.return_expr.expr,
4938 buf_sprintf("expected maybe type, got '%s'", buf_ptr(&resolved_type->name)));
4939 return g->builtin_types.entry_invalid;
4940 }
4941 }
4942 }
4943 zig_unreachable();
4944}
4945
4946static void validate_voided_expr(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) {
4947 if (type_entry->id == TypeTableEntryIdMetaType) {
4948 add_node_error(g, first_executing_node(source_node), buf_sprintf("expected expression, found type"));
4949 } else if (type_entry->id == TypeTableEntryIdErrorUnion) {
4950 add_node_error(g, first_executing_node(source_node), buf_sprintf("statement ignores error value"));
4951 }
4952}
4953
4954static TypeTableEntry *analyze_defer(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context,
4955 TypeTableEntry *expected_type, AstNode *node)
4956{
4957 if (!parent_context->fn_entry) {
4958 add_node_error(g, node, buf_sprintf("defer expression outside function definition"));
4959 return g->builtin_types.entry_invalid;
4960 }
4961
4962 if (!node->data.defer.expr) {
4963 add_node_error(g, node, buf_sprintf("defer expects an expression"));
4964 return g->builtin_types.entry_void;
4965 }
4966
4967 node->data.defer.child_block = new_block_context(node, parent_context);
4968
4969 TypeTableEntry *resolved_type = analyze_expression(g, import, parent_context, nullptr,
4970 node->data.defer.expr);
4971 validate_voided_expr(g, node->data.defer.expr, resolved_type);
4972
4973 return g->builtin_types.entry_void;
4974}
4975
4976static TypeTableEntry *analyze_string_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4977 TypeTableEntry *expected_type, AstNode *node)
4978{
4979 if (node->data.string_literal.c) {
4980 return resolve_expr_const_val_as_c_string_lit(g, node, node->data.string_literal.buf);
4981 } else {
4982 return resolve_expr_const_val_as_string_lit(g, node, node->data.string_literal.buf);
4983 }
4984}
4985
4986static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context,
4987 TypeTableEntry *expected_type, AstNode *node)
4988{
4989 BlockContext *child_context = new_block_context(node, parent_context);
4990 node->data.block.child_block = child_context;
4991 TypeTableEntry *return_type = g->builtin_types.entry_void;
4992
4993 for (size_t i = 0; i < node->data.block.statements.length; i += 1) {
4994 AstNode *child = node->data.block.statements.at(i);
4995 if (child->type == NodeTypeLabel) {
4996 FnTableEntry *fn_table_entry = child_context->fn_entry;
4997 assert(fn_table_entry);
4998
4999 LabelTableEntry *label = allocate<LabelTableEntry>(1);
5000 label->decl_node = child;
5001 label->entered_from_fallthrough = (return_type->id != TypeTableEntryIdUnreachable);
5002
5003 child->block_context = child_context;
5004 child->data.label.label_entry = label;
5005 fn_table_entry->all_labels.append(label);
5006
5007 child_context->label_table.put(child->data.label.name, label);
5008
5009 return_type = g->builtin_types.entry_void;
5010 continue;
5011 }
5012 if (return_type->id == TypeTableEntryIdUnreachable) {
5013 if (is_node_void_expr(child)) {
5014 // {unreachable;void;void} is allowed.
5015 // ignore void statements once we enter unreachable land.
5016 analyze_expression(g, import, child_context, g->builtin_types.entry_void, child);
5017 continue;
5018 }
5019 add_node_error(g, first_executing_node(child), buf_sprintf("unreachable code"));
5020 break;
5021 }
5022 bool is_last = (i == node->data.block.statements.length - 1);
5023 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
5024 return_type = analyze_expression(g, import, child_context, passed_expected_type, child);
5025 if (child->type == NodeTypeDefer && return_type->id != TypeTableEntryIdInvalid) {
5026 // defer starts a new block context
5027 child_context = child->data.defer.child_block;
5028 assert(child_context);
5029 }
5030 if (!is_last) {
5031 validate_voided_expr(g, child, return_type);
5032 }
5033 }
5034 node->data.block.nested_block = child_context;
5035
5036 ConstExprValue *const_val = &node->data.block.resolved_expr.const_val;
5037 if (node->data.block.statements.length == 0) {
5038 const_val->ok = true;
5039 } else if (node->data.block.statements.length == 1) {
5040 AstNode *only_node = node->data.block.statements.at(0);
5041 ConstExprValue *other_const_val = &get_resolved_expr(only_node)->const_val;
5042 if (other_const_val->ok) {
5043 *const_val = *other_const_val;
5044 }
5045 }
5046
5047 return return_type;
5048}
5049
5050static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
5051 TypeTableEntry *expected_type, AstNode *node)
5052{
5053 mark_impure_fn(g, context, node);
5054
5055 node->data.asm_expr.return_count = 0;
5056 TypeTableEntry *return_type = g->builtin_types.entry_void;
5057 for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1) {
5058 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
5059 if (asm_output->return_type) {
5060 node->data.asm_expr.return_count += 1;
5061 return_type = analyze_type_expr(g, import, context, asm_output->return_type);
5062 if (node->data.asm_expr.return_count > 1) {
5063 add_node_error(g, node,
5064 buf_sprintf("inline assembly allows up to one output value"));
5065 break;
5066 }
5067 } else {
5068 Buf *variable_name = asm_output->variable_name;
5069 VariableTableEntry *var = find_variable(g, context, variable_name);
5070 if (var) {
5071 asm_output->variable = var;
5072 return var->type;
5073 } else {
5074 add_node_error(g, node,
5075 buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
5076 return g->builtin_types.entry_invalid;
5077 }
5078 }
5079 }
5080 for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1) {
5081 AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
5082 analyze_expression(g, import, context, nullptr, asm_input->expr);
5083 }
5084
5085 return return_type;
5086}
5087
5088static TypeTableEntry *analyze_goto_pass1(CodeGen *g, ImportTableEntry *import, BlockContext *context,
5089 TypeTableEntry *expected_type, AstNode *node)
5090{
5091 assert(node->type == NodeTypeGoto);
5092
5093 FnTableEntry *fn_table_entry = context->fn_entry;
5094 assert(fn_table_entry);
5095
5096 fn_table_entry->goto_list.append(node);
5097
5098 return g->builtin_types.entry_unreachable;
5099}
5100
5101static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEntry *import,
5102 BlockContext *context, TypeTableEntry *expected_type, AstNode *node, bool pointer_only)
5103{
5104 assert(!expected_type || expected_type->id != TypeTableEntryIdInvalid);
5105 TypeTableEntry *return_type = nullptr;
5106 node->block_context = context;
5107 switch (node->type) {
5108 case NodeTypeBlock:
5109 return_type = analyze_block_expr(g, import, context, expected_type, node);
5110 break;
5111
5112 case NodeTypeReturnExpr:
5113 return_type = analyze_return_expr(g, import, context, expected_type, node);
5114 break;
5115 case NodeTypeDefer:
5116 return_type = analyze_defer(g, import, context, expected_type, node);
5117 break;
5118 case NodeTypeVariableDeclaration:
5119 analyze_variable_declaration(g, import, context, expected_type, node);
5120 return_type = g->builtin_types.entry_void;
5121 break;
5122 case NodeTypeGoto:
5123 return_type = analyze_goto_pass1(g, import, context, expected_type, node);
5124 break;
5125 case NodeTypeBreak:
5126 return_type = analyze_break_expr(g, import, context, expected_type, node);
5127 break;
5128 case NodeTypeContinue:
5129 return_type = analyze_continue_expr(g, import, context, expected_type, node);
5130 break;
5131 case NodeTypeAsmExpr:
5132 return_type = analyze_asm_expr(g, import, context, expected_type, node);
5133 break;
5134 case NodeTypeBinOpExpr:
5135 return_type = analyze_bin_op_expr(g, import, context, expected_type, node);
5136 break;
5137 case NodeTypeUnwrapErrorExpr:
5138 return_type = analyze_unwrap_error_expr(g, import, context, expected_type, node);
5139 break;
5140 case NodeTypeFnCallExpr:
5141 return_type = analyze_fn_call_expr(g, import, context, expected_type, node);
5142 break;
5143
5144 case NodeTypeArrayAccessExpr:
5145 // for reading array access; assignment handled elsewhere
5146 return_type = analyze_array_access_expr(g, import, context, node, LValPurposeAddressOf);
5147 break;
5148 case NodeTypeSliceExpr:
5149 return_type = analyze_slice_expr(g, import, context, node);
5150 break;
5151 case NodeTypeFieldAccessExpr:
5152 return_type = analyze_field_access_expr(g, import, context, expected_type, node);
5153 break;
5154 case NodeTypeContainerInitExpr:
5155 zig_panic("analyze container init moved to ir.cpp");
5156 break;
5157 case NodeTypeNumberLiteral:
5158 return_type = analyze_number_literal_expr(g, import, context, expected_type, node);
5159 break;
5160 case NodeTypeStringLiteral:
5161 return_type = analyze_string_literal_expr(g, import, context, expected_type, node);
5162 break;
5163 case NodeTypeCharLiteral:
5164 return_type = resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
5165 node->data.char_literal.value, false);
5166 break;
5167 case NodeTypeBoolLiteral:
5168 zig_panic("moved to ir.cpp");
5169 break;
5170 case NodeTypeNullLiteral:
5171 return_type = analyze_null_literal_expr(g, import, context, expected_type, node);
5172 break;
5173 case NodeTypeUndefinedLiteral:
5174 return_type = analyze_undefined_literal_expr(g, import, context, expected_type, node);
5175 break;
5176 case NodeTypeZeroesLiteral:
5177 return_type = analyze_zeroes_literal_expr(g, import, context, expected_type, node);
5178 break;
5179 case NodeTypeThisLiteral:
5180 zig_panic("moved to ir.cpp");
5181 break;
5182 case NodeTypeSymbol:
5183 return_type = analyze_symbol_expr(g, import, context, expected_type, node, pointer_only);
5184 break;
5185 case NodeTypePrefixOpExpr:
5186 zig_panic("moved to ir.cpp");
5187 break;
5188 case NodeTypeIfBoolExpr:
5189 return_type = analyze_if_bool_expr(g, import, context, expected_type, node);
5190 break;
5191 case NodeTypeIfVarExpr:
5192 return_type = analyze_if_var_expr(g, import, context, expected_type, node);
5193 break;
5194 case NodeTypeWhileExpr:
5195 return_type = analyze_while_expr(g, import, context, expected_type, node);
5196 break;
5197 case NodeTypeForExpr:
5198 zig_panic("moved to ir.cpp");
5199 break;
5200 case NodeTypeArrayType:
5201 return_type = analyze_array_type(g, import, context, expected_type, node);
5202 break;
5203 case NodeTypeFnProto:
5204 return_type = analyze_fn_proto_expr(g, import, context, expected_type, node);
5205 break;
5206 case NodeTypeErrorType:
5207 return_type = resolve_expr_const_val_as_type(g, node, g->builtin_types.entry_pure_error, false);
5208 break;
5209 case NodeTypeTypeLiteral:
5210 return_type = resolve_expr_const_val_as_type(g, node, g->builtin_types.entry_type, false);
5211 break;
5212 case NodeTypeSwitchExpr:
5213 return_type = analyze_switch_expr(g, import, context, expected_type, node);
5214 break;
5215 case NodeTypeVarLiteral:
5216 return_type = resolve_expr_const_val_as_type(g, node, g->builtin_types.entry_var, false);
5217 break;
5218 case NodeTypeSwitchProng:
5219 case NodeTypeSwitchRange:
5220 case NodeTypeFnDecl:
5221 case NodeTypeParamDecl:
5222 case NodeTypeRoot:
5223 case NodeTypeFnDef:
5224 case NodeTypeUse:
5225 case NodeTypeLabel:
5226 case NodeTypeContainerDecl:
5227 case NodeTypeStructField:
5228 case NodeTypeStructValueField:
5229 case NodeTypeErrorValueDecl:
5230 case NodeTypeTypeDecl:
5231 zig_unreachable();
5232 }
5233 assert(return_type);
5234 // resolve_type_compatibility might do implicit cast which means node is now a child
5235 // of the actual node that we want to return the type of.
5236 //AstNode **field = node->parent_field;
5237 TypeTableEntry *resolved_type = resolve_type_compatibility(g, import, context, node,
5238 expected_type, return_type);
5239
5240 Expr *expr = get_resolved_expr(node);
5241 expr->type_entry = return_type;
5242
5243 add_global_const_expr(g, node);
5244
5245 return resolved_type;
5246}
5247
5248// When you call analyze_expression, the node you pass might no longer be the child node
5249// you thought it was due to implicit casting rewriting the AST.
5250static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
5251 TypeTableEntry *expected_type, AstNode *node)
5252{
5253 return analyze_expression_pointer_only(g, import, context, expected_type, node, false);
5254}
5255
5256static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
5257 ImportTableEntry *import = fn_table_entry->import_entry;
5258 AstNode *node = fn_table_entry->fn_def_node;
5259 assert(node->type == NodeTypeFnDef);
5260
5261 AstNode *fn_proto_node = node->data.fn_def.fn_proto;
5262 assert(fn_proto_node->type == NodeTypeFnProto);
5263
5264 if (fn_proto_node->data.fn_proto.skip) {
5265 // we detected an error with this function definition which prevents us
5266 // from further analyzing it.
5267 fn_table_entry->anal_state = FnAnalStateSkipped;
5268 return;
5269 }
5270 fn_table_entry->anal_state = FnAnalStateProbing;
5271
5272 BlockContext *context = node->data.fn_def.block_context;
5273
5274 TypeTableEntry *fn_type = fn_table_entry->type_entry;
5275 AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto;
5276 for (size_t i = 0; i < fn_proto->params.length; i += 1) {
5277 AstNode *param_decl_node = fn_proto->params.at(i);
5278 assert(param_decl_node->type == NodeTypeParamDecl);
5279
5280 // define local variables for parameters
5281 AstNodeParamDecl *param_decl = &param_decl_node->data.param_decl;
5282 TypeTableEntry *type = unwrapped_node_type(param_decl->type);
5283
5284 if (param_decl->is_noalias && !type_is_codegen_pointer(type)) {
5285 add_node_error(g, param_decl_node, buf_sprintf("noalias on non-pointer parameter"));
5286 }
52872538
5288 if (fn_type->data.fn.fn_type_id.is_extern && handle_is_ptr(type)) {2539 if (fn_type->data.fn.fn_type_id.is_extern && handle_is_ptr(type)) {
5289 add_node_error(g, param_decl_node,2540 add_node_error(g, param_decl_node,
...@@ -5340,162 +2591,6 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {...@@ -5340,162 +2591,6 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
5340 fn_table_entry->anal_state = FnAnalStateComplete;2591 fn_table_entry->anal_state = FnAnalStateComplete;
5341}2592}
53422593
5343static void add_top_level_decl(CodeGen *g, ImportTableEntry *import, BlockContext *block_context,
5344 AstNode *node, Buf *name)
5345{
5346 assert(import);
5347
5348 TopLevelDecl *tld = get_as_top_level_decl(node);
5349 tld->import = import;
5350 tld->name = name;
5351
5352 bool want_to_resolve = (g->check_unused || g->is_test_build || tld->visib_mod == VisibModExport);
5353 bool is_generic_container = (node->type == NodeTypeContainerDecl &&
5354 node->data.struct_decl.generic_params.length > 0);
5355 if (want_to_resolve && !is_generic_container) {
5356 g->resolve_queue.append(node);
5357 }
5358
5359 node->block_context = block_context;
5360
5361 auto entry = block_context->decl_table.maybe_get(name);
5362 if (entry) {
5363 AstNode *other_decl_node = entry->value;
5364 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(name)));
5365 add_error_note(g, msg, other_decl_node, buf_sprintf("previous definition is here"));
5366 } else {
5367 block_context->decl_table.put(name, node);
5368 }
5369}
5370
5371static void count_inline_and_var_args(AstNode *proto_node) {
5372 assert(proto_node->type == NodeTypeFnProto);
5373
5374 size_t *inline_arg_count = &proto_node->data.fn_proto.inline_arg_count;
5375 size_t *inline_or_var_type_arg_count = &proto_node->data.fn_proto.inline_or_var_type_arg_count;
5376
5377 *inline_arg_count = 0;
5378 *inline_or_var_type_arg_count = 0;
5379
5380 // TODO run these nodes through the type analysis system rather than looking for
5381 // specialized ast nodes. this would get fooled by `{var}` instead of `var` which
5382 // is supposed to be equivalent
5383 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
5384 AstNode *param_node = proto_node->data.fn_proto.params.at(i);
5385 assert(param_node->type == NodeTypeParamDecl);
5386 if (param_node->data.param_decl.is_inline) {
5387 *inline_arg_count += 1;
5388 *inline_or_var_type_arg_count += 1;
5389 } else if (param_node->data.param_decl.type->type == NodeTypeVarLiteral) {
5390 *inline_or_var_type_arg_count += 1;
5391 }
5392 }
5393}
5394
5395static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) {
5396 switch (node->type) {
5397 case NodeTypeRoot:
5398 for (size_t i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {
5399 AstNode *child = import->root->data.root.top_level_decls.at(i);
5400 scan_decls(g, import, context, child);
5401 }
5402 break;
5403 case NodeTypeContainerDecl:
5404 {
5405 Buf *name = node->data.struct_decl.name;
5406 add_top_level_decl(g, import, context, node, name);
5407 if (node->data.struct_decl.generic_params.length == 0) {
5408 scan_struct_decl(g, import, context, node);
5409 }
5410 }
5411 break;
5412 case NodeTypeFnDef:
5413 node->data.fn_def.fn_proto->data.fn_proto.fn_def_node = node;
5414 scan_decls(g, import, context, node->data.fn_def.fn_proto);
5415 break;
5416 case NodeTypeVariableDeclaration:
5417 {
5418 Buf *name = node->data.variable_declaration.symbol;
5419 add_top_level_decl(g, import, context, node, name);
5420 break;
5421 }
5422 case NodeTypeTypeDecl:
5423 {
5424 Buf *name = node->data.type_decl.symbol;
5425 add_top_level_decl(g, import, context, node, name);
5426 break;
5427 }
5428 case NodeTypeFnProto:
5429 {
5430 // if the name is missing, we immediately announce an error
5431 Buf *fn_name = node->data.fn_proto.name;
5432 if (buf_len(fn_name) == 0) {
5433 node->data.fn_proto.skip = true;
5434 add_node_error(g, node, buf_sprintf("missing function name"));
5435 break;
5436 }
5437 count_inline_and_var_args(node);
5438
5439 add_top_level_decl(g, import, context, node, fn_name);
5440 break;
5441 }
5442 case NodeTypeUse:
5443 {
5444 TopLevelDecl *tld = get_as_top_level_decl(node);
5445 tld->import = import;
5446 node->block_context = context;
5447 g->use_queue.append(node);
5448 tld->import->use_decls.append(node);
5449 break;
5450 }
5451 case NodeTypeErrorValueDecl:
5452 // error value declarations do not depend on other top level decls
5453 preview_error_value_decl(g, node);
5454 break;
5455 case NodeTypeParamDecl:
5456 case NodeTypeFnDecl:
5457 case NodeTypeReturnExpr:
5458 case NodeTypeDefer:
5459 case NodeTypeBlock:
5460 case NodeTypeBinOpExpr:
5461 case NodeTypeUnwrapErrorExpr:
5462 case NodeTypeFnCallExpr:
5463 case NodeTypeArrayAccessExpr:
5464 case NodeTypeSliceExpr:
5465 case NodeTypeNumberLiteral:
5466 case NodeTypeStringLiteral:
5467 case NodeTypeCharLiteral:
5468 case NodeTypeBoolLiteral:
5469 case NodeTypeNullLiteral:
5470 case NodeTypeUndefinedLiteral:
5471 case NodeTypeZeroesLiteral:
5472 case NodeTypeThisLiteral:
5473 case NodeTypeSymbol:
5474 case NodeTypePrefixOpExpr:
5475 case NodeTypeIfBoolExpr:
5476 case NodeTypeIfVarExpr:
5477 case NodeTypeWhileExpr:
5478 case NodeTypeForExpr:
5479 case NodeTypeSwitchExpr:
5480 case NodeTypeSwitchProng:
5481 case NodeTypeSwitchRange:
5482 case NodeTypeLabel:
5483 case NodeTypeGoto:
5484 case NodeTypeBreak:
5485 case NodeTypeContinue:
5486 case NodeTypeAsmExpr:
5487 case NodeTypeFieldAccessExpr:
5488 case NodeTypeStructField:
5489 case NodeTypeContainerInitExpr:
5490 case NodeTypeStructValueField:
5491 case NodeTypeArrayType:
5492 case NodeTypeErrorType:
5493 case NodeTypeTypeLiteral:
5494 case NodeTypeVarLiteral:
5495 zig_unreachable();
5496 }
5497}
5498
5499static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node) {2594static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node) {
5500 TopLevelDecl *tld = get_as_top_level_decl(dst_use_node);2595 TopLevelDecl *tld = get_as_top_level_decl(dst_use_node);
5501 AstNode *use_target_node = src_use_node->data.use.expr;2596 AstNode *use_target_node = src_use_node->data.use.expr;
...@@ -5565,11 +2660,11 @@ static void resolve_use_decl(CodeGen *g, AstNode *node) {...@@ -5565,11 +2660,11 @@ static void resolve_use_decl(CodeGen *g, AstNode *node) {
5565static void preview_use_decl(CodeGen *g, AstNode *node) {2660static void preview_use_decl(CodeGen *g, AstNode *node) {
5566 assert(node->type == NodeTypeUse);2661 assert(node->type == NodeTypeUse);
5567 TopLevelDecl *tld = get_as_top_level_decl(node);2662 TopLevelDecl *tld = get_as_top_level_decl(node);
5568 TypeTableEntry *use_expr_type = analyze_expression(g, tld->import, tld->import->block_context,2663
5569 g->builtin_types.entry_namespace, node->data.use.expr);2664 IrInstruction *result = analyze_const_value(g, tld->import->block_context, node->data.use.expr,
5570 if (use_expr_type->id == TypeTableEntryIdInvalid) {2665 g->builtin_types.entry_namespace);
2666 if (result->type_entry->id == TypeTableEntryIdInvalid)
5571 tld->import->any_imports_failed = true;2667 tld->import->any_imports_failed = true;
5572 }
5573}2668}
55742669
5575ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,2670ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
src/analyze.hpp-4
...@@ -45,10 +45,6 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,...@@ -45,10 +45,6 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
4545
46AstNode *first_executing_node(AstNode *node);46AstNode *first_executing_node(AstNode *node);
4747
48TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, ImportTableEntry *import,
49 BlockContext *block_context, AstNode *parent_source_node,
50 AstNode **child_nodes, TypeTableEntry **child_types, size_t child_count);
51
5248
53// TODO move these over, these used to be static49// TODO move these over, these used to be static
54bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type);50bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type);
src/ast_render.cpp+5-27
...@@ -261,17 +261,6 @@ static void print_indent(AstRender *ar) {...@@ -261,17 +261,6 @@ static void print_indent(AstRender *ar) {
261 }261 }
262}262}
263263
264static bool is_node_void(AstNode *node) {
265 if (node->type == NodeTypeSymbol) {
266 if (node->data.symbol_expr.override_type_entry) {
267 return node->data.symbol_expr.override_type_entry->id == TypeTableEntryIdVoid;
268 } else if (buf_eql_str(node->data.symbol_expr.symbol, "void")) {
269 return true;
270 }
271 }
272 return false;
273}
274
275static bool is_alpha_under(uint8_t c) {264static bool is_alpha_under(uint8_t c) {
276 return (c >= 'a' && c <= 'z') ||265 return (c >= 'a' && c <= 'z') ||
277 (c >= 'A' && c <= 'Z') || c == '_';266 (c >= 'A' && c <= 'Z') || c == '_';
...@@ -406,10 +395,8 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -406,10 +395,8 @@ static void render_node(AstRender *ar, AstNode *node) {
406 fprintf(ar->f, ")");395 fprintf(ar->f, ")");
407396
408 AstNode *return_type_node = node->data.fn_proto.return_type;397 AstNode *return_type_node = node->data.fn_proto.return_type;
409 if (!is_node_void(return_type_node)) {398 fprintf(ar->f, " -> ");
410 fprintf(ar->f, " -> ");399 render_node(ar, return_type_node);
411 render_node(ar, return_type_node);
412 }
413 break;400 break;
414 }401 }
415 case NodeTypeFnDef:402 case NodeTypeFnDef:
...@@ -521,14 +508,7 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -521,14 +508,7 @@ static void render_node(AstRender *ar, AstNode *node) {
521 break;508 break;
522 }509 }
523 case NodeTypeSymbol:510 case NodeTypeSymbol:
524 {511 print_symbol(ar, node->data.symbol_expr.symbol);
525 TypeTableEntry *override_type = node->data.symbol_expr.override_type_entry;
526 if (override_type) {
527 fprintf(ar->f, "%s", buf_ptr(&override_type->name));
528 } else {
529 print_symbol(ar, node->data.symbol_expr.symbol);
530 }
531 }
532 break;512 break;
533 case NodeTypePrefixOpExpr:513 case NodeTypePrefixOpExpr:
534 {514 {
...@@ -623,10 +603,8 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -623,10 +603,8 @@ static void render_node(AstRender *ar, AstNode *node) {
623 assert(field_node->type == NodeTypeStructField);603 assert(field_node->type == NodeTypeStructField);
624 print_indent(ar);604 print_indent(ar);
625 print_symbol(ar, field_node->data.struct_field.name);605 print_symbol(ar, field_node->data.struct_field.name);
626 if (!is_node_void(field_node->data.struct_field.type)) {606 fprintf(ar->f, ": ");
627 fprintf(ar->f, ": ");607 render_node(ar, field_node->data.struct_field.type);
628 render_node(ar, field_node->data.struct_field.type);
629 }
630 fprintf(ar->f, ",\n");608 fprintf(ar->f, ",\n");
631 }609 }
632610
src/codegen.cpp+1-3
...@@ -2965,6 +2965,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2965,6 +2965,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2965 case IrInstructionIdToPtrType:2965 case IrInstructionIdToPtrType:
2966 case IrInstructionIdPtrTypeChild:2966 case IrInstructionIdPtrTypeChild:
2967 case IrInstructionIdFieldPtr:2967 case IrInstructionIdFieldPtr:
2968 case IrInstructionIdSetFnTest:
2968 zig_unreachable();2969 zig_unreachable();
2969 case IrInstructionIdReturn:2970 case IrInstructionIdReturn:
2970 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);2971 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
...@@ -2996,7 +2997,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2996,7 +2997,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2996 return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction);2997 return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction);
2997 case IrInstructionIdSwitchBr:2998 case IrInstructionIdSwitchBr:
2998 case IrInstructionIdPhi:2999 case IrInstructionIdPhi:
2999 case IrInstructionIdBuiltinCall:
3000 case IrInstructionIdContainerInitList:3000 case IrInstructionIdContainerInitList:
3001 case IrInstructionIdContainerInitFields:3001 case IrInstructionIdContainerInitFields:
3002 case IrInstructionIdReadField:3002 case IrInstructionIdReadField:
...@@ -5303,8 +5303,6 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {...@@ -5303,8 +5303,6 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
5303}5303}
53045304
5305static void get_c_type_node(CodeGen *g, AstNode *type_node, Buf *out_buf) {5305static void get_c_type_node(CodeGen *g, AstNode *type_node, Buf *out_buf) {
5306 assert(type_node->type != NodeTypeSymbol || !type_node->data.symbol_expr.override_type_entry);
5307
5308 Expr *expr = get_resolved_expr(type_node);5306 Expr *expr = get_resolved_expr(type_node);
5309 assert(expr->type_entry);5307 assert(expr->type_entry);
5310 assert(expr->type_entry->id == TypeTableEntryIdMetaType);5308 assert(expr->type_entry->id == TypeTableEntryIdMetaType);
src/ir.cpp+3627-1356
...@@ -149,10 +149,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCall *) {...@@ -149,10 +149,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCall *) {
149 return IrInstructionIdCall;149 return IrInstructionIdCall;
150}150}
151151
152static constexpr IrInstructionId ir_instruction_id(IrInstructionBuiltinCall *) {
153 return IrInstructionIdBuiltinCall;
154}
155
156static constexpr IrInstructionId ir_instruction_id(IrInstructionConst *) {152static constexpr IrInstructionId ir_instruction_id(IrInstructionConst *) {
157 return IrInstructionIdConst;153 return IrInstructionIdConst;
158}154}
...@@ -189,6 +185,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *)...@@ -189,6 +185,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *)
189 return IrInstructionIdPtrTypeChild;185 return IrInstructionIdPtrTypeChild;
190}186}
191187
188static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnTest *) {
189 return IrInstructionIdSetFnTest;
190}
191
192template<typename T>192template<typename T>
193static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {193static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
194 T *special_instruction = allocate<T>(1);194 T *special_instruction = allocate<T>(1);
...@@ -353,7 +353,7 @@ static IrInstruction *ir_build_const_scope(IrBuilder *irb, AstNode *source_node,...@@ -353,7 +353,7 @@ static IrInstruction *ir_build_const_scope(IrBuilder *irb, AstNode *source_node,
353353
354static IrInstruction *ir_build_const_bool(IrBuilder *irb, AstNode *source_node, bool value) {354static IrInstruction *ir_build_const_bool(IrBuilder *irb, AstNode *source_node, bool value) {
355 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);355 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
356 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_block;356 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_bool;
357 const_instruction->base.static_value.ok = true;357 const_instruction->base.static_value.ok = true;
358 const_instruction->base.static_value.data.x_bool = value;358 const_instruction->base.static_value.data.x_bool = value;
359 return &const_instruction->base;359 return &const_instruction->base;
...@@ -505,20 +505,6 @@ static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_inst...@@ -505,20 +505,6 @@ static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_inst
505 return new_instruction;505 return new_instruction;
506}506}
507507
508static IrInstruction *ir_build_builtin_call(IrBuilder *irb, AstNode *source_node,
509 BuiltinFnEntry *fn, IrInstruction **args)
510{
511 IrInstructionBuiltinCall *call_instruction = ir_build_instruction<IrInstructionBuiltinCall>(irb, source_node);
512 call_instruction->fn = fn;
513 call_instruction->args = args;
514
515 for (size_t i = 0; i < fn->param_count; i += 1) {
516 ir_ref_instruction(args[i]);
517 }
518
519 return &call_instruction->base;
520}
521
522static IrInstruction *ir_build_phi(IrBuilder *irb, AstNode *source_node,508static IrInstruction *ir_build_phi(IrBuilder *irb, AstNode *source_node,
523 size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values)509 size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values)
524{510{
...@@ -717,6 +703,19 @@ static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, AstNode *source_no...@@ -717,6 +703,19 @@ static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, AstNode *source_no
717 return &instruction->base;703 return &instruction->base;
718}704}
719705
706static IrInstruction *ir_build_set_fn_test(IrBuilder *irb, AstNode *source_node, IrInstruction *fn_value,
707 IrInstruction *is_test)
708{
709 IrInstructionSetFnTest *instruction = ir_build_instruction<IrInstructionSetFnTest>(irb, source_node);
710 instruction->fn_value = fn_value;
711 instruction->is_test = is_test;
712
713 ir_ref_instruction(fn_value);
714 ir_ref_instruction(is_test);
715
716 return &instruction->base;
717}
718
720//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {719//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
721// size_t result = 0;720// size_t result = 0;
722// while (inner_block != outer_block) {721// while (inner_block != outer_block) {
...@@ -1066,10 +1065,6 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstN...@@ -1066,10 +1065,6 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstN
1066static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, LValPurpose lval) {1065static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, LValPurpose lval) {
1067 assert(node->type == NodeTypeSymbol);1066 assert(node->type == NodeTypeSymbol);
10681067
1069 if (node->data.symbol_expr.override_type_entry) {
1070 zig_panic("TODO have parseh directly generate IR");
1071 }
1072
1073 Buf *variable_name = node->data.symbol_expr.symbol;1068 Buf *variable_name = node->data.symbol_expr.symbol;
10741069
1075 auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name);1070 auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name);
...@@ -1163,26 +1158,71 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {...@@ -1163,26 +1158,71 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
11631158
1164 builtin_fn->ref_count += 1;1159 builtin_fn->ref_count += 1;
11651160
1166 if (builtin_fn->id == BuiltinFnIdUnreachable) {1161 switch (builtin_fn->id) {
1167 return ir_build_unreachable(irb, node);1162 case BuiltinFnIdInvalid:
1168 } else if (builtin_fn->id == BuiltinFnIdTypeof) {1163 zig_unreachable();
1169 AstNode *arg_node = node->data.fn_call_expr.params.at(0);1164 case BuiltinFnIdUnreachable:
1170 IrInstruction *arg = ir_gen_node(irb, arg_node, node->block_context);1165 return ir_build_unreachable(irb, node);
1171 if (arg == irb->codegen->invalid_instruction)1166 case BuiltinFnIdTypeof:
1172 return arg;1167 {
1173 return ir_build_typeof(irb, node, arg);1168 AstNode *arg_node = node->data.fn_call_expr.params.at(0);
1174 }1169 IrInstruction *arg = ir_gen_node(irb, arg_node, node->block_context);
1170 if (arg == irb->codegen->invalid_instruction)
1171 return arg;
1172 return ir_build_typeof(irb, node, arg);
1173 }
1174 case BuiltinFnIdSetFnTest:
1175 {
1176 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
1177 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, node->block_context);
1178 if (arg0_value == irb->codegen->invalid_instruction)
1179 return arg0_value;
11751180
1176 IrInstruction **args = allocate<IrInstruction *>(actual_param_count);1181 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
1177 for (size_t i = 0; i < actual_param_count; i += 1) {1182 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, node->block_context);
1178 AstNode *arg_node = node->data.fn_call_expr.params.at(i);1183 if (arg1_value == irb->codegen->invalid_instruction)
1179 IrInstruction *arg = ir_gen_node(irb, arg_node, node->block_context);1184 return arg1_value;
1180 if (arg == irb->codegen->invalid_instruction)
1181 return arg;
1182 args[i] = arg;
1183 }
11841185
1185 return ir_build_builtin_call(irb, node, builtin_fn, args);1186 return ir_build_set_fn_test(irb, node, arg0_value, arg1_value);
1187 }
1188 case BuiltinFnIdMemcpy:
1189 case BuiltinFnIdMemset:
1190 case BuiltinFnIdSizeof:
1191 case BuiltinFnIdAlignof:
1192 case BuiltinFnIdMaxValue:
1193 case BuiltinFnIdMinValue:
1194 case BuiltinFnIdMemberCount:
1195 case BuiltinFnIdAddWithOverflow:
1196 case BuiltinFnIdSubWithOverflow:
1197 case BuiltinFnIdMulWithOverflow:
1198 case BuiltinFnIdShlWithOverflow:
1199 case BuiltinFnIdCInclude:
1200 case BuiltinFnIdCDefine:
1201 case BuiltinFnIdCUndef:
1202 case BuiltinFnIdCompileVar:
1203 case BuiltinFnIdCompileErr:
1204 case BuiltinFnIdConstEval:
1205 case BuiltinFnIdCtz:
1206 case BuiltinFnIdClz:
1207 case BuiltinFnIdImport:
1208 case BuiltinFnIdCImport:
1209 case BuiltinFnIdErrName:
1210 case BuiltinFnIdBreakpoint:
1211 case BuiltinFnIdReturnAddress:
1212 case BuiltinFnIdFrameAddress:
1213 case BuiltinFnIdEmbedFile:
1214 case BuiltinFnIdCmpExchange:
1215 case BuiltinFnIdFence:
1216 case BuiltinFnIdDivExact:
1217 case BuiltinFnIdTruncate:
1218 case BuiltinFnIdIntType:
1219 case BuiltinFnIdSetFnVisible:
1220 case BuiltinFnIdSetFnStaticEval:
1221 case BuiltinFnIdSetFnNoInline:
1222 case BuiltinFnIdSetDebugSafety:
1223 zig_panic("TODO IR gen more builtin functions");
1224 }
1225 zig_unreachable();
1186}1226}
11871227
1188static IrInstruction *ir_gen_fn_call(IrBuilder *irb, AstNode *node) {1228static IrInstruction *ir_gen_fn_call(IrBuilder *irb, AstNode *node) {
...@@ -2044,6 +2084,53 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value...@@ -2044,6 +2084,53 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value
2044 return const_val->data.x_type;2084 return const_val->data.x_type;
2045}2085}
20462086
2087static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out) {
2088 if (bool_value == ira->codegen->invalid_instruction)
2089 return false;
2090
2091 if (bool_value->type_entry->id == TypeTableEntryIdInvalid)
2092 return false;
2093
2094 if (bool_value->type_entry->id != TypeTableEntryIdBool) {
2095 add_node_error(ira->codegen, bool_value->source_node,
2096 buf_sprintf("expected type 'bool', found '%s'", buf_ptr(&bool_value->type_entry->name)));
2097 return false;
2098 }
2099
2100 ConstExprValue *const_val = &bool_value->static_value;
2101 if (!const_val->ok) {
2102 add_node_error(ira->codegen, bool_value->source_node,
2103 buf_sprintf("unable to evaluate constant expression"));
2104 return false;
2105 }
2106
2107 *out = const_val->data.x_bool;
2108 return true;
2109}
2110
2111static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
2112 if (fn_value == ira->codegen->invalid_instruction)
2113 return nullptr;
2114
2115 if (fn_value->type_entry->id == TypeTableEntryIdInvalid)
2116 return nullptr;
2117
2118 if (fn_value->type_entry->id != TypeTableEntryIdFn) {
2119 add_node_error(ira->codegen, fn_value->source_node,
2120 buf_sprintf("expected function type, found '%s'", buf_ptr(&fn_value->type_entry->name)));
2121 return nullptr;
2122 }
2123
2124 ConstExprValue *const_val = &fn_value->static_value;
2125 if (!const_val->ok) {
2126 add_node_error(ira->codegen, fn_value->source_node,
2127 buf_sprintf("unable to evaluate constant expression"));
2128 return nullptr;
2129 }
2130
2131 return const_val->data.x_fn;
2132}
2133
2047static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,2134static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
2048 IrInstruction *dest_type, IrInstruction *value)2135 IrInstruction *dest_type, IrInstruction *value)
2049{2136{
...@@ -2837,11 +2924,18 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction...@@ -2837,11 +2924,18 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
2837 } else if (fn_ref->type_entry->id == TypeTableEntryIdFn) {2924 } else if (fn_ref->type_entry->id == TypeTableEntryIdFn) {
2838 // TODO fully port over the fn call analyze code to IR2925 // TODO fully port over the fn call analyze code to IR
2839 FnTableEntry *fn_table_entry = fn_ref->static_value.data.x_fn;2926 FnTableEntry *fn_table_entry = fn_ref->static_value.data.x_fn;
2927 TypeTableEntry *fn_type = fn_table_entry->type_entry;
2928
2929 IrInstruction **casted_args = allocate<IrInstruction *>(call_instruction->arg_count);
2930 for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
2931 TypeTableEntry *param_type = fn_type->data.fn.fn_type_id.param_info[i].type;
2932 IrInstruction *old_arg = call_instruction->args[i]->other;
2933 casted_args[i] = ir_get_casted_value(ira, old_arg, param_type);
2934 }
28402935
2841 ir_build_call_from(&ira->new_irb, &call_instruction->base,2936 ir_build_call_from(&ira->new_irb, &call_instruction->base,
2842 call_instruction->fn, call_instruction->arg_count, call_instruction->args);2937 call_instruction->fn, call_instruction->arg_count, casted_args);
28432938
2844 TypeTableEntry *fn_type = fn_table_entry->type_entry;
2845 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;2939 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
2846 return return_type;2940 return return_type;
2847 } else {2941 } else {
...@@ -3075,1121 +3169,8 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio...@@ -3075,1121 +3169,8 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
3075 zig_unreachable();3169 zig_unreachable();
3076}3170}
30773171
3078//static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,3172static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) {
3079// AstNode *node, const char *err_format, bool is_max)3173 IrBasicBlock *old_dest_block = br_instruction->dest_block;
3080//{
3081// assert(node->type == NodeTypeFnCallExpr);
3082// assert(node->data.fn_call_expr.params.length == 1);
3083//
3084// AstNode *type_node = node->data.fn_call_expr.params.at(0);
3085// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
3086//
3087// if (type_entry->id == TypeTableEntryIdInvalid) {
3088// return g->builtin_types.entry_invalid;
3089// } else if (type_entry->id == TypeTableEntryIdInt) {
3090// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
3091// return g->builtin_types.entry_num_lit_int;
3092// } else if (type_entry->id == TypeTableEntryIdFloat) {
3093// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
3094// return g->builtin_types.entry_num_lit_float;
3095// } else if (type_entry->id == TypeTableEntryIdBool) {
3096// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
3097// return type_entry;
3098// } else {
3099// add_node_error(g, node,
3100// buf_sprintf(err_format, buf_ptr(&type_entry->name)));
3101// return g->builtin_types.entry_invalid;
3102// }
3103//}
3104
3105//static TypeTableEntry *analyze_import(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3106// AstNode *node)
3107//{
3108// assert(node->type == NodeTypeFnCallExpr);
3109//
3110// if (context->fn_entry) {
3111// add_node_error(g, node, buf_sprintf("@import invalid inside function bodies"));
3112// return g->builtin_types.entry_invalid;
3113// }
3114//
3115// AstNode *first_param_node = node->data.fn_call_expr.params.at(0);
3116// Buf *import_target_str = resolve_const_expr_str(g, import, context, first_param_node->parent_field);
3117// if (!import_target_str) {
3118// return g->builtin_types.entry_invalid;
3119// }
3120//
3121// Buf *import_target_path;
3122// Buf *search_dir;
3123// assert(import->package);
3124// PackageTableEntry *target_package;
3125// auto package_entry = import->package->package_table.maybe_get(import_target_str);
3126// if (package_entry) {
3127// target_package = package_entry->value;
3128// import_target_path = &target_package->root_src_path;
3129// search_dir = &target_package->root_src_dir;
3130// } else {
3131// // try it as a filename
3132// target_package = import->package;
3133// import_target_path = import_target_str;
3134// search_dir = &import->package->root_src_dir;
3135// }
3136//
3137// Buf full_path = BUF_INIT;
3138// os_path_join(search_dir, import_target_path, &full_path);
3139//
3140// Buf *import_code = buf_alloc();
3141// Buf *abs_full_path = buf_alloc();
3142// int err;
3143// if ((err = os_path_real(&full_path, abs_full_path))) {
3144// if (err == ErrorFileNotFound) {
3145// add_node_error(g, node,
3146// buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
3147// return g->builtin_types.entry_invalid;
3148// } else {
3149// g->error_during_imports = true;
3150// add_node_error(g, node,
3151// buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
3152// return g->builtin_types.entry_invalid;
3153// }
3154// }
3155//
3156// auto import_entry = g->import_table.maybe_get(abs_full_path);
3157// if (import_entry) {
3158// return resolve_expr_const_val_as_import(g, node, import_entry->value);
3159// }
3160//
3161// if ((err = os_fetch_file_path(abs_full_path, import_code))) {
3162// if (err == ErrorFileNotFound) {
3163// add_node_error(g, node,
3164// buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
3165// return g->builtin_types.entry_invalid;
3166// } else {
3167// add_node_error(g, node,
3168// buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
3169// return g->builtin_types.entry_invalid;
3170// }
3171// }
3172// ImportTableEntry *target_import = add_source_file(g, target_package,
3173// abs_full_path, search_dir, import_target_path, import_code);
3174//
3175// scan_decls(g, target_import, target_import->block_context, target_import->root);
3176//
3177// return resolve_expr_const_val_as_import(g, node, target_import);
3178//}
3179//
3180//static TypeTableEntry *analyze_c_import(CodeGen *g, ImportTableEntry *parent_import,
3181// BlockContext *parent_context, AstNode *node)
3182//{
3183// assert(node->type == NodeTypeFnCallExpr);
3184//
3185// if (parent_context->fn_entry) {
3186// add_node_error(g, node, buf_sprintf("@c_import invalid inside function bodies"));
3187// return g->builtin_types.entry_invalid;
3188// }
3189//
3190// AstNode *block_node = node->data.fn_call_expr.params.at(0);
3191//
3192// BlockContext *child_context = new_block_context(node, parent_context);
3193// child_context->c_import_buf = buf_alloc();
3194//
3195// TypeTableEntry *resolved_type = analyze_expression(g, parent_import, child_context,
3196// g->builtin_types.entry_void, block_node);
3197//
3198// if (resolved_type->id == TypeTableEntryIdInvalid) {
3199// return resolved_type;
3200// }
3201//
3202// find_libc_include_path(g);
3203//
3204// ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
3205// child_import->c_import_node = node;
3206//
3207// ZigList<ErrorMsg *> errors = {0};
3208//
3209// int err;
3210// if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g, node))) {
3211// zig_panic("unable to parse h file: %s\n", err_str(err));
3212// }
3213//
3214// if (errors.length > 0) {
3215// ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed"));
3216// for (size_t i = 0; i < errors.length; i += 1) {
3217// ErrorMsg *err_msg = errors.at(i);
3218// err_msg_add_note(parent_err_msg, err_msg);
3219// }
3220//
3221// return g->builtin_types.entry_invalid;
3222// }
3223//
3224// if (g->verbose) {
3225// fprintf(stderr, "\nc_import:\n");
3226// fprintf(stderr, "-----------\n");
3227// ast_render(stderr, child_import->root, 4);
3228// }
3229//
3230// child_import->di_file = parent_import->di_file;
3231// child_import->block_context = new_block_context(child_import->root, nullptr);
3232//
3233// scan_decls(g, child_import, child_import->block_context, child_import->root);
3234// return resolve_expr_const_val_as_import(g, node, child_import);
3235//}
3236//
3237//static TypeTableEntry *analyze_err_name(CodeGen *g, ImportTableEntry *import,
3238// BlockContext *context, AstNode *node)
3239//{
3240// assert(node->type == NodeTypeFnCallExpr);
3241//
3242// AstNode *err_value = node->data.fn_call_expr.params.at(0);
3243// TypeTableEntry *resolved_type = analyze_expression(g, import, context,
3244// g->builtin_types.entry_pure_error, err_value);
3245//
3246// if (resolved_type->id == TypeTableEntryIdInvalid) {
3247// return resolved_type;
3248// }
3249//
3250// g->generate_error_name_table = true;
3251//
3252// TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);
3253// return str_type;
3254//}
3255//
3256//static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import,
3257// BlockContext *context, AstNode *node)
3258//{
3259// assert(node->type == NodeTypeFnCallExpr);
3260//
3261// AstNode **first_param_node = &node->data.fn_call_expr.params.at(0);
3262// Buf *rel_file_path = resolve_const_expr_str(g, import, context, first_param_node);
3263// if (!rel_file_path) {
3264// return g->builtin_types.entry_invalid;
3265// }
3266//
3267// // figure out absolute path to resource
3268// Buf source_dir_path = BUF_INIT;
3269// os_path_dirname(import->path, &source_dir_path);
3270//
3271// Buf file_path = BUF_INIT;
3272// os_path_resolve(&source_dir_path, rel_file_path, &file_path);
3273//
3274// // load from file system into const expr
3275// Buf file_contents = BUF_INIT;
3276// int err;
3277// if ((err = os_fetch_file_path(&file_path, &file_contents))) {
3278// if (err == ErrorFileNotFound) {
3279// add_node_error(g, node,
3280// buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));
3281// return g->builtin_types.entry_invalid;
3282// } else {
3283// add_node_error(g, node,
3284// buf_sprintf("unable to open '%s': %s", buf_ptr(&file_path), err_str(err)));
3285// return g->builtin_types.entry_invalid;
3286// }
3287// }
3288//
3289// // TODO add dependency on the file we embedded so that we know if it changes
3290// // we'll have to invalidate the cache
3291//
3292// return resolve_expr_const_val_as_string_lit(g, node, &file_contents);
3293//}
3294//
3295//static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,
3296// BlockContext *context, AstNode *node)
3297//{
3298// assert(node->type == NodeTypeFnCallExpr);
3299//
3300// AstNode **ptr_arg = &node->data.fn_call_expr.params.at(0);
3301// AstNode **cmp_arg = &node->data.fn_call_expr.params.at(1);
3302// AstNode **new_arg = &node->data.fn_call_expr.params.at(2);
3303// AstNode **success_order_arg = &node->data.fn_call_expr.params.at(3);
3304// AstNode **failure_order_arg = &node->data.fn_call_expr.params.at(4);
3305//
3306// TypeTableEntry *ptr_type = analyze_expression(g, import, context, nullptr, *ptr_arg);
3307// if (ptr_type->id == TypeTableEntryIdInvalid) {
3308// return g->builtin_types.entry_invalid;
3309// } else if (ptr_type->id != TypeTableEntryIdPointer) {
3310// add_node_error(g, *ptr_arg,
3311// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&ptr_type->name)));
3312// return g->builtin_types.entry_invalid;
3313// }
3314//
3315// TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
3316// TypeTableEntry *cmp_type = analyze_expression(g, import, context, child_type, *cmp_arg);
3317// TypeTableEntry *new_type = analyze_expression(g, import, context, child_type, *new_arg);
3318//
3319// TypeTableEntry *success_order_type = analyze_expression(g, import, context,
3320// g->builtin_types.entry_atomic_order_enum, *success_order_arg);
3321// TypeTableEntry *failure_order_type = analyze_expression(g, import, context,
3322// g->builtin_types.entry_atomic_order_enum, *failure_order_arg);
3323//
3324// if (cmp_type->id == TypeTableEntryIdInvalid ||
3325// new_type->id == TypeTableEntryIdInvalid ||
3326// success_order_type->id == TypeTableEntryIdInvalid ||
3327// failure_order_type->id == TypeTableEntryIdInvalid)
3328// {
3329// return g->builtin_types.entry_invalid;
3330// }
3331//
3332// ConstExprValue *success_order_val = &get_resolved_expr(*success_order_arg)->const_val;
3333// ConstExprValue *failure_order_val = &get_resolved_expr(*failure_order_arg)->const_val;
3334// if (!success_order_val->ok) {
3335// add_node_error(g, *success_order_arg, buf_sprintf("unable to evaluate constant expression"));
3336// return g->builtin_types.entry_invalid;
3337// } else if (!failure_order_val->ok) {
3338// add_node_error(g, *failure_order_arg, buf_sprintf("unable to evaluate constant expression"));
3339// return g->builtin_types.entry_invalid;
3340// }
3341//
3342// if (success_order_val->data.x_enum.tag < AtomicOrderMonotonic) {
3343// add_node_error(g, *success_order_arg,
3344// buf_sprintf("success atomic ordering must be Monotonic or stricter"));
3345// return g->builtin_types.entry_invalid;
3346// }
3347// if (failure_order_val->data.x_enum.tag < AtomicOrderMonotonic) {
3348// add_node_error(g, *failure_order_arg,
3349// buf_sprintf("failure atomic ordering must be Monotonic or stricter"));
3350// return g->builtin_types.entry_invalid;
3351// }
3352// if (failure_order_val->data.x_enum.tag > success_order_val->data.x_enum.tag) {
3353// add_node_error(g, *failure_order_arg,
3354// buf_sprintf("failure atomic ordering must be no stricter than success"));
3355// return g->builtin_types.entry_invalid;
3356// }
3357// if (failure_order_val->data.x_enum.tag == AtomicOrderRelease ||
3358// failure_order_val->data.x_enum.tag == AtomicOrderAcqRel)
3359// {
3360// add_node_error(g, *failure_order_arg,
3361// buf_sprintf("failure atomic ordering must not be Release or AcqRel"));
3362// return g->builtin_types.entry_invalid;
3363// }
3364//
3365// return g->builtin_types.entry_bool;
3366//}
3367//
3368//static TypeTableEntry *analyze_fence(CodeGen *g, ImportTableEntry *import,
3369// BlockContext *context, AstNode *node)
3370//{
3371// assert(node->type == NodeTypeFnCallExpr);
3372//
3373// AstNode **atomic_order_arg = &node->data.fn_call_expr.params.at(0);
3374// TypeTableEntry *atomic_order_type = analyze_expression(g, import, context,
3375// g->builtin_types.entry_atomic_order_enum, *atomic_order_arg);
3376//
3377// if (atomic_order_type->id == TypeTableEntryIdInvalid) {
3378// return g->builtin_types.entry_invalid;
3379// }
3380//
3381// ConstExprValue *atomic_order_val = &get_resolved_expr(*atomic_order_arg)->const_val;
3382//
3383// if (!atomic_order_val->ok) {
3384// add_node_error(g, *atomic_order_arg, buf_sprintf("unable to evaluate constant expression"));
3385// return g->builtin_types.entry_invalid;
3386// }
3387//
3388// return g->builtin_types.entry_void;
3389//}
3390//
3391//static TypeTableEntry *analyze_div_exact(CodeGen *g, ImportTableEntry *import,
3392// BlockContext *context, AstNode *node)
3393//{
3394// assert(node->type == NodeTypeFnCallExpr);
3395//
3396// AstNode **op1 = &node->data.fn_call_expr.params.at(0);
3397// AstNode **op2 = &node->data.fn_call_expr.params.at(1);
3398//
3399// TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1);
3400// TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2);
3401//
3402// AstNode *op_nodes[] = {*op1, *op2};
3403// TypeTableEntry *op_types[] = {op1_type, op2_type};
3404// TypeTableEntry *result_type = resolve_peer_type_compatibility(g, import, context, node,
3405// op_nodes, op_types, 2);
3406//
3407// if (result_type->id == TypeTableEntryIdInvalid) {
3408// return g->builtin_types.entry_invalid;
3409// } else if (result_type->id == TypeTableEntryIdInt) {
3410// return result_type;
3411// } else if (result_type->id == TypeTableEntryIdNumLitInt) {
3412// // check for division by zero
3413// // check for non exact division
3414// zig_panic("TODO");
3415// } else {
3416// add_node_error(g, node,
3417// buf_sprintf("expected integer type, got '%s'", buf_ptr(&result_type->name)));
3418// return g->builtin_types.entry_invalid;
3419// }
3420//}
3421//
3422//static TypeTableEntry *analyze_truncate(CodeGen *g, ImportTableEntry *import,
3423// BlockContext *context, AstNode *node)
3424//{
3425// assert(node->type == NodeTypeFnCallExpr);
3426//
3427// AstNode **op1 = &node->data.fn_call_expr.params.at(0);
3428// AstNode **op2 = &node->data.fn_call_expr.params.at(1);
3429//
3430// TypeTableEntry *dest_type = analyze_type_expr(g, import, context, *op1);
3431// TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, *op2);
3432//
3433// if (dest_type->id == TypeTableEntryIdInvalid || src_type->id == TypeTableEntryIdInvalid) {
3434// return g->builtin_types.entry_invalid;
3435// } else if (dest_type->id != TypeTableEntryIdInt) {
3436// add_node_error(g, *op1,
3437// buf_sprintf("expected integer type, got '%s'", buf_ptr(&dest_type->name)));
3438// return g->builtin_types.entry_invalid;
3439// } else if (src_type->id != TypeTableEntryIdInt) {
3440// add_node_error(g, *op2,
3441// buf_sprintf("expected integer type, got '%s'", buf_ptr(&src_type->name)));
3442// return g->builtin_types.entry_invalid;
3443// } else if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
3444// const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
3445// add_node_error(g, *op2,
3446// buf_sprintf("expected %s integer type, got '%s'", sign_str, buf_ptr(&src_type->name)));
3447// return g->builtin_types.entry_invalid;
3448// } else if (src_type->data.integral.bit_count <= dest_type->data.integral.bit_count) {
3449// add_node_error(g, *op2,
3450// buf_sprintf("type '%s' has same or fewer bits than destination type '%s'",
3451// buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
3452// return g->builtin_types.entry_invalid;
3453// }
3454//
3455// // TODO const expr eval
3456//
3457// return dest_type;
3458//}
3459//
3460//static TypeTableEntry *analyze_compile_err(CodeGen *g, ImportTableEntry *import,
3461// BlockContext *context, AstNode *node)
3462//{
3463// AstNode *first_param_node = node->data.fn_call_expr.params.at(0);
3464// Buf *err_msg = resolve_const_expr_str(g, import, context, first_param_node->parent_field);
3465// if (!err_msg) {
3466// return g->builtin_types.entry_invalid;
3467// }
3468//
3469// add_node_error(g, node, err_msg);
3470//
3471// return g->builtin_types.entry_invalid;
3472//}
3473//
3474//static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import,
3475// BlockContext *context, AstNode *node)
3476//{
3477// AstNode **is_signed_node = &node->data.fn_call_expr.params.at(0);
3478// AstNode **bit_count_node = &node->data.fn_call_expr.params.at(1);
3479//
3480// TypeTableEntry *bool_type = g->builtin_types.entry_bool;
3481// TypeTableEntry *usize_type = g->builtin_types.entry_usize;
3482// TypeTableEntry *is_signed_type = analyze_expression(g, import, context, bool_type, *is_signed_node);
3483// TypeTableEntry *bit_count_type = analyze_expression(g, import, context, usize_type, *bit_count_node);
3484//
3485// if (is_signed_type->id == TypeTableEntryIdInvalid ||
3486// bit_count_type->id == TypeTableEntryIdInvalid)
3487// {
3488// return g->builtin_types.entry_invalid;
3489// }
3490//
3491// ConstExprValue *is_signed_val = &get_resolved_expr(*is_signed_node)->const_val;
3492// ConstExprValue *bit_count_val = &get_resolved_expr(*bit_count_node)->const_val;
3493//
3494// AstNode *bad_node = nullptr;
3495// if (!is_signed_val->ok) {
3496// bad_node = *is_signed_node;
3497// } else if (!bit_count_val->ok) {
3498// bad_node = *bit_count_node;
3499// }
3500// if (bad_node) {
3501// add_node_error(g, bad_node, buf_sprintf("unable to evaluate constant expression"));
3502// return g->builtin_types.entry_invalid;
3503// }
3504//
3505// bool depends_on_compile_var = is_signed_val->depends_on_compile_var || bit_count_val->depends_on_compile_var;
3506//
3507// TypeTableEntry *int_type = get_int_type(g, is_signed_val->data.x_bool,
3508// bit_count_val->data.x_bignum.data.x_uint);
3509// return resolve_expr_const_val_as_type(g, node, int_type, depends_on_compile_var);
3510//
3511//}
3512//
3513//static TypeTableEntry *analyze_set_fn_test(CodeGen *g, ImportTableEntry *import,
3514// BlockContext *context, AstNode *node)
3515//{
3516// AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
3517// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
3518//
3519// FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
3520// if (!fn_entry) {
3521// return g->builtin_types.entry_invalid;
3522// }
3523//
3524// bool ok = resolve_const_expr_bool(g, import, context, value_node, &fn_entry->is_test);
3525// if (!ok) {
3526// return g->builtin_types.entry_invalid;
3527// }
3528//
3529// if (fn_entry->fn_test_set_node) {
3530// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function test attribute set twice"));
3531// add_error_note(g, msg, fn_entry->fn_test_set_node, buf_sprintf("first set here"));
3532// return g->builtin_types.entry_invalid;
3533// }
3534// fn_entry->fn_test_set_node = node;
3535//
3536// g->test_fn_count += 1;
3537// return g->builtin_types.entry_void;
3538//}
3539//
3540//static TypeTableEntry *analyze_set_fn_no_inline(CodeGen *g, ImportTableEntry *import,
3541// BlockContext *context, AstNode *node)
3542//{
3543// AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
3544// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
3545//
3546// FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
3547// if (!fn_entry) {
3548// return g->builtin_types.entry_invalid;
3549// }
3550//
3551// bool is_noinline;
3552// bool ok = resolve_const_expr_bool(g, import, context, value_node, &is_noinline);
3553// if (!ok) {
3554// return g->builtin_types.entry_invalid;
3555// }
3556//
3557// if (fn_entry->fn_no_inline_set_node) {
3558// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function no inline attribute set twice"));
3559// add_error_note(g, msg, fn_entry->fn_no_inline_set_node, buf_sprintf("first set here"));
3560// return g->builtin_types.entry_invalid;
3561// }
3562// fn_entry->fn_no_inline_set_node = node;
3563//
3564// if (fn_entry->fn_inline == FnInlineAlways) {
3565// add_node_error(g, node, buf_sprintf("function is both inline and noinline"));
3566// fn_entry->proto_node->data.fn_proto.skip = true;
3567// return g->builtin_types.entry_invalid;
3568// } else if (is_noinline) {
3569// fn_entry->fn_inline = FnInlineNever;
3570// }
3571//
3572// return g->builtin_types.entry_void;
3573//}
3574//
3575//static TypeTableEntry *analyze_set_fn_static_eval(CodeGen *g, ImportTableEntry *import,
3576// BlockContext *context, AstNode *node)
3577//{
3578// AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
3579// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
3580//
3581// FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
3582// if (!fn_entry) {
3583// return g->builtin_types.entry_invalid;
3584// }
3585//
3586// bool want_static_eval;
3587// bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_static_eval);
3588// if (!ok) {
3589// return g->builtin_types.entry_invalid;
3590// }
3591//
3592// if (fn_entry->fn_static_eval_set_node) {
3593// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function static eval attribute set twice"));
3594// add_error_note(g, msg, fn_entry->fn_static_eval_set_node, buf_sprintf("first set here"));
3595// return g->builtin_types.entry_invalid;
3596// }
3597// fn_entry->fn_static_eval_set_node = node;
3598//
3599// if (want_static_eval && !context->fn_entry->is_pure) {
3600// add_node_error(g, node, buf_sprintf("attribute appears too late within function"));
3601// return g->builtin_types.entry_invalid;
3602// }
3603//
3604// if (want_static_eval) {
3605// fn_entry->want_pure = WantPureTrue;
3606// fn_entry->want_pure_attr_node = node;
3607// } else {
3608// fn_entry->want_pure = WantPureFalse;
3609// fn_entry->is_pure = false;
3610// }
3611//
3612// return g->builtin_types.entry_void;
3613//}
3614//
3615//static TypeTableEntry *analyze_set_fn_visible(CodeGen *g, ImportTableEntry *import,
3616// BlockContext *context, AstNode *node)
3617//{
3618// AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
3619// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
3620//
3621// FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
3622// if (!fn_entry) {
3623// return g->builtin_types.entry_invalid;
3624// }
3625//
3626// bool want_export;
3627// bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_export);
3628// if (!ok) {
3629// return g->builtin_types.entry_invalid;
3630// }
3631//
3632// if (fn_entry->fn_export_set_node) {
3633// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function visibility set twice"));
3634// add_error_note(g, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here"));
3635// return g->builtin_types.entry_invalid;
3636// }
3637// fn_entry->fn_export_set_node = node;
3638//
3639// AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto;
3640// if (fn_proto->top_level_decl.visib_mod != VisibModExport) {
3641// ErrorMsg *msg = add_node_error(g, node,
3642// buf_sprintf("function must be marked export to set function visibility"));
3643// add_error_note(g, msg, fn_entry->proto_node, buf_sprintf("function declared here"));
3644// return g->builtin_types.entry_void;
3645// }
3646// if (!want_export) {
3647// fn_proto->top_level_decl.visib_mod = VisibModPub;
3648// }
3649//
3650// return g->builtin_types.entry_void;
3651//}
3652//
3653//static TypeTableEntry *analyze_set_debug_safety(CodeGen *g, ImportTableEntry *import,
3654// BlockContext *parent_context, AstNode *node)
3655//{
3656// AstNode **target_node = &node->data.fn_call_expr.params.at(0);
3657// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
3658//
3659// TypeTableEntry *target_type = analyze_expression(g, import, parent_context, nullptr, *target_node);
3660// BlockContext *target_context;
3661// ConstExprValue *const_val = &get_resolved_expr(*target_node)->const_val;
3662// if (target_type->id == TypeTableEntryIdInvalid) {
3663// return g->builtin_types.entry_invalid;
3664// }
3665// if (!const_val->ok) {
3666// add_node_error(g, *target_node, buf_sprintf("unable to evaluate constant expression"));
3667// return g->builtin_types.entry_invalid;
3668// }
3669// if (target_type->id == TypeTableEntryIdBlock) {
3670// target_context = const_val->data.x_block;
3671// } else if (target_type->id == TypeTableEntryIdFn) {
3672// target_context = const_val->data.x_fn->fn_def_node->data.fn_def.block_context;
3673// } else if (target_type->id == TypeTableEntryIdMetaType) {
3674// TypeTableEntry *type_arg = const_val->data.x_type;
3675// if (type_arg->id == TypeTableEntryIdStruct) {
3676// target_context = type_arg->data.structure.block_context;
3677// } else if (type_arg->id == TypeTableEntryIdEnum) {
3678// target_context = type_arg->data.enumeration.block_context;
3679// } else if (type_arg->id == TypeTableEntryIdUnion) {
3680// target_context = type_arg->data.unionation.block_context;
3681// } else {
3682// add_node_error(g, *target_node,
3683// buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name)));
3684// return g->builtin_types.entry_invalid;
3685// }
3686// } else {
3687// add_node_error(g, *target_node,
3688// buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name)));
3689// return g->builtin_types.entry_invalid;
3690// }
3691//
3692// bool want_debug_safety;
3693// bool ok = resolve_const_expr_bool(g, import, parent_context, value_node, &want_debug_safety);
3694// if (!ok) {
3695// return g->builtin_types.entry_invalid;
3696// }
3697//
3698// if (target_context->safety_set_node) {
3699// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("debug safety for scope set twice"));
3700// add_error_note(g, msg, target_context->safety_set_node, buf_sprintf("first set here"));
3701// return g->builtin_types.entry_invalid;
3702// }
3703// target_context->safety_set_node = node;
3704//
3705// target_context->safety_off = !want_debug_safety;
3706//
3707// return g->builtin_types.entry_void;
3708//}
3709
3710
3711//static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3712// TypeTableEntry *expected_type, AstNode *node)
3713//{
3714//
3715// switch (builtin_fn->id) {
3716// case BuiltinFnIdInvalid:
3717// zig_unreachable();
3718// case BuiltinFnIdAddWithOverflow:
3719// case BuiltinFnIdSubWithOverflow:
3720// case BuiltinFnIdMulWithOverflow:
3721// case BuiltinFnIdShlWithOverflow:
3722// {
3723// AstNode *type_node = node->data.fn_call_expr.params.at(0);
3724// TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node);
3725// if (int_type->id == TypeTableEntryIdInvalid) {
3726// return g->builtin_types.entry_bool;
3727// } else if (int_type->id == TypeTableEntryIdInt) {
3728// AstNode *op1_node = node->data.fn_call_expr.params.at(1);
3729// AstNode *op2_node = node->data.fn_call_expr.params.at(2);
3730// AstNode *result_node = node->data.fn_call_expr.params.at(3);
3731//
3732// analyze_expression(g, import, context, int_type, op1_node);
3733// analyze_expression(g, import, context, int_type, op2_node);
3734// analyze_expression(g, import, context, get_pointer_to_type(g, int_type, false),
3735// result_node);
3736// } else {
3737// add_node_error(g, type_node,
3738// buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name)));
3739// }
3740//
3741// // TODO constant expression evaluation
3742//
3743// return g->builtin_types.entry_bool;
3744// }
3745// case BuiltinFnIdMemcpy:
3746// {
3747// AstNode *dest_node = node->data.fn_call_expr.params.at(0);
3748// AstNode *src_node = node->data.fn_call_expr.params.at(1);
3749// AstNode *len_node = node->data.fn_call_expr.params.at(2);
3750// TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node);
3751// TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, src_node);
3752// analyze_expression(g, import, context, builtin_fn->param_types[2], len_node);
3753//
3754// if (dest_type->id != TypeTableEntryIdInvalid &&
3755// dest_type->id != TypeTableEntryIdPointer)
3756// {
3757// add_node_error(g, dest_node,
3758// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
3759// }
3760//
3761// if (src_type->id != TypeTableEntryIdInvalid &&
3762// src_type->id != TypeTableEntryIdPointer)
3763// {
3764// add_node_error(g, src_node,
3765// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&src_type->name)));
3766// }
3767//
3768// if (dest_type->id == TypeTableEntryIdPointer &&
3769// src_type->id == TypeTableEntryIdPointer)
3770// {
3771// uint64_t dest_align = get_memcpy_align(g, dest_type->data.pointer.child_type);
3772// uint64_t src_align = get_memcpy_align(g, src_type->data.pointer.child_type);
3773// if (dest_align != src_align) {
3774// add_node_error(g, dest_node, buf_sprintf(
3775// "misaligned memcpy, '%s' has alignment '%" PRIu64 ", '%s' has alignment %" PRIu64,
3776// buf_ptr(&dest_type->name), dest_align,
3777// buf_ptr(&src_type->name), src_align));
3778// }
3779// }
3780//
3781// return builtin_fn->return_type;
3782// }
3783// case BuiltinFnIdMemset:
3784// {
3785// AstNode *dest_node = node->data.fn_call_expr.params.at(0);
3786// AstNode *char_node = node->data.fn_call_expr.params.at(1);
3787// AstNode *len_node = node->data.fn_call_expr.params.at(2);
3788// TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node);
3789// analyze_expression(g, import, context, builtin_fn->param_types[1], char_node);
3790// analyze_expression(g, import, context, builtin_fn->param_types[2], len_node);
3791//
3792// if (dest_type->id != TypeTableEntryIdInvalid &&
3793// dest_type->id != TypeTableEntryIdPointer)
3794// {
3795// add_node_error(g, dest_node,
3796// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
3797// }
3798//
3799// return builtin_fn->return_type;
3800// }
3801// case BuiltinFnIdSizeof:
3802// {
3803// AstNode *type_node = node->data.fn_call_expr.params.at(0);
3804// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
3805// if (type_entry->id == TypeTableEntryIdInvalid) {
3806// return g->builtin_types.entry_invalid;
3807// } else if (type_entry->id == TypeTableEntryIdUnreachable) {
3808// add_node_error(g, first_executing_node(type_node),
3809// buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
3810// return g->builtin_types.entry_invalid;
3811// } else {
3812// uint64_t size_in_bytes = type_size(g, type_entry);
3813// bool depends_on_compile_var = (type_entry == g->builtin_types.entry_usize ||
3814// type_entry == g->builtin_types.entry_isize);
3815// return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
3816// size_in_bytes, depends_on_compile_var);
3817// }
3818// }
3819// case BuiltinFnIdAlignof:
3820// {
3821// AstNode *type_node = node->data.fn_call_expr.params.at(0);
3822// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
3823// if (type_entry->id == TypeTableEntryIdInvalid) {
3824// return g->builtin_types.entry_invalid;
3825// } else if (type_entry->id == TypeTableEntryIdUnreachable) {
3826// add_node_error(g, first_executing_node(type_node),
3827// buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name)));
3828// return g->builtin_types.entry_invalid;
3829// } else {
3830// uint64_t align_in_bytes = LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref);
3831// return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
3832// align_in_bytes, false);
3833// }
3834// }
3835// case BuiltinFnIdMaxValue:
3836// return analyze_min_max_value(g, import, context, node,
3837// "no max value available for type '%s'", true);
3838// case BuiltinFnIdMinValue:
3839// return analyze_min_max_value(g, import, context, node,
3840// "no min value available for type '%s'", false);
3841// case BuiltinFnIdMemberCount:
3842// {
3843// AstNode *type_node = node->data.fn_call_expr.params.at(0);
3844// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
3845//
3846// if (type_entry->id == TypeTableEntryIdInvalid) {
3847// return type_entry;
3848// } else if (type_entry->id == TypeTableEntryIdEnum) {
3849// uint64_t value_count = type_entry->data.enumeration.src_field_count;
3850// return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
3851// value_count, false);
3852// } else {
3853// add_node_error(g, node,
3854// buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name)));
3855// return g->builtin_types.entry_invalid;
3856// }
3857// }
3858// case BuiltinFnIdCInclude:
3859// {
3860// if (!context->c_import_buf) {
3861// add_node_error(g, node, buf_sprintf("@c_include valid only in c_import blocks"));
3862// return g->builtin_types.entry_invalid;
3863// }
3864//
3865// AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field;
3866// TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);
3867// TypeTableEntry *resolved_type = analyze_expression(g, import, context, str_type, *str_node);
3868//
3869// if (resolved_type->id == TypeTableEntryIdInvalid) {
3870// return resolved_type;
3871// }
3872//
3873// ConstExprValue *const_str_val = &get_resolved_expr(*str_node)->const_val;
3874//
3875// if (!const_str_val->ok) {
3876// add_node_error(g, *str_node, buf_sprintf("@c_include requires constant expression"));
3877// return g->builtin_types.entry_void;
3878// }
3879//
3880// buf_appendf(context->c_import_buf, "#include <");
3881// ConstExprValue *ptr_field = const_str_val->data.x_struct.fields[0];
3882// uint64_t len = ptr_field->data.x_ptr.len;
3883// for (uint64_t i = 0; i < len; i += 1) {
3884// ConstExprValue *char_val = ptr_field->data.x_ptr.ptr[i];
3885// uint64_t big_c = char_val->data.x_bignum.data.x_uint;
3886// assert(big_c <= UINT8_MAX);
3887// uint8_t c = big_c;
3888// buf_append_char(context->c_import_buf, c);
3889// }
3890// buf_appendf(context->c_import_buf, ">\n");
3891//
3892// return g->builtin_types.entry_void;
3893// }
3894// case BuiltinFnIdCDefine:
3895// zig_panic("TODO");
3896// case BuiltinFnIdCUndef:
3897// zig_panic("TODO");
3898//
3899// case BuiltinFnIdCompileVar:
3900// {
3901// AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field;
3902//
3903// Buf *var_name = resolve_const_expr_str(g, import, context, str_node);
3904// if (!var_name) {
3905// return g->builtin_types.entry_invalid;
3906// }
3907//
3908// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
3909// const_val->ok = true;
3910// const_val->depends_on_compile_var = true;
3911//
3912// if (buf_eql_str(var_name, "is_big_endian")) {
3913// return resolve_expr_const_val_as_bool(g, node, g->is_big_endian, true);
3914// } else if (buf_eql_str(var_name, "is_release")) {
3915// return resolve_expr_const_val_as_bool(g, node, g->is_release_build, true);
3916// } else if (buf_eql_str(var_name, "is_test")) {
3917// return resolve_expr_const_val_as_bool(g, node, g->is_test_build, true);
3918// } else if (buf_eql_str(var_name, "os")) {
3919// const_val->data.x_enum.tag = g->target_os_index;
3920// return g->builtin_types.entry_os_enum;
3921// } else if (buf_eql_str(var_name, "arch")) {
3922// const_val->data.x_enum.tag = g->target_arch_index;
3923// return g->builtin_types.entry_arch_enum;
3924// } else if (buf_eql_str(var_name, "environ")) {
3925// const_val->data.x_enum.tag = g->target_environ_index;
3926// return g->builtin_types.entry_environ_enum;
3927// } else if (buf_eql_str(var_name, "object_format")) {
3928// const_val->data.x_enum.tag = g->target_oformat_index;
3929// return g->builtin_types.entry_oformat_enum;
3930// } else {
3931// add_node_error(g, *str_node,
3932// buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(var_name)));
3933// return g->builtin_types.entry_invalid;
3934// }
3935// }
3936// case BuiltinFnIdConstEval:
3937// {
3938// AstNode **expr_node = node->data.fn_call_expr.params.at(0)->parent_field;
3939// TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_type, *expr_node);
3940// if (resolved_type->id == TypeTableEntryIdInvalid) {
3941// return resolved_type;
3942// }
3943//
3944// ConstExprValue *const_expr_val = &get_resolved_expr(*expr_node)->const_val;
3945//
3946// if (!const_expr_val->ok) {
3947// add_node_error(g, *expr_node, buf_sprintf("unable to evaluate constant expression"));
3948// return g->builtin_types.entry_invalid;
3949// }
3950//
3951// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
3952// *const_val = *const_expr_val;
3953//
3954// return resolved_type;
3955// }
3956// case BuiltinFnIdCtz:
3957// case BuiltinFnIdClz:
3958// {
3959// AstNode *type_node = node->data.fn_call_expr.params.at(0);
3960// TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node);
3961// if (int_type->id == TypeTableEntryIdInvalid) {
3962// return int_type;
3963// } else if (int_type->id == TypeTableEntryIdInt) {
3964// AstNode **expr_node = node->data.fn_call_expr.params.at(1)->parent_field;
3965// TypeTableEntry *resolved_type = analyze_expression(g, import, context, int_type, *expr_node);
3966// if (resolved_type->id == TypeTableEntryIdInvalid) {
3967// return resolved_type;
3968// }
3969//
3970// // TODO const expr eval
3971//
3972// return resolved_type;
3973// } else {
3974// add_node_error(g, type_node,
3975// buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name)));
3976// return g->builtin_types.entry_invalid;
3977// }
3978// }
3979// case BuiltinFnIdImport:
3980// return analyze_import(g, import, context, node);
3981// case BuiltinFnIdCImport:
3982// return analyze_c_import(g, import, context, node);
3983// case BuiltinFnIdErrName:
3984// return analyze_err_name(g, import, context, node);
3985// case BuiltinFnIdBreakpoint:
3986// mark_impure_fn(g, context, node);
3987// return g->builtin_types.entry_void;
3988// case BuiltinFnIdReturnAddress:
3989// case BuiltinFnIdFrameAddress:
3990// mark_impure_fn(g, context, node);
3991// return builtin_fn->return_type;
3992// case BuiltinFnIdEmbedFile:
3993// return analyze_embed_file(g, import, context, node);
3994// case BuiltinFnIdCmpExchange:
3995// return analyze_cmpxchg(g, import, context, node);
3996// case BuiltinFnIdFence:
3997// return analyze_fence(g, import, context, node);
3998// case BuiltinFnIdDivExact:
3999// return analyze_div_exact(g, import, context, node);
4000// case BuiltinFnIdTruncate:
4001// return analyze_truncate(g, import, context, node);
4002// case BuiltinFnIdCompileErr:
4003// return analyze_compile_err(g, import, context, node);
4004// case BuiltinFnIdIntType:
4005// return analyze_int_type(g, import, context, node);
4006// case BuiltinFnIdSetFnTest:
4007// return analyze_set_fn_test(g, import, context, node);
4008// case BuiltinFnIdSetFnNoInline:
4009// return analyze_set_fn_no_inline(g, import, context, node);
4010// case BuiltinFnIdSetFnStaticEval:
4011// return analyze_set_fn_static_eval(g, import, context, node);
4012// case BuiltinFnIdSetFnVisible:
4013// return analyze_set_fn_visible(g, import, context, node);
4014// case BuiltinFnIdSetDebugSafety:
4015// return analyze_set_debug_safety(g, import, context, node);
4016// }
4017// zig_unreachable();
4018//}
4019
4020//static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry *import,
4021// BlockContext *context, AstNode *node)
4022//{
4023// assert(node->type == NodeTypeContainerInitExpr);
4024//
4025// AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
4026//
4027// ContainerInitKind kind = container_init_expr->kind;
4028//
4029// if (container_init_expr->type->type == NodeTypeFieldAccessExpr) {
4030// container_init_expr->type->data.field_access_expr.container_init_expr_node = node;
4031// }
4032//
4033// TypeTableEntry *container_meta_type = analyze_expression(g, import, context, nullptr,
4034// container_init_expr->type);
4035//
4036// if (container_meta_type->id == TypeTableEntryIdInvalid) {
4037// return g->builtin_types.entry_invalid;
4038// }
4039//
4040// if (node->data.container_init_expr.enum_type) {
4041// get_resolved_expr(node)->const_val = get_resolved_expr(container_init_expr->type)->const_val;
4042// return node->data.container_init_expr.enum_type;
4043// }
4044//
4045// TypeTableEntry *container_type = resolve_type(g, container_init_expr->type);
4046//
4047// if (container_type->id == TypeTableEntryIdInvalid) {
4048// return container_type;
4049// } else if (container_type->id == TypeTableEntryIdStruct &&
4050// !container_type->data.structure.is_slice &&
4051// (kind == ContainerInitKindStruct || (kind == ContainerInitKindArray &&
4052// container_init_expr->entries.length == 0)))
4053// {
4054// StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
4055// codegen->type_entry = container_type;
4056// codegen->source_node = node;
4057//
4058//
4059// size_t expr_field_count = container_init_expr->entries.length;
4060// size_t actual_field_count = container_type->data.structure.src_field_count;
4061//
4062// AstNode *non_const_expr_culprit = nullptr;
4063//
4064// size_t *field_use_counts = allocate<size_t>(actual_field_count);
4065// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
4066// const_val->ok = true;
4067// const_val->data.x_struct.fields = allocate<ConstExprValue*>(actual_field_count);
4068// for (size_t i = 0; i < expr_field_count; i += 1) {
4069// AstNode *val_field_node = container_init_expr->entries.at(i);
4070// assert(val_field_node->type == NodeTypeStructValueField);
4071//
4072// val_field_node->block_context = context;
4073//
4074// TypeStructField *type_field = find_struct_type_field(container_type,
4075// val_field_node->data.struct_val_field.name);
4076//
4077// if (!type_field) {
4078// add_node_error(g, val_field_node,
4079// buf_sprintf("no member named '%s' in '%s'",
4080// buf_ptr(val_field_node->data.struct_val_field.name), buf_ptr(&container_type->name)));
4081// continue;
4082// }
4083//
4084// if (type_field->type_entry->id == TypeTableEntryIdInvalid) {
4085// return g->builtin_types.entry_invalid;
4086// }
4087//
4088// size_t field_index = type_field->src_index;
4089// field_use_counts[field_index] += 1;
4090// if (field_use_counts[field_index] > 1) {
4091// add_node_error(g, val_field_node, buf_sprintf("duplicate field"));
4092// continue;
4093// }
4094//
4095// val_field_node->data.struct_val_field.type_struct_field = type_field;
4096//
4097// analyze_expression(g, import, context, type_field->type_entry,
4098// val_field_node->data.struct_val_field.expr);
4099//
4100// if (const_val->ok) {
4101// ConstExprValue *field_val =
4102// &get_resolved_expr(val_field_node->data.struct_val_field.expr)->const_val;
4103// if (field_val->ok) {
4104// const_val->data.x_struct.fields[field_index] = field_val;
4105// const_val->depends_on_compile_var = const_val->depends_on_compile_var || field_val->depends_on_compile_var;
4106// } else {
4107// const_val->ok = false;
4108// non_const_expr_culprit = val_field_node->data.struct_val_field.expr;
4109// }
4110// }
4111// }
4112// if (!const_val->ok) {
4113// assert(non_const_expr_culprit);
4114// if (context->fn_entry) {
4115// context->fn_entry->struct_val_expr_alloca_list.append(codegen);
4116// } else {
4117// add_node_error(g, non_const_expr_culprit, buf_sprintf("unable to evaluate constant expression"));
4118// }
4119// }
4120//
4121// for (size_t i = 0; i < actual_field_count; i += 1) {
4122// if (field_use_counts[i] == 0) {
4123// add_node_error(g, node,
4124// buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name)));
4125// }
4126// }
4127// return container_type;
4128// } else if (container_type->id == TypeTableEntryIdStruct &&
4129// container_type->data.structure.is_slice &&
4130// kind == ContainerInitKindArray)
4131// {
4132// size_t elem_count = container_init_expr->entries.length;
4133//
4134// TypeTableEntry *pointer_type = container_type->data.structure.fields[0].type_entry;
4135// assert(pointer_type->id == TypeTableEntryIdPointer);
4136// TypeTableEntry *child_type = pointer_type->data.pointer.child_type;
4137//
4138// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
4139// const_val->ok = true;
4140// const_val->data.x_array.fields = allocate<ConstExprValue*>(elem_count);
4141//
4142// for (size_t i = 0; i < elem_count; i += 1) {
4143// AstNode **elem_node = &container_init_expr->entries.at(i);
4144// analyze_expression(g, import, context, child_type, *elem_node);
4145//
4146// if (const_val->ok) {
4147// ConstExprValue *elem_const_val = &get_resolved_expr(*elem_node)->const_val;
4148// if (elem_const_val->ok) {
4149// const_val->data.x_array.fields[i] = elem_const_val;
4150// const_val->depends_on_compile_var = const_val->depends_on_compile_var ||
4151// elem_const_val->depends_on_compile_var;
4152// } else {
4153// const_val->ok = false;
4154// }
4155// }
4156// }
4157//
4158// TypeTableEntry *fixed_size_array_type = get_array_type(g, child_type, elem_count);
4159//
4160// StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
4161// codegen->type_entry = fixed_size_array_type;
4162// codegen->source_node = node;
4163// if (!const_val->ok) {
4164// if (!context->fn_entry) {
4165// add_node_error(g, node,
4166// buf_sprintf("unable to evaluate constant expression"));
4167// } else {
4168// context->fn_entry->struct_val_expr_alloca_list.append(codegen);
4169// }
4170// }
4171//
4172// return fixed_size_array_type;
4173// } else if (container_type->id == TypeTableEntryIdArray) {
4174// zig_panic("TODO array container init");
4175// return container_type;
4176// } else if (container_type->id == TypeTableEntryIdVoid) {
4177// if (container_init_expr->entries.length != 0) {
4178// add_node_error(g, node, buf_sprintf("void expression expects no arguments"));
4179// return g->builtin_types.entry_invalid;
4180// } else {
4181// return resolve_expr_const_val_as_void(g, node);
4182// }
4183// } else {
4184// add_node_error(g, node,
4185// buf_sprintf("type '%s' does not support %s initialization syntax",
4186// buf_ptr(&container_type->name), err_container_init_syntax_name(kind)));
4187// return g->builtin_types.entry_invalid;
4188// }
4189//}
4190
4191static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) {
4192 IrBasicBlock *old_dest_block = br_instruction->dest_block;
41933174
4194 // TODO detect backward jumps3175 // TODO detect backward jumps
41953176
...@@ -4235,55 +3216,6 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct...@@ -4235,55 +3216,6 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
4235 return ira->codegen->builtin_types.entry_unreachable;3216 return ira->codegen->builtin_types.entry_unreachable;
4236}3217}
42373218
4238static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira,
4239 IrInstructionBuiltinCall *builtin_call_instruction)
4240{
4241 switch (builtin_call_instruction->fn->id) {
4242 case BuiltinFnIdInvalid:
4243 case BuiltinFnIdUnreachable:
4244 case BuiltinFnIdTypeof:
4245 zig_unreachable();
4246 case BuiltinFnIdMemcpy:
4247 case BuiltinFnIdMemset:
4248 case BuiltinFnIdSizeof:
4249 case BuiltinFnIdAlignof:
4250 case BuiltinFnIdMaxValue:
4251 case BuiltinFnIdMinValue:
4252 case BuiltinFnIdMemberCount:
4253 case BuiltinFnIdAddWithOverflow:
4254 case BuiltinFnIdSubWithOverflow:
4255 case BuiltinFnIdMulWithOverflow:
4256 case BuiltinFnIdShlWithOverflow:
4257 case BuiltinFnIdCInclude:
4258 case BuiltinFnIdCDefine:
4259 case BuiltinFnIdCUndef:
4260 case BuiltinFnIdCompileVar:
4261 case BuiltinFnIdCompileErr:
4262 case BuiltinFnIdConstEval:
4263 case BuiltinFnIdCtz:
4264 case BuiltinFnIdClz:
4265 case BuiltinFnIdImport:
4266 case BuiltinFnIdCImport:
4267 case BuiltinFnIdErrName:
4268 case BuiltinFnIdBreakpoint:
4269 case BuiltinFnIdReturnAddress:
4270 case BuiltinFnIdFrameAddress:
4271 case BuiltinFnIdEmbedFile:
4272 case BuiltinFnIdCmpExchange:
4273 case BuiltinFnIdFence:
4274 case BuiltinFnIdDivExact:
4275 case BuiltinFnIdTruncate:
4276 case BuiltinFnIdIntType:
4277 case BuiltinFnIdSetFnTest:
4278 case BuiltinFnIdSetFnVisible:
4279 case BuiltinFnIdSetFnStaticEval:
4280 case BuiltinFnIdSetFnNoInline:
4281 case BuiltinFnIdSetDebugSafety:
4282 zig_panic("TODO analyze more builtin functions");
4283 }
4284 zig_unreachable();
4285}
4286
4287static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira,3219static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira,
4288 IrInstructionUnreachable *unreachable_instruction)3220 IrInstructionUnreachable *unreachable_instruction)
4289{3221{
...@@ -4731,6 +3663,34 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira,...@@ -4731,6 +3663,34 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira,
4731 return ira->codegen->builtin_types.entry_type;3663 return ira->codegen->builtin_types.entry_type;
4732}3664}
47333665
3666static TypeTableEntry *ir_analyze_instruction_set_fn_test(IrAnalyze *ira,
3667 IrInstructionSetFnTest *set_fn_test_instruction)
3668{
3669 IrInstruction *fn_value = set_fn_test_instruction->fn_value->other;
3670 IrInstruction *is_test_value = set_fn_test_instruction->is_test->other;
3671
3672 FnTableEntry *fn_entry = ir_resolve_fn(ira, fn_value);
3673 if (!fn_entry)
3674 return ira->codegen->builtin_types.entry_invalid;
3675
3676 if (!ir_resolve_bool(ira, is_test_value, &fn_entry->is_test))
3677 return ira->codegen->builtin_types.entry_invalid;
3678
3679 AstNode *source_node = set_fn_test_instruction->base.source_node;
3680 if (fn_entry->fn_test_set_node) {
3681 ErrorMsg *msg = add_node_error(ira->codegen, source_node,
3682 buf_sprintf("function test attribute set twice"));
3683 add_error_note(ira->codegen, msg, fn_entry->fn_test_set_node, buf_sprintf("first set here"));
3684 return ira->codegen->builtin_types.entry_invalid;
3685 }
3686 fn_entry->fn_test_set_node = source_node;
3687
3688 ira->codegen->test_fn_count += 1;
3689
3690 ir_build_const_from(ira, &set_fn_test_instruction->base, false);
3691 return ira->codegen->builtin_types.entry_void;
3692}
3693
4734static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {3694static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
4735 switch (instruction->id) {3695 switch (instruction->id) {
4736 case IrInstructionIdInvalid:3696 case IrInstructionIdInvalid:
...@@ -4763,8 +3723,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -4763,8 +3723,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
4763 return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction);3723 return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction);
4764 case IrInstructionIdCondBr:3724 case IrInstructionIdCondBr:
4765 return ir_analyze_instruction_cond_br(ira, (IrInstructionCondBr *)instruction);3725 return ir_analyze_instruction_cond_br(ira, (IrInstructionCondBr *)instruction);
4766 case IrInstructionIdBuiltinCall:
4767 return ir_analyze_instruction_builtin_call(ira, (IrInstructionBuiltinCall *)instruction);
4768 case IrInstructionIdUnreachable:3726 case IrInstructionIdUnreachable:
4769 return ir_analyze_instruction_unreachable(ira, (IrInstructionUnreachable *)instruction);3727 return ir_analyze_instruction_unreachable(ira, (IrInstructionUnreachable *)instruction);
4770 case IrInstructionIdPhi:3728 case IrInstructionIdPhi:
...@@ -4775,175 +3733,3488 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -4775,175 +3733,3488 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
4775 return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction);3733 return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction);
4776 case IrInstructionIdPtrTypeChild:3734 case IrInstructionIdPtrTypeChild:
4777 return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);3735 return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);
3736 case IrInstructionIdSetFnTest:
3737 return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction);
3738 case IrInstructionIdSwitchBr:
3739 case IrInstructionIdCast:
3740 case IrInstructionIdContainerInitList:
3741 case IrInstructionIdContainerInitFields:
3742 case IrInstructionIdStructFieldPtr:
3743 zig_panic("TODO analyze more instructions");
3744 }
3745 zig_unreachable();
3746}
3747
3748static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction) {
3749 TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction);
3750 instruction->type_entry = instruction_type;
3751 if (instruction->other) {
3752 instruction->other->type_entry = instruction_type;
3753 } else {
3754 assert(instruction_type->id == TypeTableEntryIdInvalid ||
3755 instruction_type->id == TypeTableEntryIdUnreachable);
3756 instruction->other = instruction;
3757 }
3758 return instruction_type;
3759}
3760
3761// This function attempts to evaluate IR code while doing type checking and other analysis.
3762// It emits a new IrExecutable which is partially evaluated IR code.
3763TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec,
3764 TypeTableEntry *expected_type, AstNode *expected_type_source_node)
3765{
3766 IrAnalyze ir_analyze_data = {};
3767 IrAnalyze *ira = &ir_analyze_data;
3768 ira->codegen = codegen;
3769 ira->explicit_return_type = expected_type;
3770
3771 ira->old_irb.codegen = codegen;
3772 ira->old_irb.exec = old_exec;
3773
3774 ira->new_irb.codegen = codegen;
3775 ira->new_irb.exec = new_exec;
3776
3777 ira->exec_context.mem_slot_count = ira->old_irb.exec->mem_slot_count;
3778 ira->exec_context.mem_slot_list = allocate<ConstExprValue>(ira->exec_context.mem_slot_count);
3779
3780 IrBasicBlock *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0);
3781 IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb);
3782 ir_ref_bb(new_entry_bb);
3783 ira->old_irb.current_basic_block = old_entry_bb;
3784 ira->new_irb.current_basic_block = new_entry_bb;
3785 ira->block_queue_index = 0;
3786 ira->instruction_index = 0;
3787
3788 while (ira->block_queue_index < ira->old_bb_queue.length) {
3789 IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
3790
3791 if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) {
3792 ira->instruction_index += 1;
3793 continue;
3794 }
3795
3796 TypeTableEntry *return_type = ir_analyze_instruction(ira, old_instruction);
3797
3798 // unreachable instructions do their own control flow.
3799 if (return_type->id == TypeTableEntryIdUnreachable)
3800 continue;
3801
3802 ira->instruction_index += 1;
3803 }
3804
3805 return ir_resolve_peer_types(ira, expected_type_source_node, ira->implicit_return_type_list.items,
3806 ira->implicit_return_type_list.length);
3807}
3808
3809bool ir_has_side_effects(IrInstruction *instruction) {
3810 switch (instruction->id) {
3811 case IrInstructionIdInvalid:
3812 zig_unreachable();
3813 case IrInstructionIdBr:
3814 case IrInstructionIdCondBr:
4778 case IrInstructionIdSwitchBr:3815 case IrInstructionIdSwitchBr:
3816 case IrInstructionIdDeclVar:
3817 case IrInstructionIdStorePtr:
3818 case IrInstructionIdCall:
3819 case IrInstructionIdReturn:
3820 case IrInstructionIdUnreachable:
3821 case IrInstructionIdSetFnTest:
3822 return true;
3823 case IrInstructionIdPhi:
3824 case IrInstructionIdUnOp:
3825 case IrInstructionIdBinOp:
3826 case IrInstructionIdLoadPtr:
3827 case IrInstructionIdConst:
4779 case IrInstructionIdCast:3828 case IrInstructionIdCast:
4780 case IrInstructionIdContainerInitList:3829 case IrInstructionIdContainerInitList:
4781 case IrInstructionIdContainerInitFields:3830 case IrInstructionIdContainerInitFields:
3831 case IrInstructionIdFieldPtr:
3832 case IrInstructionIdElemPtr:
3833 case IrInstructionIdVarPtr:
3834 case IrInstructionIdTypeOf:
3835 case IrInstructionIdToPtrType:
3836 case IrInstructionIdPtrTypeChild:
3837 case IrInstructionIdReadField:
4782 case IrInstructionIdStructFieldPtr:3838 case IrInstructionIdStructFieldPtr:
4783 zig_panic("TODO analyze more instructions");3839 return false;
4784 }3840 }
4785 zig_unreachable();3841 zig_unreachable();
4786}3842}
47873843
4788static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction) {3844IrInstruction *ir_exec_const_result(IrExecutable *exec) {
4789 TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction);3845 if (exec->basic_block_list.length != 1)
4790 instruction->type_entry = instruction_type;3846 return nullptr;
4791 if (instruction->other) {
4792 instruction->other->type_entry = instruction_type;
4793 } else {
4794 assert(instruction_type->id == TypeTableEntryIdInvalid ||
4795 instruction_type->id == TypeTableEntryIdUnreachable);
4796 instruction->other = instruction;
4797 }
4798 return instruction_type;
4799}
4800
4801// This function attempts to evaluate IR code while doing type checking and other analysis.
4802// It emits a new IrExecutable which is partially evaluated IR code.
4803TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec,
4804 TypeTableEntry *expected_type, AstNode *expected_type_source_node)
4805{
4806 IrAnalyze ir_analyze_data = {};
4807 IrAnalyze *ira = &ir_analyze_data;
4808 ira->codegen = codegen;
4809 ira->explicit_return_type = expected_type;
48103847
4811 ira->old_irb.codegen = codegen;3848 IrBasicBlock *bb = exec->basic_block_list.at(0);
4812 ira->old_irb.exec = old_exec;3849 if (bb->instruction_list.length != 1)
3850 return nullptr;
48133851
4814 ira->new_irb.codegen = codegen;3852 IrInstruction *only_inst = bb->instruction_list.at(0);
4815 ira->new_irb.exec = new_exec;3853 if (only_inst->id != IrInstructionIdReturn)
3854 return nullptr;
48163855
4817 ira->exec_context.mem_slot_count = ira->old_irb.exec->mem_slot_count;3856 IrInstructionReturn *ret_inst = (IrInstructionReturn *)only_inst;
4818 ira->exec_context.mem_slot_list = allocate<ConstExprValue>(ira->exec_context.mem_slot_count);3857 IrInstruction *value = ret_inst->value;
3858 assert(value->static_value.ok);
3859 return value;
3860}
48193861
4820 IrBasicBlock *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0);3862//static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4821 IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb);3863// AstNode *node, const char *err_format, bool is_max)
4822 ir_ref_bb(new_entry_bb);3864//{
4823 ira->old_irb.current_basic_block = old_entry_bb;3865// assert(node->type == NodeTypeFnCallExpr);
4824 ira->new_irb.current_basic_block = new_entry_bb;3866// assert(node->data.fn_call_expr.params.length == 1);
4825 ira->block_queue_index = 0;3867//
4826 ira->instruction_index = 0;3868// AstNode *type_node = node->data.fn_call_expr.params.at(0);
3869// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
3870//
3871// if (type_entry->id == TypeTableEntryIdInvalid) {
3872// return g->builtin_types.entry_invalid;
3873// } else if (type_entry->id == TypeTableEntryIdInt) {
3874// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
3875// return g->builtin_types.entry_num_lit_int;
3876// } else if (type_entry->id == TypeTableEntryIdFloat) {
3877// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
3878// return g->builtin_types.entry_num_lit_float;
3879// } else if (type_entry->id == TypeTableEntryIdBool) {
3880// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
3881// return type_entry;
3882// } else {
3883// add_node_error(g, node,
3884// buf_sprintf(err_format, buf_ptr(&type_entry->name)));
3885// return g->builtin_types.entry_invalid;
3886// }
3887//}
48273888
4828 while (ira->block_queue_index < ira->old_bb_queue.length) {3889//static TypeTableEntry *analyze_import(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4829 IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);3890// AstNode *node)
3891//{
3892// assert(node->type == NodeTypeFnCallExpr);
3893//
3894// if (context->fn_entry) {
3895// add_node_error(g, node, buf_sprintf("@import invalid inside function bodies"));
3896// return g->builtin_types.entry_invalid;
3897// }
3898//
3899// AstNode *first_param_node = node->data.fn_call_expr.params.at(0);
3900// Buf *import_target_str = resolve_const_expr_str(g, import, context, first_param_node->parent_field);
3901// if (!import_target_str) {
3902// return g->builtin_types.entry_invalid;
3903// }
3904//
3905// Buf *import_target_path;
3906// Buf *search_dir;
3907// assert(import->package);
3908// PackageTableEntry *target_package;
3909// auto package_entry = import->package->package_table.maybe_get(import_target_str);
3910// if (package_entry) {
3911// target_package = package_entry->value;
3912// import_target_path = &target_package->root_src_path;
3913// search_dir = &target_package->root_src_dir;
3914// } else {
3915// // try it as a filename
3916// target_package = import->package;
3917// import_target_path = import_target_str;
3918// search_dir = &import->package->root_src_dir;
3919// }
3920//
3921// Buf full_path = BUF_INIT;
3922// os_path_join(search_dir, import_target_path, &full_path);
3923//
3924// Buf *import_code = buf_alloc();
3925// Buf *abs_full_path = buf_alloc();
3926// int err;
3927// if ((err = os_path_real(&full_path, abs_full_path))) {
3928// if (err == ErrorFileNotFound) {
3929// add_node_error(g, node,
3930// buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
3931// return g->builtin_types.entry_invalid;
3932// } else {
3933// g->error_during_imports = true;
3934// add_node_error(g, node,
3935// buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
3936// return g->builtin_types.entry_invalid;
3937// }
3938// }
3939//
3940// auto import_entry = g->import_table.maybe_get(abs_full_path);
3941// if (import_entry) {
3942// return resolve_expr_const_val_as_import(g, node, import_entry->value);
3943// }
3944//
3945// if ((err = os_fetch_file_path(abs_full_path, import_code))) {
3946// if (err == ErrorFileNotFound) {
3947// add_node_error(g, node,
3948// buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
3949// return g->builtin_types.entry_invalid;
3950// } else {
3951// add_node_error(g, node,
3952// buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
3953// return g->builtin_types.entry_invalid;
3954// }
3955// }
3956// ImportTableEntry *target_import = add_source_file(g, target_package,
3957// abs_full_path, search_dir, import_target_path, import_code);
3958//
3959// scan_decls(g, target_import, target_import->block_context, target_import->root);
3960//
3961// return resolve_expr_const_val_as_import(g, node, target_import);
3962//}
3963//
3964//static TypeTableEntry *analyze_c_import(CodeGen *g, ImportTableEntry *parent_import,
3965// BlockContext *parent_context, AstNode *node)
3966//{
3967// assert(node->type == NodeTypeFnCallExpr);
3968//
3969// if (parent_context->fn_entry) {
3970// add_node_error(g, node, buf_sprintf("@c_import invalid inside function bodies"));
3971// return g->builtin_types.entry_invalid;
3972// }
3973//
3974// AstNode *block_node = node->data.fn_call_expr.params.at(0);
3975//
3976// BlockContext *child_context = new_block_context(node, parent_context);
3977// child_context->c_import_buf = buf_alloc();
3978//
3979// TypeTableEntry *resolved_type = analyze_expression(g, parent_import, child_context,
3980// g->builtin_types.entry_void, block_node);
3981//
3982// if (resolved_type->id == TypeTableEntryIdInvalid) {
3983// return resolved_type;
3984// }
3985//
3986// find_libc_include_path(g);
3987//
3988// ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
3989// child_import->c_import_node = node;
3990//
3991// ZigList<ErrorMsg *> errors = {0};
3992//
3993// int err;
3994// if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g, node))) {
3995// zig_panic("unable to parse h file: %s\n", err_str(err));
3996// }
3997//
3998// if (errors.length > 0) {
3999// ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed"));
4000// for (size_t i = 0; i < errors.length; i += 1) {
4001// ErrorMsg *err_msg = errors.at(i);
4002// err_msg_add_note(parent_err_msg, err_msg);
4003// }
4004//
4005// return g->builtin_types.entry_invalid;
4006// }
4007//
4008// if (g->verbose) {
4009// fprintf(stderr, "\nc_import:\n");
4010// fprintf(stderr, "-----------\n");
4011// ast_render(stderr, child_import->root, 4);
4012// }
4013//
4014// child_import->di_file = parent_import->di_file;
4015// child_import->block_context = new_block_context(child_import->root, nullptr);
4016//
4017// scan_decls(g, child_import, child_import->block_context, child_import->root);
4018// return resolve_expr_const_val_as_import(g, node, child_import);
4019//}
4020//
4021//static TypeTableEntry *analyze_err_name(CodeGen *g, ImportTableEntry *import,
4022// BlockContext *context, AstNode *node)
4023//{
4024// assert(node->type == NodeTypeFnCallExpr);
4025//
4026// AstNode *err_value = node->data.fn_call_expr.params.at(0);
4027// TypeTableEntry *resolved_type = analyze_expression(g, import, context,
4028// g->builtin_types.entry_pure_error, err_value);
4029//
4030// if (resolved_type->id == TypeTableEntryIdInvalid) {
4031// return resolved_type;
4032// }
4033//
4034// g->generate_error_name_table = true;
4035//
4036// TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);
4037// return str_type;
4038//}
4039//
4040//static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import,
4041// BlockContext *context, AstNode *node)
4042//{
4043// assert(node->type == NodeTypeFnCallExpr);
4044//
4045// AstNode **first_param_node = &node->data.fn_call_expr.params.at(0);
4046// Buf *rel_file_path = resolve_const_expr_str(g, import, context, first_param_node);
4047// if (!rel_file_path) {
4048// return g->builtin_types.entry_invalid;
4049// }
4050//
4051// // figure out absolute path to resource
4052// Buf source_dir_path = BUF_INIT;
4053// os_path_dirname(import->path, &source_dir_path);
4054//
4055// Buf file_path = BUF_INIT;
4056// os_path_resolve(&source_dir_path, rel_file_path, &file_path);
4057//
4058// // load from file system into const expr
4059// Buf file_contents = BUF_INIT;
4060// int err;
4061// if ((err = os_fetch_file_path(&file_path, &file_contents))) {
4062// if (err == ErrorFileNotFound) {
4063// add_node_error(g, node,
4064// buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));
4065// return g->builtin_types.entry_invalid;
4066// } else {
4067// add_node_error(g, node,
4068// buf_sprintf("unable to open '%s': %s", buf_ptr(&file_path), err_str(err)));
4069// return g->builtin_types.entry_invalid;
4070// }
4071// }
4072//
4073// // TODO add dependency on the file we embedded so that we know if it changes
4074// // we'll have to invalidate the cache
4075//
4076// return resolve_expr_const_val_as_string_lit(g, node, &file_contents);
4077//}
4078//
4079//static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,
4080// BlockContext *context, AstNode *node)
4081//{
4082// assert(node->type == NodeTypeFnCallExpr);
4083//
4084// AstNode **ptr_arg = &node->data.fn_call_expr.params.at(0);
4085// AstNode **cmp_arg = &node->data.fn_call_expr.params.at(1);
4086// AstNode **new_arg = &node->data.fn_call_expr.params.at(2);
4087// AstNode **success_order_arg = &node->data.fn_call_expr.params.at(3);
4088// AstNode **failure_order_arg = &node->data.fn_call_expr.params.at(4);
4089//
4090// TypeTableEntry *ptr_type = analyze_expression(g, import, context, nullptr, *ptr_arg);
4091// if (ptr_type->id == TypeTableEntryIdInvalid) {
4092// return g->builtin_types.entry_invalid;
4093// } else if (ptr_type->id != TypeTableEntryIdPointer) {
4094// add_node_error(g, *ptr_arg,
4095// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&ptr_type->name)));
4096// return g->builtin_types.entry_invalid;
4097// }
4098//
4099// TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
4100// TypeTableEntry *cmp_type = analyze_expression(g, import, context, child_type, *cmp_arg);
4101// TypeTableEntry *new_type = analyze_expression(g, import, context, child_type, *new_arg);
4102//
4103// TypeTableEntry *success_order_type = analyze_expression(g, import, context,
4104// g->builtin_types.entry_atomic_order_enum, *success_order_arg);
4105// TypeTableEntry *failure_order_type = analyze_expression(g, import, context,
4106// g->builtin_types.entry_atomic_order_enum, *failure_order_arg);
4107//
4108// if (cmp_type->id == TypeTableEntryIdInvalid ||
4109// new_type->id == TypeTableEntryIdInvalid ||
4110// success_order_type->id == TypeTableEntryIdInvalid ||
4111// failure_order_type->id == TypeTableEntryIdInvalid)
4112// {
4113// return g->builtin_types.entry_invalid;
4114// }
4115//
4116// ConstExprValue *success_order_val = &get_resolved_expr(*success_order_arg)->const_val;
4117// ConstExprValue *failure_order_val = &get_resolved_expr(*failure_order_arg)->const_val;
4118// if (!success_order_val->ok) {
4119// add_node_error(g, *success_order_arg, buf_sprintf("unable to evaluate constant expression"));
4120// return g->builtin_types.entry_invalid;
4121// } else if (!failure_order_val->ok) {
4122// add_node_error(g, *failure_order_arg, buf_sprintf("unable to evaluate constant expression"));
4123// return g->builtin_types.entry_invalid;
4124// }
4125//
4126// if (success_order_val->data.x_enum.tag < AtomicOrderMonotonic) {
4127// add_node_error(g, *success_order_arg,
4128// buf_sprintf("success atomic ordering must be Monotonic or stricter"));
4129// return g->builtin_types.entry_invalid;
4130// }
4131// if (failure_order_val->data.x_enum.tag < AtomicOrderMonotonic) {
4132// add_node_error(g, *failure_order_arg,
4133// buf_sprintf("failure atomic ordering must be Monotonic or stricter"));
4134// return g->builtin_types.entry_invalid;
4135// }
4136// if (failure_order_val->data.x_enum.tag > success_order_val->data.x_enum.tag) {
4137// add_node_error(g, *failure_order_arg,
4138// buf_sprintf("failure atomic ordering must be no stricter than success"));
4139// return g->builtin_types.entry_invalid;
4140// }
4141// if (failure_order_val->data.x_enum.tag == AtomicOrderRelease ||
4142// failure_order_val->data.x_enum.tag == AtomicOrderAcqRel)
4143// {
4144// add_node_error(g, *failure_order_arg,
4145// buf_sprintf("failure atomic ordering must not be Release or AcqRel"));
4146// return g->builtin_types.entry_invalid;
4147// }
4148//
4149// return g->builtin_types.entry_bool;
4150//}
4151//
4152//static TypeTableEntry *analyze_fence(CodeGen *g, ImportTableEntry *import,
4153// BlockContext *context, AstNode *node)
4154//{
4155// assert(node->type == NodeTypeFnCallExpr);
4156//
4157// AstNode **atomic_order_arg = &node->data.fn_call_expr.params.at(0);
4158// TypeTableEntry *atomic_order_type = analyze_expression(g, import, context,
4159// g->builtin_types.entry_atomic_order_enum, *atomic_order_arg);
4160//
4161// if (atomic_order_type->id == TypeTableEntryIdInvalid) {
4162// return g->builtin_types.entry_invalid;
4163// }
4164//
4165// ConstExprValue *atomic_order_val = &get_resolved_expr(*atomic_order_arg)->const_val;
4166//
4167// if (!atomic_order_val->ok) {
4168// add_node_error(g, *atomic_order_arg, buf_sprintf("unable to evaluate constant expression"));
4169// return g->builtin_types.entry_invalid;
4170// }
4171//
4172// return g->builtin_types.entry_void;
4173//}
4174//
4175//static TypeTableEntry *analyze_div_exact(CodeGen *g, ImportTableEntry *import,
4176// BlockContext *context, AstNode *node)
4177//{
4178// assert(node->type == NodeTypeFnCallExpr);
4179//
4180// AstNode **op1 = &node->data.fn_call_expr.params.at(0);
4181// AstNode **op2 = &node->data.fn_call_expr.params.at(1);
4182//
4183// TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1);
4184// TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2);
4185//
4186// AstNode *op_nodes[] = {*op1, *op2};
4187// TypeTableEntry *op_types[] = {op1_type, op2_type};
4188// TypeTableEntry *result_type = resolve_peer_type_compatibility(g, import, context, node,
4189// op_nodes, op_types, 2);
4190//
4191// if (result_type->id == TypeTableEntryIdInvalid) {
4192// return g->builtin_types.entry_invalid;
4193// } else if (result_type->id == TypeTableEntryIdInt) {
4194// return result_type;
4195// } else if (result_type->id == TypeTableEntryIdNumLitInt) {
4196// // check for division by zero
4197// // check for non exact division
4198// zig_panic("TODO");
4199// } else {
4200// add_node_error(g, node,
4201// buf_sprintf("expected integer type, got '%s'", buf_ptr(&result_type->name)));
4202// return g->builtin_types.entry_invalid;
4203// }
4204//}
4205//
4206//static TypeTableEntry *analyze_truncate(CodeGen *g, ImportTableEntry *import,
4207// BlockContext *context, AstNode *node)
4208//{
4209// assert(node->type == NodeTypeFnCallExpr);
4210//
4211// AstNode **op1 = &node->data.fn_call_expr.params.at(0);
4212// AstNode **op2 = &node->data.fn_call_expr.params.at(1);
4213//
4214// TypeTableEntry *dest_type = analyze_type_expr(g, import, context, *op1);
4215// TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, *op2);
4216//
4217// if (dest_type->id == TypeTableEntryIdInvalid || src_type->id == TypeTableEntryIdInvalid) {
4218// return g->builtin_types.entry_invalid;
4219// } else if (dest_type->id != TypeTableEntryIdInt) {
4220// add_node_error(g, *op1,
4221// buf_sprintf("expected integer type, got '%s'", buf_ptr(&dest_type->name)));
4222// return g->builtin_types.entry_invalid;
4223// } else if (src_type->id != TypeTableEntryIdInt) {
4224// add_node_error(g, *op2,
4225// buf_sprintf("expected integer type, got '%s'", buf_ptr(&src_type->name)));
4226// return g->builtin_types.entry_invalid;
4227// } else if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
4228// const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
4229// add_node_error(g, *op2,
4230// buf_sprintf("expected %s integer type, got '%s'", sign_str, buf_ptr(&src_type->name)));
4231// return g->builtin_types.entry_invalid;
4232// } else if (src_type->data.integral.bit_count <= dest_type->data.integral.bit_count) {
4233// add_node_error(g, *op2,
4234// buf_sprintf("type '%s' has same or fewer bits than destination type '%s'",
4235// buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
4236// return g->builtin_types.entry_invalid;
4237// }
4238//
4239// // TODO const expr eval
4240//
4241// return dest_type;
4242//}
4243//
4244//static TypeTableEntry *analyze_compile_err(CodeGen *g, ImportTableEntry *import,
4245// BlockContext *context, AstNode *node)
4246//{
4247// AstNode *first_param_node = node->data.fn_call_expr.params.at(0);
4248// Buf *err_msg = resolve_const_expr_str(g, import, context, first_param_node->parent_field);
4249// if (!err_msg) {
4250// return g->builtin_types.entry_invalid;
4251// }
4252//
4253// add_node_error(g, node, err_msg);
4254//
4255// return g->builtin_types.entry_invalid;
4256//}
4257//
4258//static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import,
4259// BlockContext *context, AstNode *node)
4260//{
4261// AstNode **is_signed_node = &node->data.fn_call_expr.params.at(0);
4262// AstNode **bit_count_node = &node->data.fn_call_expr.params.at(1);
4263//
4264// TypeTableEntry *bool_type = g->builtin_types.entry_bool;
4265// TypeTableEntry *usize_type = g->builtin_types.entry_usize;
4266// TypeTableEntry *is_signed_type = analyze_expression(g, import, context, bool_type, *is_signed_node);
4267// TypeTableEntry *bit_count_type = analyze_expression(g, import, context, usize_type, *bit_count_node);
4268//
4269// if (is_signed_type->id == TypeTableEntryIdInvalid ||
4270// bit_count_type->id == TypeTableEntryIdInvalid)
4271// {
4272// return g->builtin_types.entry_invalid;
4273// }
4274//
4275// ConstExprValue *is_signed_val = &get_resolved_expr(*is_signed_node)->const_val;
4276// ConstExprValue *bit_count_val = &get_resolved_expr(*bit_count_node)->const_val;
4277//
4278// AstNode *bad_node = nullptr;
4279// if (!is_signed_val->ok) {
4280// bad_node = *is_signed_node;
4281// } else if (!bit_count_val->ok) {
4282// bad_node = *bit_count_node;
4283// }
4284// if (bad_node) {
4285// add_node_error(g, bad_node, buf_sprintf("unable to evaluate constant expression"));
4286// return g->builtin_types.entry_invalid;
4287// }
4288//
4289// bool depends_on_compile_var = is_signed_val->depends_on_compile_var || bit_count_val->depends_on_compile_var;
4290//
4291// TypeTableEntry *int_type = get_int_type(g, is_signed_val->data.x_bool,
4292// bit_count_val->data.x_bignum.data.x_uint);
4293// return resolve_expr_const_val_as_type(g, node, int_type, depends_on_compile_var);
4294//
4295//}
4296//
4297//static TypeTableEntry *analyze_set_fn_no_inline(CodeGen *g, ImportTableEntry *import,
4298// BlockContext *context, AstNode *node)
4299//{
4300// AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
4301// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
4302//
4303// FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
4304// if (!fn_entry) {
4305// return g->builtin_types.entry_invalid;
4306// }
4307//
4308// bool is_noinline;
4309// bool ok = resolve_const_expr_bool(g, import, context, value_node, &is_noinline);
4310// if (!ok) {
4311// return g->builtin_types.entry_invalid;
4312// }
4313//
4314// if (fn_entry->fn_no_inline_set_node) {
4315// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function no inline attribute set twice"));
4316// add_error_note(g, msg, fn_entry->fn_no_inline_set_node, buf_sprintf("first set here"));
4317// return g->builtin_types.entry_invalid;
4318// }
4319// fn_entry->fn_no_inline_set_node = node;
4320//
4321// if (fn_entry->fn_inline == FnInlineAlways) {
4322// add_node_error(g, node, buf_sprintf("function is both inline and noinline"));
4323// fn_entry->proto_node->data.fn_proto.skip = true;
4324// return g->builtin_types.entry_invalid;
4325// } else if (is_noinline) {
4326// fn_entry->fn_inline = FnInlineNever;
4327// }
4328//
4329// return g->builtin_types.entry_void;
4330//}
4331//
4332//static TypeTableEntry *analyze_set_fn_static_eval(CodeGen *g, ImportTableEntry *import,
4333// BlockContext *context, AstNode *node)
4334//{
4335// AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
4336// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
4337//
4338// FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
4339// if (!fn_entry) {
4340// return g->builtin_types.entry_invalid;
4341// }
4342//
4343// bool want_static_eval;
4344// bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_static_eval);
4345// if (!ok) {
4346// return g->builtin_types.entry_invalid;
4347// }
4348//
4349// if (fn_entry->fn_static_eval_set_node) {
4350// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function static eval attribute set twice"));
4351// add_error_note(g, msg, fn_entry->fn_static_eval_set_node, buf_sprintf("first set here"));
4352// return g->builtin_types.entry_invalid;
4353// }
4354// fn_entry->fn_static_eval_set_node = node;
4355//
4356// if (want_static_eval && !context->fn_entry->is_pure) {
4357// add_node_error(g, node, buf_sprintf("attribute appears too late within function"));
4358// return g->builtin_types.entry_invalid;
4359// }
4360//
4361// if (want_static_eval) {
4362// fn_entry->want_pure = WantPureTrue;
4363// fn_entry->want_pure_attr_node = node;
4364// } else {
4365// fn_entry->want_pure = WantPureFalse;
4366// fn_entry->is_pure = false;
4367// }
4368//
4369// return g->builtin_types.entry_void;
4370//}
4371//
4372//static TypeTableEntry *analyze_set_fn_visible(CodeGen *g, ImportTableEntry *import,
4373// BlockContext *context, AstNode *node)
4374//{
4375// AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
4376// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
4377//
4378// FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
4379// if (!fn_entry) {
4380// return g->builtin_types.entry_invalid;
4381// }
4382//
4383// bool want_export;
4384// bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_export);
4385// if (!ok) {
4386// return g->builtin_types.entry_invalid;
4387// }
4388//
4389// if (fn_entry->fn_export_set_node) {
4390// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function visibility set twice"));
4391// add_error_note(g, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here"));
4392// return g->builtin_types.entry_invalid;
4393// }
4394// fn_entry->fn_export_set_node = node;
4395//
4396// AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto;
4397// if (fn_proto->top_level_decl.visib_mod != VisibModExport) {
4398// ErrorMsg *msg = add_node_error(g, node,
4399// buf_sprintf("function must be marked export to set function visibility"));
4400// add_error_note(g, msg, fn_entry->proto_node, buf_sprintf("function declared here"));
4401// return g->builtin_types.entry_void;
4402// }
4403// if (!want_export) {
4404// fn_proto->top_level_decl.visib_mod = VisibModPub;
4405// }
4406//
4407// return g->builtin_types.entry_void;
4408//}
4409//
4410//static TypeTableEntry *analyze_set_debug_safety(CodeGen *g, ImportTableEntry *import,
4411// BlockContext *parent_context, AstNode *node)
4412//{
4413// AstNode **target_node = &node->data.fn_call_expr.params.at(0);
4414// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
4415//
4416// TypeTableEntry *target_type = analyze_expression(g, import, parent_context, nullptr, *target_node);
4417// BlockContext *target_context;
4418// ConstExprValue *const_val = &get_resolved_expr(*target_node)->const_val;
4419// if (target_type->id == TypeTableEntryIdInvalid) {
4420// return g->builtin_types.entry_invalid;
4421// }
4422// if (!const_val->ok) {
4423// add_node_error(g, *target_node, buf_sprintf("unable to evaluate constant expression"));
4424// return g->builtin_types.entry_invalid;
4425// }
4426// if (target_type->id == TypeTableEntryIdBlock) {
4427// target_context = const_val->data.x_block;
4428// } else if (target_type->id == TypeTableEntryIdFn) {
4429// target_context = const_val->data.x_fn->fn_def_node->data.fn_def.block_context;
4430// } else if (target_type->id == TypeTableEntryIdMetaType) {
4431// TypeTableEntry *type_arg = const_val->data.x_type;
4432// if (type_arg->id == TypeTableEntryIdStruct) {
4433// target_context = type_arg->data.structure.block_context;
4434// } else if (type_arg->id == TypeTableEntryIdEnum) {
4435// target_context = type_arg->data.enumeration.block_context;
4436// } else if (type_arg->id == TypeTableEntryIdUnion) {
4437// target_context = type_arg->data.unionation.block_context;
4438// } else {
4439// add_node_error(g, *target_node,
4440// buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name)));
4441// return g->builtin_types.entry_invalid;
4442// }
4443// } else {
4444// add_node_error(g, *target_node,
4445// buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name)));
4446// return g->builtin_types.entry_invalid;
4447// }
4448//
4449// bool want_debug_safety;
4450// bool ok = resolve_const_expr_bool(g, import, parent_context, value_node, &want_debug_safety);
4451// if (!ok) {
4452// return g->builtin_types.entry_invalid;
4453// }
4454//
4455// if (target_context->safety_set_node) {
4456// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("debug safety for scope set twice"));
4457// add_error_note(g, msg, target_context->safety_set_node, buf_sprintf("first set here"));
4458// return g->builtin_types.entry_invalid;
4459// }
4460// target_context->safety_set_node = node;
4461//
4462// target_context->safety_off = !want_debug_safety;
4463//
4464// return g->builtin_types.entry_void;
4465//}
48304466
4831 if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) {
4832 ira->instruction_index += 1;
4833 continue;
4834 }
48354467
4836 TypeTableEntry *return_type = ir_analyze_instruction(ira, old_instruction);4468//static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4469// TypeTableEntry *expected_type, AstNode *node)
4470//{
4471//
4472// switch (builtin_fn->id) {
4473// case BuiltinFnIdInvalid:
4474// zig_unreachable();
4475// case BuiltinFnIdAddWithOverflow:
4476// case BuiltinFnIdSubWithOverflow:
4477// case BuiltinFnIdMulWithOverflow:
4478// case BuiltinFnIdShlWithOverflow:
4479// {
4480// AstNode *type_node = node->data.fn_call_expr.params.at(0);
4481// TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node);
4482// if (int_type->id == TypeTableEntryIdInvalid) {
4483// return g->builtin_types.entry_bool;
4484// } else if (int_type->id == TypeTableEntryIdInt) {
4485// AstNode *op1_node = node->data.fn_call_expr.params.at(1);
4486// AstNode *op2_node = node->data.fn_call_expr.params.at(2);
4487// AstNode *result_node = node->data.fn_call_expr.params.at(3);
4488//
4489// analyze_expression(g, import, context, int_type, op1_node);
4490// analyze_expression(g, import, context, int_type, op2_node);
4491// analyze_expression(g, import, context, get_pointer_to_type(g, int_type, false),
4492// result_node);
4493// } else {
4494// add_node_error(g, type_node,
4495// buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name)));
4496// }
4497//
4498// // TODO constant expression evaluation
4499//
4500// return g->builtin_types.entry_bool;
4501// }
4502// case BuiltinFnIdMemcpy:
4503// {
4504// AstNode *dest_node = node->data.fn_call_expr.params.at(0);
4505// AstNode *src_node = node->data.fn_call_expr.params.at(1);
4506// AstNode *len_node = node->data.fn_call_expr.params.at(2);
4507// TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node);
4508// TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, src_node);
4509// analyze_expression(g, import, context, builtin_fn->param_types[2], len_node);
4510//
4511// if (dest_type->id != TypeTableEntryIdInvalid &&
4512// dest_type->id != TypeTableEntryIdPointer)
4513// {
4514// add_node_error(g, dest_node,
4515// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
4516// }
4517//
4518// if (src_type->id != TypeTableEntryIdInvalid &&
4519// src_type->id != TypeTableEntryIdPointer)
4520// {
4521// add_node_error(g, src_node,
4522// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&src_type->name)));
4523// }
4524//
4525// if (dest_type->id == TypeTableEntryIdPointer &&
4526// src_type->id == TypeTableEntryIdPointer)
4527// {
4528// uint64_t dest_align = get_memcpy_align(g, dest_type->data.pointer.child_type);
4529// uint64_t src_align = get_memcpy_align(g, src_type->data.pointer.child_type);
4530// if (dest_align != src_align) {
4531// add_node_error(g, dest_node, buf_sprintf(
4532// "misaligned memcpy, '%s' has alignment '%" PRIu64 ", '%s' has alignment %" PRIu64,
4533// buf_ptr(&dest_type->name), dest_align,
4534// buf_ptr(&src_type->name), src_align));
4535// }
4536// }
4537//
4538// return builtin_fn->return_type;
4539// }
4540// case BuiltinFnIdMemset:
4541// {
4542// AstNode *dest_node = node->data.fn_call_expr.params.at(0);
4543// AstNode *char_node = node->data.fn_call_expr.params.at(1);
4544// AstNode *len_node = node->data.fn_call_expr.params.at(2);
4545// TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node);
4546// analyze_expression(g, import, context, builtin_fn->param_types[1], char_node);
4547// analyze_expression(g, import, context, builtin_fn->param_types[2], len_node);
4548//
4549// if (dest_type->id != TypeTableEntryIdInvalid &&
4550// dest_type->id != TypeTableEntryIdPointer)
4551// {
4552// add_node_error(g, dest_node,
4553// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
4554// }
4555//
4556// return builtin_fn->return_type;
4557// }
4558// case BuiltinFnIdSizeof:
4559// {
4560// AstNode *type_node = node->data.fn_call_expr.params.at(0);
4561// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
4562// if (type_entry->id == TypeTableEntryIdInvalid) {
4563// return g->builtin_types.entry_invalid;
4564// } else if (type_entry->id == TypeTableEntryIdUnreachable) {
4565// add_node_error(g, first_executing_node(type_node),
4566// buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
4567// return g->builtin_types.entry_invalid;
4568// } else {
4569// uint64_t size_in_bytes = type_size(g, type_entry);
4570// bool depends_on_compile_var = (type_entry == g->builtin_types.entry_usize ||
4571// type_entry == g->builtin_types.entry_isize);
4572// return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
4573// size_in_bytes, depends_on_compile_var);
4574// }
4575// }
4576// case BuiltinFnIdAlignof:
4577// {
4578// AstNode *type_node = node->data.fn_call_expr.params.at(0);
4579// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
4580// if (type_entry->id == TypeTableEntryIdInvalid) {
4581// return g->builtin_types.entry_invalid;
4582// } else if (type_entry->id == TypeTableEntryIdUnreachable) {
4583// add_node_error(g, first_executing_node(type_node),
4584// buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name)));
4585// return g->builtin_types.entry_invalid;
4586// } else {
4587// uint64_t align_in_bytes = LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref);
4588// return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
4589// align_in_bytes, false);
4590// }
4591// }
4592// case BuiltinFnIdMaxValue:
4593// return analyze_min_max_value(g, import, context, node,
4594// "no max value available for type '%s'", true);
4595// case BuiltinFnIdMinValue:
4596// return analyze_min_max_value(g, import, context, node,
4597// "no min value available for type '%s'", false);
4598// case BuiltinFnIdMemberCount:
4599// {
4600// AstNode *type_node = node->data.fn_call_expr.params.at(0);
4601// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
4602//
4603// if (type_entry->id == TypeTableEntryIdInvalid) {
4604// return type_entry;
4605// } else if (type_entry->id == TypeTableEntryIdEnum) {
4606// uint64_t value_count = type_entry->data.enumeration.src_field_count;
4607// return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
4608// value_count, false);
4609// } else {
4610// add_node_error(g, node,
4611// buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name)));
4612// return g->builtin_types.entry_invalid;
4613// }
4614// }
4615// case BuiltinFnIdCInclude:
4616// {
4617// if (!context->c_import_buf) {
4618// add_node_error(g, node, buf_sprintf("@c_include valid only in c_import blocks"));
4619// return g->builtin_types.entry_invalid;
4620// }
4621//
4622// AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field;
4623// TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);
4624// TypeTableEntry *resolved_type = analyze_expression(g, import, context, str_type, *str_node);
4625//
4626// if (resolved_type->id == TypeTableEntryIdInvalid) {
4627// return resolved_type;
4628// }
4629//
4630// ConstExprValue *const_str_val = &get_resolved_expr(*str_node)->const_val;
4631//
4632// if (!const_str_val->ok) {
4633// add_node_error(g, *str_node, buf_sprintf("@c_include requires constant expression"));
4634// return g->builtin_types.entry_void;
4635// }
4636//
4637// buf_appendf(context->c_import_buf, "#include <");
4638// ConstExprValue *ptr_field = const_str_val->data.x_struct.fields[0];
4639// uint64_t len = ptr_field->data.x_ptr.len;
4640// for (uint64_t i = 0; i < len; i += 1) {
4641// ConstExprValue *char_val = ptr_field->data.x_ptr.ptr[i];
4642// uint64_t big_c = char_val->data.x_bignum.data.x_uint;
4643// assert(big_c <= UINT8_MAX);
4644// uint8_t c = big_c;
4645// buf_append_char(context->c_import_buf, c);
4646// }
4647// buf_appendf(context->c_import_buf, ">\n");
4648//
4649// return g->builtin_types.entry_void;
4650// }
4651// case BuiltinFnIdCDefine:
4652// zig_panic("TODO");
4653// case BuiltinFnIdCUndef:
4654// zig_panic("TODO");
4655//
4656// case BuiltinFnIdCompileVar:
4657// {
4658// AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field;
4659//
4660// Buf *var_name = resolve_const_expr_str(g, import, context, str_node);
4661// if (!var_name) {
4662// return g->builtin_types.entry_invalid;
4663// }
4664//
4665// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
4666// const_val->ok = true;
4667// const_val->depends_on_compile_var = true;
4668//
4669// if (buf_eql_str(var_name, "is_big_endian")) {
4670// return resolve_expr_const_val_as_bool(g, node, g->is_big_endian, true);
4671// } else if (buf_eql_str(var_name, "is_release")) {
4672// return resolve_expr_const_val_as_bool(g, node, g->is_release_build, true);
4673// } else if (buf_eql_str(var_name, "is_test")) {
4674// return resolve_expr_const_val_as_bool(g, node, g->is_test_build, true);
4675// } else if (buf_eql_str(var_name, "os")) {
4676// const_val->data.x_enum.tag = g->target_os_index;
4677// return g->builtin_types.entry_os_enum;
4678// } else if (buf_eql_str(var_name, "arch")) {
4679// const_val->data.x_enum.tag = g->target_arch_index;
4680// return g->builtin_types.entry_arch_enum;
4681// } else if (buf_eql_str(var_name, "environ")) {
4682// const_val->data.x_enum.tag = g->target_environ_index;
4683// return g->builtin_types.entry_environ_enum;
4684// } else if (buf_eql_str(var_name, "object_format")) {
4685// const_val->data.x_enum.tag = g->target_oformat_index;
4686// return g->builtin_types.entry_oformat_enum;
4687// } else {
4688// add_node_error(g, *str_node,
4689// buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(var_name)));
4690// return g->builtin_types.entry_invalid;
4691// }
4692// }
4693// case BuiltinFnIdConstEval:
4694// {
4695// AstNode **expr_node = node->data.fn_call_expr.params.at(0)->parent_field;
4696// TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_type, *expr_node);
4697// if (resolved_type->id == TypeTableEntryIdInvalid) {
4698// return resolved_type;
4699// }
4700//
4701// ConstExprValue *const_expr_val = &get_resolved_expr(*expr_node)->const_val;
4702//
4703// if (!const_expr_val->ok) {
4704// add_node_error(g, *expr_node, buf_sprintf("unable to evaluate constant expression"));
4705// return g->builtin_types.entry_invalid;
4706// }
4707//
4708// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
4709// *const_val = *const_expr_val;
4710//
4711// return resolved_type;
4712// }
4713// case BuiltinFnIdCtz:
4714// case BuiltinFnIdClz:
4715// {
4716// AstNode *type_node = node->data.fn_call_expr.params.at(0);
4717// TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node);
4718// if (int_type->id == TypeTableEntryIdInvalid) {
4719// return int_type;
4720// } else if (int_type->id == TypeTableEntryIdInt) {
4721// AstNode **expr_node = node->data.fn_call_expr.params.at(1)->parent_field;
4722// TypeTableEntry *resolved_type = analyze_expression(g, import, context, int_type, *expr_node);
4723// if (resolved_type->id == TypeTableEntryIdInvalid) {
4724// return resolved_type;
4725// }
4726//
4727// // TODO const expr eval
4728//
4729// return resolved_type;
4730// } else {
4731// add_node_error(g, type_node,
4732// buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name)));
4733// return g->builtin_types.entry_invalid;
4734// }
4735// }
4736// case BuiltinFnIdImport:
4737// return analyze_import(g, import, context, node);
4738// case BuiltinFnIdCImport:
4739// return analyze_c_import(g, import, context, node);
4740// case BuiltinFnIdErrName:
4741// return analyze_err_name(g, import, context, node);
4742// case BuiltinFnIdBreakpoint:
4743// mark_impure_fn(g, context, node);
4744// return g->builtin_types.entry_void;
4745// case BuiltinFnIdReturnAddress:
4746// case BuiltinFnIdFrameAddress:
4747// mark_impure_fn(g, context, node);
4748// return builtin_fn->return_type;
4749// case BuiltinFnIdEmbedFile:
4750// return analyze_embed_file(g, import, context, node);
4751// case BuiltinFnIdCmpExchange:
4752// return analyze_cmpxchg(g, import, context, node);
4753// case BuiltinFnIdFence:
4754// return analyze_fence(g, import, context, node);
4755// case BuiltinFnIdDivExact:
4756// return analyze_div_exact(g, import, context, node);
4757// case BuiltinFnIdTruncate:
4758// return analyze_truncate(g, import, context, node);
4759// case BuiltinFnIdCompileErr:
4760// return analyze_compile_err(g, import, context, node);
4761// case BuiltinFnIdIntType:
4762// return analyze_int_type(g, import, context, node);
4763// case BuiltinFnIdSetFnTest:
4764// return analyze_set_fn_test(g, import, context, node);
4765// case BuiltinFnIdSetFnNoInline:
4766// return analyze_set_fn_no_inline(g, import, context, node);
4767// case BuiltinFnIdSetFnStaticEval:
4768// return analyze_set_fn_static_eval(g, import, context, node);
4769// case BuiltinFnIdSetFnVisible:
4770// return analyze_set_fn_visible(g, import, context, node);
4771// case BuiltinFnIdSetDebugSafety:
4772// return analyze_set_debug_safety(g, import, context, node);
4773// }
4774// zig_unreachable();
4775//}
48374776
4838 // unreachable instructions do their own control flow.4777//static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry *import,
4839 if (return_type->id == TypeTableEntryIdUnreachable)4778// BlockContext *context, AstNode *node)
4840 continue;4779//{
4780// assert(node->type == NodeTypeContainerInitExpr);
4781//
4782// AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
4783//
4784// ContainerInitKind kind = container_init_expr->kind;
4785//
4786// if (container_init_expr->type->type == NodeTypeFieldAccessExpr) {
4787// container_init_expr->type->data.field_access_expr.container_init_expr_node = node;
4788// }
4789//
4790// TypeTableEntry *container_meta_type = analyze_expression(g, import, context, nullptr,
4791// container_init_expr->type);
4792//
4793// if (container_meta_type->id == TypeTableEntryIdInvalid) {
4794// return g->builtin_types.entry_invalid;
4795// }
4796//
4797// if (node->data.container_init_expr.enum_type) {
4798// get_resolved_expr(node)->const_val = get_resolved_expr(container_init_expr->type)->const_val;
4799// return node->data.container_init_expr.enum_type;
4800// }
4801//
4802// TypeTableEntry *container_type = resolve_type(g, container_init_expr->type);
4803//
4804// if (container_type->id == TypeTableEntryIdInvalid) {
4805// return container_type;
4806// } else if (container_type->id == TypeTableEntryIdStruct &&
4807// !container_type->data.structure.is_slice &&
4808// (kind == ContainerInitKindStruct || (kind == ContainerInitKindArray &&
4809// container_init_expr->entries.length == 0)))
4810// {
4811// StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
4812// codegen->type_entry = container_type;
4813// codegen->source_node = node;
4814//
4815//
4816// size_t expr_field_count = container_init_expr->entries.length;
4817// size_t actual_field_count = container_type->data.structure.src_field_count;
4818//
4819// AstNode *non_const_expr_culprit = nullptr;
4820//
4821// size_t *field_use_counts = allocate<size_t>(actual_field_count);
4822// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
4823// const_val->ok = true;
4824// const_val->data.x_struct.fields = allocate<ConstExprValue*>(actual_field_count);
4825// for (size_t i = 0; i < expr_field_count; i += 1) {
4826// AstNode *val_field_node = container_init_expr->entries.at(i);
4827// assert(val_field_node->type == NodeTypeStructValueField);
4828//
4829// val_field_node->block_context = context;
4830//
4831// TypeStructField *type_field = find_struct_type_field(container_type,
4832// val_field_node->data.struct_val_field.name);
4833//
4834// if (!type_field) {
4835// add_node_error(g, val_field_node,
4836// buf_sprintf("no member named '%s' in '%s'",
4837// buf_ptr(val_field_node->data.struct_val_field.name), buf_ptr(&container_type->name)));
4838// continue;
4839// }
4840//
4841// if (type_field->type_entry->id == TypeTableEntryIdInvalid) {
4842// return g->builtin_types.entry_invalid;
4843// }
4844//
4845// size_t field_index = type_field->src_index;
4846// field_use_counts[field_index] += 1;
4847// if (field_use_counts[field_index] > 1) {
4848// add_node_error(g, val_field_node, buf_sprintf("duplicate field"));
4849// continue;
4850// }
4851//
4852// val_field_node->data.struct_val_field.type_struct_field = type_field;
4853//
4854// analyze_expression(g, import, context, type_field->type_entry,
4855// val_field_node->data.struct_val_field.expr);
4856//
4857// if (const_val->ok) {
4858// ConstExprValue *field_val =
4859// &get_resolved_expr(val_field_node->data.struct_val_field.expr)->const_val;
4860// if (field_val->ok) {
4861// const_val->data.x_struct.fields[field_index] = field_val;
4862// const_val->depends_on_compile_var = const_val->depends_on_compile_var || field_val->depends_on_compile_var;
4863// } else {
4864// const_val->ok = false;
4865// non_const_expr_culprit = val_field_node->data.struct_val_field.expr;
4866// }
4867// }
4868// }
4869// if (!const_val->ok) {
4870// assert(non_const_expr_culprit);
4871// if (context->fn_entry) {
4872// context->fn_entry->struct_val_expr_alloca_list.append(codegen);
4873// } else {
4874// add_node_error(g, non_const_expr_culprit, buf_sprintf("unable to evaluate constant expression"));
4875// }
4876// }
4877//
4878// for (size_t i = 0; i < actual_field_count; i += 1) {
4879// if (field_use_counts[i] == 0) {
4880// add_node_error(g, node,
4881// buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name)));
4882// }
4883// }
4884// return container_type;
4885// } else if (container_type->id == TypeTableEntryIdStruct &&
4886// container_type->data.structure.is_slice &&
4887// kind == ContainerInitKindArray)
4888// {
4889// size_t elem_count = container_init_expr->entries.length;
4890//
4891// TypeTableEntry *pointer_type = container_type->data.structure.fields[0].type_entry;
4892// assert(pointer_type->id == TypeTableEntryIdPointer);
4893// TypeTableEntry *child_type = pointer_type->data.pointer.child_type;
4894//
4895// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
4896// const_val->ok = true;
4897// const_val->data.x_array.fields = allocate<ConstExprValue*>(elem_count);
4898//
4899// for (size_t i = 0; i < elem_count; i += 1) {
4900// AstNode **elem_node = &container_init_expr->entries.at(i);
4901// analyze_expression(g, import, context, child_type, *elem_node);
4902//
4903// if (const_val->ok) {
4904// ConstExprValue *elem_const_val = &get_resolved_expr(*elem_node)->const_val;
4905// if (elem_const_val->ok) {
4906// const_val->data.x_array.fields[i] = elem_const_val;
4907// const_val->depends_on_compile_var = const_val->depends_on_compile_var ||
4908// elem_const_val->depends_on_compile_var;
4909// } else {
4910// const_val->ok = false;
4911// }
4912// }
4913// }
4914//
4915// TypeTableEntry *fixed_size_array_type = get_array_type(g, child_type, elem_count);
4916//
4917// StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
4918// codegen->type_entry = fixed_size_array_type;
4919// codegen->source_node = node;
4920// if (!const_val->ok) {
4921// if (!context->fn_entry) {
4922// add_node_error(g, node,
4923// buf_sprintf("unable to evaluate constant expression"));
4924// } else {
4925// context->fn_entry->struct_val_expr_alloca_list.append(codegen);
4926// }
4927// }
4928//
4929// return fixed_size_array_type;
4930// } else if (container_type->id == TypeTableEntryIdArray) {
4931// zig_panic("TODO array container init");
4932// return container_type;
4933// } else if (container_type->id == TypeTableEntryIdVoid) {
4934// if (container_init_expr->entries.length != 0) {
4935// add_node_error(g, node, buf_sprintf("void expression expects no arguments"));
4936// return g->builtin_types.entry_invalid;
4937// } else {
4938// return resolve_expr_const_val_as_void(g, node);
4939// }
4940// } else {
4941// add_node_error(g, node,
4942// buf_sprintf("type '%s' does not support %s initialization syntax",
4943// buf_ptr(&container_type->name), err_container_init_syntax_name(kind)));
4944// return g->builtin_types.entry_invalid;
4945// }
4946//}
48414947
4842 ira->instruction_index += 1;
4843 }
48444948
4845 return ir_resolve_peer_types(ira, expected_type_source_node, ira->implicit_return_type_list.items,
4846 ira->implicit_return_type_list.length);
4847}
48484949
4849static bool ir_builtin_call_has_side_effects(IrInstructionBuiltinCall *call_instruction) {4950//static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4850 switch (call_instruction->fn->id) {4951// TypeTableEntry *expected_type, AstNode *node)
4851 case BuiltinFnIdInvalid:4952//{
4852 zig_unreachable();4953// assert(node->type == NodeTypeFieldAccessExpr);
4853 case BuiltinFnIdMemcpy:4954//
4854 case BuiltinFnIdMemset:4955// AstNode **struct_expr_node = &node->data.field_access_expr.struct_expr;
4855 case BuiltinFnIdAddWithOverflow:4956// TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, *struct_expr_node);
4856 case BuiltinFnIdSubWithOverflow:4957// Buf *field_name = node->data.field_access_expr.field_name;
4857 case BuiltinFnIdMulWithOverflow:4958//
4858 case BuiltinFnIdShlWithOverflow:4959// if (struct_type->id == TypeTableEntryIdInvalid) {
4859 case BuiltinFnIdCInclude:4960// return struct_type;
4860 case BuiltinFnIdCDefine:4961// } else if (is_container_ref(struct_type)) {
4861 case BuiltinFnIdCUndef:4962// return analyze_container_member_access(g, field_name, node, struct_type);
4862 case BuiltinFnIdImport:4963// } else if (struct_type->id == TypeTableEntryIdArray) {
4863 case BuiltinFnIdCImport:4964// if (buf_eql_str(field_name, "len")) {
4864 case BuiltinFnIdBreakpoint:4965// return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
4865 case BuiltinFnIdEmbedFile:4966// struct_type->data.array.len, false);
4866 case BuiltinFnIdCmpExchange:4967// } else {
4867 case BuiltinFnIdFence:4968// add_node_error(g, node,
4868 case BuiltinFnIdUnreachable:4969// buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
4869 case BuiltinFnIdSetFnTest:4970// buf_ptr(&struct_type->name)));
4870 case BuiltinFnIdSetFnVisible:4971// return g->builtin_types.entry_invalid;
4871 case BuiltinFnIdSetFnStaticEval:4972// }
4872 case BuiltinFnIdSetFnNoInline:4973// } else if (struct_type->id == TypeTableEntryIdMetaType) {
4873 case BuiltinFnIdSetDebugSafety:4974// TypeTableEntry *child_type = resolve_type(g, *struct_expr_node);
4874 return true;4975//
4875 case BuiltinFnIdSizeof:4976// if (child_type->id == TypeTableEntryIdInvalid) {
4876 case BuiltinFnIdAlignof:4977// return g->builtin_types.entry_invalid;
4877 case BuiltinFnIdMaxValue:4978// } else if (child_type->id == TypeTableEntryIdEnum) {
4878 case BuiltinFnIdMinValue:4979// AstNode *container_init_node = node->data.field_access_expr.container_init_expr_node;
4879 case BuiltinFnIdMemberCount:4980// AstNode *value_node;
4880 case BuiltinFnIdTypeof:4981// if (container_init_node) {
4881 case BuiltinFnIdCompileVar:4982// assert(container_init_node->type == NodeTypeContainerInitExpr);
4882 case BuiltinFnIdCompileErr:4983// size_t param_count = container_init_node->data.container_init_expr.entries.length;
4883 case BuiltinFnIdConstEval:4984// if (param_count > 1) {
4884 case BuiltinFnIdCtz:4985// AstNode *first_invalid_node = container_init_node->data.container_init_expr.entries.at(1);
4885 case BuiltinFnIdClz:4986// add_node_error(g, first_executing_node(first_invalid_node),
4886 case BuiltinFnIdErrName:4987// buf_sprintf("enum values accept only one parameter"));
4887 case BuiltinFnIdReturnAddress:4988// return child_type;
4888 case BuiltinFnIdFrameAddress:4989// } else {
4889 case BuiltinFnIdDivExact:4990// if (param_count == 1) {
4890 case BuiltinFnIdTruncate:4991// value_node = container_init_node->data.container_init_expr.entries.at(0);
4891 case BuiltinFnIdIntType:4992// } else {
4892 return false;4993// value_node = nullptr;
4893 }4994// }
4894 zig_unreachable();4995// container_init_node->data.container_init_expr.enum_type = child_type;
4895}4996// }
4997// } else {
4998// value_node = nullptr;
4999// }
5000// return analyze_enum_value_expr(g, import, context, node, value_node, child_type, field_name, node);
5001// } else if (child_type->id == TypeTableEntryIdStruct) {
5002// BlockContext *container_block_context = get_container_block_context(child_type);
5003// auto entry = container_block_context->decl_table.maybe_get(field_name);
5004// AstNode *decl_node = entry ? entry->value : nullptr;
5005// if (decl_node) {
5006// bool pointer_only = false;
5007// return analyze_decl_ref(g, node, decl_node, pointer_only, context, false);
5008// } else {
5009// add_node_error(g, node,
5010// buf_sprintf("container '%s' has no member called '%s'",
5011// buf_ptr(&child_type->name), buf_ptr(field_name)));
5012// return g->builtin_types.entry_invalid;
5013// }
5014// } else if (child_type->id == TypeTableEntryIdPureError) {
5015// return analyze_error_literal_expr(g, import, context, node, field_name);
5016// } else if (child_type->id == TypeTableEntryIdInt) {
5017// bool depends_on_compile_var =
5018// get_resolved_expr(*struct_expr_node)->const_val.depends_on_compile_var;
5019// if (buf_eql_str(field_name, "bit_count")) {
5020// return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
5021// child_type->data.integral.bit_count, depends_on_compile_var);
5022// } else if (buf_eql_str(field_name, "is_signed")) {
5023// return resolve_expr_const_val_as_bool(g, node, child_type->data.integral.is_signed,
5024// depends_on_compile_var);
5025// } else {
5026// add_node_error(g, node,
5027// buf_sprintf("type '%s' has no member called '%s'",
5028// buf_ptr(&child_type->name), buf_ptr(field_name)));
5029// return g->builtin_types.entry_invalid;
5030// }
5031// } else {
5032// add_node_error(g, node,
5033// buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name)));
5034// return g->builtin_types.entry_invalid;
5035// }
5036// } else if (struct_type->id == TypeTableEntryIdNamespace) {
5037// ConstExprValue *const_val = &get_resolved_expr(*struct_expr_node)->const_val;
5038// assert(const_val->ok);
5039// ImportTableEntry *namespace_import = const_val->data.x_import;
5040// AstNode *decl_node = find_decl(namespace_import->block_context, field_name);
5041// if (!decl_node) {
5042// // we must now resolve all the use decls
5043// for (size_t i = 0; i < namespace_import->use_decls.length; i += 1) {
5044// AstNode *use_decl_node = namespace_import->use_decls.at(i);
5045// if (!get_resolved_expr(use_decl_node->data.use.expr)->type_entry) {
5046// preview_use_decl(g, use_decl_node);
5047// }
5048// resolve_use_decl(g, use_decl_node);
5049// }
5050// decl_node = find_decl(namespace_import->block_context, field_name);
5051// }
5052// if (decl_node) {
5053// TopLevelDecl *tld = get_as_top_level_decl(decl_node);
5054// if (tld->visib_mod == VisibModPrivate && decl_node->owner != import) {
5055// ErrorMsg *msg = add_node_error(g, node,
5056// buf_sprintf("'%s' is private", buf_ptr(field_name)));
5057// add_error_note(g, msg, decl_node, buf_sprintf("declared here"));
5058// }
5059// bool pointer_only = false;
5060// return analyze_decl_ref(g, node, decl_node, pointer_only, context,
5061// const_val->depends_on_compile_var);
5062// } else {
5063// const char *import_name = namespace_import->path ? buf_ptr(namespace_import->path) : "(C import)";
5064// add_node_error(g, node,
5065// buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), import_name));
5066// return g->builtin_types.entry_invalid;
5067// }
5068// } else {
5069// add_node_error(g, node,
5070// buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name)));
5071// return g->builtin_types.entry_invalid;
5072// }
5073//}
5074//
48965075
4897bool ir_has_side_effects(IrInstruction *instruction) {5076//static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, BlockContext *block_context,
4898 switch (instruction->id) {5077// AstNode *lhs_node, LValPurpose purpose, bool is_ptr_const)
4899 case IrInstructionIdInvalid:5078//{
4900 zig_unreachable();5079// TypeTableEntry *expected_rhs_type = nullptr;
4901 case IrInstructionIdBr:5080// lhs_node->block_context = block_context;
4902 case IrInstructionIdCondBr:5081// if (lhs_node->type == NodeTypeSymbol) {
4903 case IrInstructionIdSwitchBr:5082// bool pointer_only = purpose == LValPurposeAddressOf;
4904 case IrInstructionIdDeclVar:5083// expected_rhs_type = analyze_symbol_expr(g, import, block_context, nullptr, lhs_node, pointer_only);
4905 case IrInstructionIdStorePtr:5084// if (expected_rhs_type->id == TypeTableEntryIdInvalid) {
4906 case IrInstructionIdCall:5085// return g->builtin_types.entry_invalid;
4907 case IrInstructionIdReturn:5086// }
4908 case IrInstructionIdUnreachable:5087// if (purpose != LValPurposeAddressOf) {
4909 return true;5088// Buf *name = lhs_node->data.symbol_expr.symbol;
4910 case IrInstructionIdPhi:5089// VariableTableEntry *var = find_variable(g, block_context, name);
4911 case IrInstructionIdUnOp:5090// if (var) {
4912 case IrInstructionIdBinOp:5091// if (var->src_is_const) {
4913 case IrInstructionIdLoadPtr:5092// add_node_error(g, lhs_node, buf_sprintf("cannot assign to constant"));
4914 case IrInstructionIdConst:5093// expected_rhs_type = g->builtin_types.entry_invalid;
4915 case IrInstructionIdCast:5094// } else {
4916 case IrInstructionIdContainerInitList:5095// expected_rhs_type = var->type;
4917 case IrInstructionIdContainerInitFields:5096// get_resolved_expr(lhs_node)->variable = var;
4918 case IrInstructionIdFieldPtr:5097// }
4919 case IrInstructionIdElemPtr:5098// } else {
4920 case IrInstructionIdVarPtr:5099// add_node_error(g, lhs_node,
4921 case IrInstructionIdTypeOf:5100// buf_sprintf("use of undeclared identifier '%s'", buf_ptr(name)));
4922 case IrInstructionIdToPtrType:5101// expected_rhs_type = g->builtin_types.entry_invalid;
4923 case IrInstructionIdPtrTypeChild:5102// }
4924 case IrInstructionIdReadField:5103// }
4925 case IrInstructionIdStructFieldPtr:5104// } else if (lhs_node->type == NodeTypeArrayAccessExpr) {
4926 return false;5105// expected_rhs_type = analyze_array_access_expr(g, import, block_context, lhs_node, purpose);
4927 case IrInstructionIdBuiltinCall:5106// } else if (lhs_node->type == NodeTypeFieldAccessExpr) {
4928 return ir_builtin_call_has_side_effects((IrInstructionBuiltinCall *)instruction);5107// expected_rhs_type = analyze_field_access_expr(g, import, block_context, nullptr, lhs_node);
4929 }5108// } else if (lhs_node->type == NodeTypePrefixOpExpr &&
4930 zig_unreachable();5109// lhs_node->data.prefix_op_expr.prefix_op == PrefixOpDereference)
4931}5110// {
5111// assert(purpose == LValPurposeAssign);
5112// AstNode *target_node = lhs_node->data.prefix_op_expr.primary_expr;
5113// TypeTableEntry *type_entry = analyze_expression(g, import, block_context, nullptr, target_node);
5114// if (type_entry->id == TypeTableEntryIdInvalid) {
5115// expected_rhs_type = type_entry;
5116// } else if (type_entry->id == TypeTableEntryIdPointer) {
5117// expected_rhs_type = type_entry->data.pointer.child_type;
5118// } else {
5119// add_node_error(g, target_node,
5120// buf_sprintf("indirection requires pointer operand ('%s' invalid)",
5121// buf_ptr(&type_entry->name)));
5122// expected_rhs_type = g->builtin_types.entry_invalid;
5123// }
5124// } else {
5125// if (purpose == LValPurposeAssign) {
5126// add_node_error(g, lhs_node, buf_sprintf("invalid assignment target"));
5127// expected_rhs_type = g->builtin_types.entry_invalid;
5128// } else if (purpose == LValPurposeAddressOf) {
5129// TypeTableEntry *type_entry = analyze_expression(g, import, block_context, nullptr, lhs_node);
5130// if (type_entry->id == TypeTableEntryIdInvalid) {
5131// expected_rhs_type = g->builtin_types.entry_invalid;
5132// } else if (type_entry->id == TypeTableEntryIdMetaType) {
5133// expected_rhs_type = type_entry;
5134// } else {
5135// add_node_error(g, lhs_node, buf_sprintf("invalid addressof target"));
5136// expected_rhs_type = g->builtin_types.entry_invalid;
5137// }
5138// }
5139// }
5140// assert(expected_rhs_type);
5141// return expected_rhs_type;
5142//}
49325143
4933IrInstruction *ir_exec_const_result(IrExecutable *exec) {
4934 if (exec->basic_block_list.length != 1)
4935 return nullptr;
49365144
4937 IrBasicBlock *bb = exec->basic_block_list.at(0);
4938 if (bb->instruction_list.length != 1)
4939 return nullptr;
49405145
4941 IrInstruction *only_inst = bb->instruction_list.at(0);5146//static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4942 if (only_inst->id != IrInstructionIdReturn)5147// TypeTableEntry *expected_type, AstNode *node)
4943 return nullptr;5148//{
5149// assert(node->type == NodeTypeBinOpExpr);
5150// BinOpType bin_op_type = node->data.bin_op_expr.bin_op;
5151// switch (bin_op_type) {
5152// case BinOpTypeAssign:
5153// case BinOpTypeAssignTimes:
5154// case BinOpTypeAssignTimesWrap:
5155// case BinOpTypeAssignDiv:
5156// case BinOpTypeAssignMod:
5157// case BinOpTypeAssignPlus:
5158// case BinOpTypeAssignPlusWrap:
5159// case BinOpTypeAssignMinus:
5160// case BinOpTypeAssignMinusWrap:
5161// case BinOpTypeAssignBitShiftLeft:
5162// case BinOpTypeAssignBitShiftLeftWrap:
5163// case BinOpTypeAssignBitShiftRight:
5164// case BinOpTypeAssignBitAnd:
5165// case BinOpTypeAssignBitXor:
5166// case BinOpTypeAssignBitOr:
5167// case BinOpTypeAssignBoolAnd:
5168// case BinOpTypeAssignBoolOr:
5169// {
5170// AstNode *lhs_node = node->data.bin_op_expr.op1;
5171//
5172// TypeTableEntry *expected_rhs_type = analyze_lvalue(g, import, context, lhs_node,
5173// LValPurposeAssign, false);
5174// if (expected_rhs_type->id == TypeTableEntryIdInvalid) {
5175// return g->builtin_types.entry_invalid;
5176// } else if (!is_op_allowed(expected_rhs_type, node->data.bin_op_expr.bin_op)) {
5177// if (expected_rhs_type->id != TypeTableEntryIdInvalid) {
5178// add_node_error(g, lhs_node,
5179// buf_sprintf("operator not allowed for type '%s'",
5180// buf_ptr(&expected_rhs_type->name)));
5181// }
5182// }
5183//
5184// analyze_expression(g, import, context, expected_rhs_type, node->data.bin_op_expr.op2);
5185// // not const ok because expression has side effects
5186// return g->builtin_types.entry_void;
5187// }
5188// case BinOpTypeBoolOr:
5189// case BinOpTypeBoolAnd:
5190// return analyze_logic_bin_op_expr(g, import, context, node);
5191// case BinOpTypeCmpEq:
5192// case BinOpTypeCmpNotEq:
5193// case BinOpTypeCmpLessThan:
5194// case BinOpTypeCmpGreaterThan:
5195// case BinOpTypeCmpLessOrEq:
5196// case BinOpTypeCmpGreaterOrEq:
5197// return analyze_bool_bin_op_expr(g, import, context, node);
5198// case BinOpTypeBinOr:
5199// case BinOpTypeBinXor:
5200// case BinOpTypeBinAnd:
5201// case BinOpTypeBitShiftLeft:
5202// case BinOpTypeBitShiftLeftWrap:
5203// case BinOpTypeBitShiftRight:
5204// case BinOpTypeAdd:
5205// case BinOpTypeAddWrap:
5206// case BinOpTypeSub:
5207// case BinOpTypeSubWrap:
5208// case BinOpTypeMult:
5209// case BinOpTypeMultWrap:
5210// case BinOpTypeDiv:
5211// case BinOpTypeMod:
5212// {
5213// AstNode **op1 = node->data.bin_op_expr.op1->parent_field;
5214// AstNode **op2 = node->data.bin_op_expr.op2->parent_field;
5215// TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, *op1);
5216// TypeTableEntry *rhs_type = analyze_expression(g, import, context, nullptr, *op2);
5217//
5218// AstNode *op_nodes[] = {*op1, *op2};
5219// TypeTableEntry *op_types[] = {lhs_type, rhs_type};
5220//
5221// TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, import, context, node,
5222// op_nodes, op_types, 2);
5223//
5224// if (resolved_type->id == TypeTableEntryIdInvalid) {
5225// return resolved_type;
5226// }
5227//
5228// if (resolved_type->id == TypeTableEntryIdInt ||
5229// resolved_type->id == TypeTableEntryIdNumLitInt)
5230// {
5231// // int
5232// } else if ((resolved_type->id == TypeTableEntryIdFloat ||
5233// resolved_type->id == TypeTableEntryIdNumLitFloat) &&
5234// (bin_op_type == BinOpTypeAdd ||
5235// bin_op_type == BinOpTypeSub ||
5236// bin_op_type == BinOpTypeMult ||
5237// bin_op_type == BinOpTypeDiv ||
5238// bin_op_type == BinOpTypeMod))
5239// {
5240// // float
5241// } else {
5242// add_node_error(g, node, buf_sprintf("invalid operands to binary expression: '%s' and '%s'",
5243// buf_ptr(&lhs_type->name), buf_ptr(&rhs_type->name)));
5244// return g->builtin_types.entry_invalid;
5245// }
5246//
5247// ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;
5248// ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;
5249// if (!op1_val->ok || !op2_val->ok) {
5250// return resolved_type;
5251// }
5252//
5253// ConstExprValue *out_val = &get_resolved_expr(node)->const_val;
5254// int err;
5255// if ((err = eval_const_expr_bin_op(op1_val, resolved_type, bin_op_type,
5256// op2_val, resolved_type, out_val)))
5257// {
5258// if (err == ErrorDivByZero) {
5259// add_node_error(g, node, buf_sprintf("division by zero is undefined"));
5260// return g->builtin_types.entry_invalid;
5261// } else if (err == ErrorOverflow) {
5262// add_node_error(g, node, buf_sprintf("value cannot be represented in any integer type"));
5263// return g->builtin_types.entry_invalid;
5264// }
5265// return g->builtin_types.entry_invalid;
5266// }
5267//
5268// num_lit_fits_in_other_type(g, node, resolved_type);
5269// return resolved_type;
5270// }
5271// case BinOpTypeUnwrapMaybe:
5272// {
5273// AstNode *op1 = node->data.bin_op_expr.op1;
5274// AstNode *op2 = node->data.bin_op_expr.op2;
5275// TypeTableEntry *lhs_type = analyze_expression(g, import, context, nullptr, op1);
5276//
5277// if (lhs_type->id == TypeTableEntryIdInvalid) {
5278// return lhs_type;
5279// } else if (lhs_type->id == TypeTableEntryIdMaybe) {
5280// TypeTableEntry *child_type = lhs_type->data.maybe.child_type;
5281// analyze_expression(g, import, context, child_type, op2);
5282// return child_type;
5283// } else {
5284// add_node_error(g, op1,
5285// buf_sprintf("expected maybe type, got '%s'",
5286// buf_ptr(&lhs_type->name)));
5287// return g->builtin_types.entry_invalid;
5288// }
5289// }
5290// case BinOpTypeArrayCat:
5291// {
5292// AstNode **op1 = node->data.bin_op_expr.op1->parent_field;
5293// AstNode **op2 = node->data.bin_op_expr.op2->parent_field;
5294//
5295// TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1);
5296// TypeTableEntry *child_type;
5297// if (op1_type->id == TypeTableEntryIdInvalid) {
5298// return g->builtin_types.entry_invalid;
5299// } else if (op1_type->id == TypeTableEntryIdArray) {
5300// child_type = op1_type->data.array.child_type;
5301// } else if (op1_type->id == TypeTableEntryIdPointer &&
5302// op1_type->data.pointer.child_type == g->builtin_types.entry_u8) {
5303// child_type = op1_type->data.pointer.child_type;
5304// } else {
5305// add_node_error(g, *op1, buf_sprintf("expected array or C string literal, got '%s'",
5306// buf_ptr(&op1_type->name)));
5307// return g->builtin_types.entry_invalid;
5308// }
5309//
5310// TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2);
5311//
5312// if (op2_type->id == TypeTableEntryIdInvalid) {
5313// return g->builtin_types.entry_invalid;
5314// } else if (op2_type->id == TypeTableEntryIdArray) {
5315// if (op2_type->data.array.child_type != child_type) {
5316// add_node_error(g, *op2, buf_sprintf("expected array of type '%s', got '%s'",
5317// buf_ptr(&child_type->name),
5318// buf_ptr(&op2_type->name)));
5319// return g->builtin_types.entry_invalid;
5320// }
5321// } else if (op2_type->id == TypeTableEntryIdPointer &&
5322// op2_type->data.pointer.child_type == g->builtin_types.entry_u8) {
5323// } else {
5324// add_node_error(g, *op2, buf_sprintf("expected array or C string literal, got '%s'",
5325// buf_ptr(&op2_type->name)));
5326// return g->builtin_types.entry_invalid;
5327// }
5328//
5329// ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;
5330// ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;
5331//
5332// AstNode *bad_node;
5333// if (!op1_val->ok) {
5334// bad_node = *op1;
5335// } else if (!op2_val->ok) {
5336// bad_node = *op2;
5337// } else {
5338// bad_node = nullptr;
5339// }
5340// if (bad_node) {
5341// add_node_error(g, bad_node, buf_sprintf("array concatenation requires constant expression"));
5342// return g->builtin_types.entry_invalid;
5343// }
5344//
5345// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
5346// const_val->ok = true;
5347// const_val->depends_on_compile_var = op1_val->depends_on_compile_var ||
5348// op2_val->depends_on_compile_var;
5349//
5350// if (op1_type->id == TypeTableEntryIdArray) {
5351// uint64_t new_len = op1_type->data.array.len + op2_type->data.array.len;
5352// const_val->data.x_array.fields = allocate<ConstExprValue*>(new_len);
5353// uint64_t next_index = 0;
5354// for (uint64_t i = 0; i < op1_type->data.array.len; i += 1, next_index += 1) {
5355// const_val->data.x_array.fields[next_index] = op1_val->data.x_array.fields[i];
5356// }
5357// for (uint64_t i = 0; i < op2_type->data.array.len; i += 1, next_index += 1) {
5358// const_val->data.x_array.fields[next_index] = op2_val->data.x_array.fields[i];
5359// }
5360// return get_array_type(g, child_type, new_len);
5361// } else if (op1_type->id == TypeTableEntryIdPointer) {
5362// if (!op1_val->data.x_ptr.is_c_str) {
5363// add_node_error(g, *op1,
5364// buf_sprintf("expected array or C string literal, got '%s'",
5365// buf_ptr(&op1_type->name)));
5366// return g->builtin_types.entry_invalid;
5367// } else if (!op2_val->data.x_ptr.is_c_str) {
5368// add_node_error(g, *op2,
5369// buf_sprintf("expected array or C string literal, got '%s'",
5370// buf_ptr(&op2_type->name)));
5371// return g->builtin_types.entry_invalid;
5372// }
5373// const_val->data.x_ptr.is_c_str = true;
5374// const_val->data.x_ptr.len = op1_val->data.x_ptr.len + op2_val->data.x_ptr.len - 1;
5375// const_val->data.x_ptr.ptr = allocate<ConstExprValue*>(const_val->data.x_ptr.len);
5376// uint64_t next_index = 0;
5377// for (uint64_t i = 0; i < op1_val->data.x_ptr.len - 1; i += 1, next_index += 1) {
5378// const_val->data.x_ptr.ptr[next_index] = op1_val->data.x_ptr.ptr[i];
5379// }
5380// for (uint64_t i = 0; i < op2_val->data.x_ptr.len; i += 1, next_index += 1) {
5381// const_val->data.x_ptr.ptr[next_index] = op2_val->data.x_ptr.ptr[i];
5382// }
5383// return op1_type;
5384// } else {
5385// zig_unreachable();
5386// }
5387// }
5388// case BinOpTypeArrayMult:
5389// return analyze_array_mult(g, import, context, expected_type, node);
5390// case BinOpTypeInvalid:
5391// zig_unreachable();
5392// }
5393// zig_unreachable();
5394//}
49445395
4945 IrInstructionReturn *ret_inst = (IrInstructionReturn *)only_inst;5396
4946 IrInstruction *value = ret_inst->value;5397//static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4947 assert(value->static_value.ok);5398// AstNode *node)
4948 return value;5399//{
4949}5400// assert(node->type == NodeTypeBinOpExpr);
5401// BinOpType bin_op_type = node->data.bin_op_expr.bin_op;
5402//
5403// AstNode **op1 = &node->data.bin_op_expr.op1;
5404// AstNode **op2 = &node->data.bin_op_expr.op2;
5405// TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1);
5406// TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2);
5407//
5408// AstNode *op_nodes[] = {*op1, *op2};
5409// TypeTableEntry *op_types[] = {op1_type, op2_type};
5410//
5411// TypeTableEntry *resolved_type = resolve_peer_type_compatibility(g, import, context, node,
5412// op_nodes, op_types, 2);
5413//
5414// bool is_equality_cmp = (bin_op_type == BinOpTypeCmpEq || bin_op_type == BinOpTypeCmpNotEq);
5415//
5416// switch (resolved_type->id) {
5417// case TypeTableEntryIdInvalid:
5418// return g->builtin_types.entry_invalid;
5419//
5420// case TypeTableEntryIdNumLitFloat:
5421// case TypeTableEntryIdNumLitInt:
5422// case TypeTableEntryIdInt:
5423// case TypeTableEntryIdFloat:
5424// break;
5425//
5426// case TypeTableEntryIdBool:
5427// case TypeTableEntryIdMetaType:
5428// case TypeTableEntryIdVoid:
5429// case TypeTableEntryIdPointer:
5430// case TypeTableEntryIdPureError:
5431// case TypeTableEntryIdFn:
5432// case TypeTableEntryIdTypeDecl:
5433// case TypeTableEntryIdNamespace:
5434// case TypeTableEntryIdBlock:
5435// case TypeTableEntryIdGenericFn:
5436// if (!is_equality_cmp) {
5437// add_node_error(g, node,
5438// buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
5439// return g->builtin_types.entry_invalid;
5440// }
5441// break;
5442//
5443// case TypeTableEntryIdEnum:
5444// if (!is_equality_cmp || resolved_type->data.enumeration.gen_field_count != 0) {
5445// add_node_error(g, node,
5446// buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
5447// return g->builtin_types.entry_invalid;
5448// }
5449// break;
5450//
5451// case TypeTableEntryIdUnreachable:
5452// case TypeTableEntryIdArray:
5453// case TypeTableEntryIdStruct:
5454// case TypeTableEntryIdUndefLit:
5455// case TypeTableEntryIdNullLit:
5456// case TypeTableEntryIdMaybe:
5457// case TypeTableEntryIdErrorUnion:
5458// case TypeTableEntryIdUnion:
5459// add_node_error(g, node,
5460// buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
5461// return g->builtin_types.entry_invalid;
5462//
5463// case TypeTableEntryIdVar:
5464// zig_unreachable();
5465// }
5466//
5467// ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;
5468// ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;
5469// if (!op1_val->ok || !op2_val->ok) {
5470// return g->builtin_types.entry_bool;
5471// }
5472//
5473//
5474// ConstExprValue *out_val = &get_resolved_expr(node)->const_val;
5475// eval_const_expr_bin_op(op1_val, op1_type, bin_op_type, op2_val, op2_type, out_val);
5476// return g->builtin_types.entry_bool;
5477//
5478//}
5479//
5480////
5481//static TypeTableEntry *analyze_if(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context,
5482// TypeTableEntry *expected_type, AstNode *node,
5483// AstNode **then_node, AstNode **else_node, bool cond_is_const, bool cond_bool_val)
5484//{
5485// if (!*else_node) {
5486// *else_node = create_ast_void_node(g, import, node);
5487// normalize_parent_ptrs(node);
5488// }
5489//
5490// BlockContext *then_context;
5491// BlockContext *else_context;
5492// if (cond_is_const) {
5493// if (cond_bool_val) {
5494// then_context = parent_context;
5495// else_context = new_block_context(node, parent_context);
5496//
5497// else_context->codegen_excluded = true;
5498// } else {
5499// then_context = new_block_context(node, parent_context);
5500// else_context = parent_context;
5501//
5502// then_context->codegen_excluded = true;
5503// }
5504// } else {
5505// then_context = parent_context;
5506// else_context = parent_context;
5507// }
5508//
5509// TypeTableEntry *then_type = nullptr;
5510// TypeTableEntry *else_type = nullptr;
5511//
5512// if (!then_context->codegen_excluded) {
5513// then_type = analyze_expression(g, import, then_context, expected_type, *then_node);
5514// if (then_type->id == TypeTableEntryIdInvalid) {
5515// return g->builtin_types.entry_invalid;
5516// }
5517// }
5518// if (!else_context->codegen_excluded) {
5519// else_type = analyze_expression(g, import, else_context, expected_type, *else_node);
5520// if (else_type->id == TypeTableEntryIdInvalid) {
5521// return g->builtin_types.entry_invalid;
5522// }
5523// }
5524//
5525// TypeTableEntry *result_type;
5526// if (then_context->codegen_excluded) {
5527// result_type = else_type;
5528// } else if (else_context->codegen_excluded) {
5529// result_type = then_type;
5530// } else if (expected_type) {
5531// result_type = (then_type->id == TypeTableEntryIdUnreachable) ? else_type : then_type;
5532// } else {
5533// AstNode *op_nodes[] = {*then_node, *else_node};
5534// TypeTableEntry *op_types[] = {then_type, else_type};
5535// result_type = resolve_peer_type_compatibility(g, import, parent_context, node, op_nodes, op_types, 2);
5536// }
5537//
5538// if (!cond_is_const) {
5539// return add_error_if_type_is_num_lit(g, result_type, node);
5540// }
5541//
5542// ConstExprValue *other_const_val;
5543// if (cond_bool_val) {
5544// other_const_val = &get_resolved_expr(*then_node)->const_val;
5545// } else {
5546// other_const_val = &get_resolved_expr(*else_node)->const_val;
5547// }
5548// if (!other_const_val->ok) {
5549// return add_error_if_type_is_num_lit(g, result_type, node);
5550// }
5551//
5552// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
5553// *const_val = *other_const_val;
5554// // the condition depends on a compile var, so the entire if statement does too
5555// const_val->depends_on_compile_var = true;
5556// return result_type;
5557//}
5558//
5559//static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context,
5560// TypeTableEntry *expected_type, AstNode *node)
5561//{
5562// assert(node->type == NodeTypeIfVarExpr);
5563//
5564// BlockContext *child_context = new_block_context(node, parent_context);
5565//
5566// analyze_variable_declaration_raw(g, import, child_context, node, &node->data.if_var_expr.var_decl, true,
5567// nullptr, node->data.if_var_expr.var_is_ptr);
5568// VariableTableEntry *var = node->data.if_var_expr.var_decl.variable;
5569// if (var->type->id == TypeTableEntryIdInvalid) {
5570// return g->builtin_types.entry_invalid;
5571// }
5572// AstNode *var_expr_node = node->data.if_var_expr.var_decl.expr;
5573// ConstExprValue *var_const_val = &get_resolved_expr(var_expr_node)->const_val;
5574// bool cond_is_const = var_const_val->ok;
5575// bool cond_bool_val = cond_is_const ? (var_const_val->data.x_maybe != nullptr) : false;
5576//
5577//
5578// AstNode **then_node = &node->data.if_var_expr.then_block;
5579// AstNode **else_node = &node->data.if_var_expr.else_node;
5580//
5581// return analyze_if(g, import, child_context, expected_type,
5582// node, then_node, else_node, cond_is_const, cond_bool_val);
5583//}
5584//
5585//static TypeTableEntry *bad_method_call(CodeGen *g, AstNode *node, TypeTableEntry *container_type,
5586// TypeTableEntry *expected_param_type, FnTableEntry *fn_table_entry)
5587//{
5588// ErrorMsg *msg = add_node_error(g, node,
5589// buf_sprintf("function called as method of '%s', but first parameter is of type '%s'",
5590// buf_ptr(&container_type->name),
5591// buf_ptr(&expected_param_type->name)));
5592// if (fn_table_entry) {
5593// add_error_note(g, msg, fn_table_entry->proto_node, buf_sprintf("function declared here"));
5594// }
5595// return g->builtin_types.entry_invalid;
5596//}
5597//
5598//// Before calling this function, set node->data.fn_call_expr.fn_table_entry if the function is known
5599//// at compile time. Otherwise this is a function pointer call.
5600//static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
5601// TypeTableEntry *expected_type, AstNode *node, TypeTableEntry *fn_type,
5602// AstNode *struct_node)
5603//{
5604// assert(node->type == NodeTypeFnCallExpr);
5605//
5606// if (fn_type->id == TypeTableEntryIdInvalid) {
5607// return fn_type;
5608// }
5609//
5610// // The function call might include inline parameters which we need to ignore according to the
5611// // fn_type.
5612// FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
5613// AstNode *generic_proto_node = fn_table_entry ?
5614// fn_table_entry->proto_node->data.fn_proto.generic_proto_node : nullptr;
5615//
5616// // count parameters
5617// size_t struct_node_1_or_0 = struct_node ? 1 : 0;
5618// size_t src_param_count = fn_type->data.fn.fn_type_id.param_count +
5619// (generic_proto_node ? generic_proto_node->data.fn_proto.inline_arg_count : 0);
5620// size_t call_param_count = node->data.fn_call_expr.params.length;
5621// size_t expect_arg_count = src_param_count - struct_node_1_or_0;
5622//
5623// bool ok_invocation = true;
5624//
5625// if (fn_type->data.fn.fn_type_id.is_var_args) {
5626// if (call_param_count < expect_arg_count) {
5627// ok_invocation = false;
5628// add_node_error(g, node,
5629// buf_sprintf("expected at least %zu arguments, got %zu", src_param_count, call_param_count));
5630// }
5631// } else if (expect_arg_count != call_param_count) {
5632// ok_invocation = false;
5633// add_node_error(g, node,
5634// buf_sprintf("expected %zu arguments, got %zu", expect_arg_count, call_param_count));
5635// }
5636//
5637// bool all_args_const_expr = true;
5638//
5639// if (struct_node) {
5640// Expr *struct_expr = get_resolved_expr(struct_node);
5641// ConstExprValue *struct_const_val = &struct_expr->const_val;
5642// if (!struct_const_val->ok) {
5643// all_args_const_expr = false;
5644// }
5645//
5646// FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[0];
5647// TypeTableEntry *expected_param_type = param_info->type;
5648// TypeTableEntry *container_bare_type = container_ref_type(struct_expr->type_entry);
5649// if (is_container_ref(expected_param_type)) {
5650// TypeTableEntry *param_bare_type = container_ref_type(expected_param_type);
5651// if (param_bare_type != container_bare_type) {
5652// return bad_method_call(g, node, container_bare_type, expected_param_type, fn_table_entry);
5653// }
5654// } else {
5655// return bad_method_call(g, node, container_bare_type, expected_param_type, fn_table_entry);
5656// }
5657// }
5658//
5659// // analyze each parameter. in the case of a method, we already analyzed the
5660// // first parameter in order to figure out which struct we were calling a method on.
5661// size_t next_type_i = struct_node_1_or_0;
5662// for (size_t call_i = 0; call_i < call_param_count; call_i += 1) {
5663// size_t proto_i = call_i + struct_node_1_or_0;
5664// AstNode **param_node = &node->data.fn_call_expr.params.at(call_i);
5665// // determine the expected type for each parameter
5666// TypeTableEntry *expected_param_type = nullptr;
5667// if (proto_i < src_param_count) {
5668// if (generic_proto_node &&
5669// generic_proto_node->data.fn_proto.params.at(proto_i)->data.param_decl.is_inline)
5670// {
5671// continue;
5672// }
5673//
5674// FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[next_type_i];
5675// next_type_i += 1;
5676//
5677// expected_param_type = param_info->type;
5678// }
5679// TypeTableEntry *param_type = analyze_expression(g, import, context, expected_param_type, *param_node);
5680// if (param_type->id == TypeTableEntryIdInvalid) {
5681// return param_type;
5682// }
5683//
5684// ConstExprValue *const_arg_val = &get_resolved_expr(*param_node)->const_val;
5685// if (!const_arg_val->ok) {
5686// all_args_const_expr = false;
5687// }
5688// }
5689//
5690// TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
5691//
5692// if (return_type->id == TypeTableEntryIdInvalid) {
5693// return return_type;
5694// }
5695//
5696// ConstExprValue *result_val = &get_resolved_expr(node)->const_val;
5697// if (ok_invocation && fn_table_entry && fn_table_entry->is_pure && fn_table_entry->want_pure != WantPureFalse) {
5698// if (fn_table_entry->anal_state == FnAnalStateReady) {
5699// analyze_fn_body(g, fn_table_entry);
5700// if (fn_table_entry->proto_node->data.fn_proto.skip) {
5701// return g->builtin_types.entry_invalid;
5702// }
5703// }
5704// if (all_args_const_expr) {
5705// if (fn_table_entry->is_pure && fn_table_entry->anal_state == FnAnalStateComplete) {
5706// if (eval_fn(g, node, fn_table_entry, result_val, 1000, struct_node)) {
5707// // function evaluation generated an error
5708// return g->builtin_types.entry_invalid;
5709// }
5710// return return_type;
5711// }
5712// }
5713// }
5714// if (!ok_invocation || !fn_table_entry || !fn_table_entry->is_pure || fn_table_entry->want_pure == WantPureFalse) {
5715// // calling an impure fn is impure
5716// mark_impure_fn(g, context, node);
5717// if (fn_table_entry && fn_table_entry->want_pure == WantPureTrue) {
5718// return g->builtin_types.entry_invalid;
5719// }
5720// }
5721//
5722// // TODO
5723// //if (handle_is_ptr(return_type)) {
5724// // if (context->fn_entry) {
5725// // context->fn_entry->cast_alloca_list.append(node);
5726// // } else if (!result_val->ok) {
5727// // add_node_error(g, node, buf_sprintf("unable to evaluate constant expression"));
5728// // }
5729// //}
5730//
5731// return return_type;
5732//}
5733//
5734//static TypeTableEntry *analyze_fn_call_with_inline_args(CodeGen *g, ImportTableEntry *import,
5735// BlockContext *parent_context, TypeTableEntry *expected_type, AstNode *call_node,
5736// FnTableEntry *fn_table_entry, AstNode *struct_node)
5737//{
5738// assert(call_node->type == NodeTypeFnCallExpr);
5739// assert(fn_table_entry);
5740//
5741// AstNode *decl_node = fn_table_entry->proto_node;
5742//
5743// // count parameters
5744// size_t struct_node_1_or_0 = (struct_node ? 1 : 0);
5745// size_t src_param_count = decl_node->data.fn_proto.params.length;
5746// size_t call_param_count = call_node->data.fn_call_expr.params.length;
5747//
5748// if (src_param_count != call_param_count + struct_node_1_or_0) {
5749// add_node_error(g, call_node,
5750// buf_sprintf("expected %zu arguments, got %zu", src_param_count - struct_node_1_or_0, call_param_count));
5751// return g->builtin_types.entry_invalid;
5752// }
5753//
5754// size_t inline_or_var_type_arg_count = decl_node->data.fn_proto.inline_or_var_type_arg_count;
5755// assert(inline_or_var_type_arg_count > 0);
5756//
5757// BlockContext *child_context = decl_node->owner->block_context;
5758// size_t next_generic_param_index = 0;
5759//
5760// GenericFnTypeId *generic_fn_type_id = allocate<GenericFnTypeId>(1);
5761// generic_fn_type_id->decl_node = decl_node;
5762// generic_fn_type_id->generic_param_count = inline_or_var_type_arg_count;
5763// generic_fn_type_id->generic_params = allocate<GenericParamValue>(inline_or_var_type_arg_count);
5764//
5765// size_t next_impl_i = 0;
5766// for (size_t call_i = 0; call_i < call_param_count; call_i += 1) {
5767// size_t proto_i = call_i + struct_node_1_or_0;
5768// AstNode *generic_param_decl_node = decl_node->data.fn_proto.params.at(proto_i);
5769// assert(generic_param_decl_node->type == NodeTypeParamDecl);
5770//
5771// AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type;
5772// TypeTableEntry *expected_param_type = analyze_type_expr(g, decl_node->owner, child_context,
5773// *generic_param_type_node);
5774// if (expected_param_type->id == TypeTableEntryIdInvalid) {
5775// return expected_param_type;
5776// }
5777//
5778// bool is_var_type = (expected_param_type->id == TypeTableEntryIdVar);
5779// bool is_inline = generic_param_decl_node->data.param_decl.is_inline;
5780// if (!is_inline && !is_var_type) {
5781// next_impl_i += 1;
5782// continue;
5783// }
5784//
5785//
5786// AstNode **param_node = &call_node->data.fn_call_expr.params.at(call_i);
5787// TypeTableEntry *param_type = analyze_expression(g, import, parent_context,
5788// is_var_type ? nullptr : expected_param_type, *param_node);
5789// if (param_type->id == TypeTableEntryIdInvalid) {
5790// return param_type;
5791// }
5792//
5793// // set child_context so that the previous param is in scope
5794// child_context = new_block_context(generic_param_decl_node, child_context);
5795//
5796// ConstExprValue *const_val = &get_resolved_expr(*param_node)->const_val;
5797// if (is_inline && !const_val->ok) {
5798// add_node_error(g, *param_node,
5799// buf_sprintf("unable to evaluate constant expression for inline parameter"));
5800//
5801// return g->builtin_types.entry_invalid;
5802// }
5803//
5804// VariableTableEntry *var = add_local_var_shadowable(g, generic_param_decl_node, decl_node->owner, child_context,
5805// generic_param_decl_node->data.param_decl.name, param_type, true, *param_node, true);
5806// // This generic function instance could be called with anything, so when this variable is read it
5807// // needs to know that it depends on compile time variable data.
5808// var->force_depends_on_compile_var = true;
5809//
5810// GenericParamValue *generic_param_value =
5811// &generic_fn_type_id->generic_params[next_generic_param_index];
5812// generic_param_value->type = param_type;
5813// generic_param_value->node = is_inline ? *param_node : nullptr;
5814// generic_param_value->impl_index = next_impl_i;
5815// next_generic_param_index += 1;
5816//
5817// if (!is_inline) {
5818// next_impl_i += 1;
5819// }
5820// }
5821//
5822// assert(next_generic_param_index == inline_or_var_type_arg_count);
5823//
5824// auto entry = g->generic_table.maybe_get(generic_fn_type_id);
5825// FnTableEntry *impl_fn;
5826// if (entry) {
5827// AstNode *impl_decl_node = entry->value;
5828// assert(impl_decl_node->type == NodeTypeFnProto);
5829// impl_fn = impl_decl_node->data.fn_proto.fn_table_entry;
5830// } else {
5831// AstNode *decl_node = generic_fn_type_id->decl_node;
5832// AstNode *impl_fn_def_node = ast_clone_subtree_special(decl_node->data.fn_proto.fn_def_node,
5833// &g->next_node_index, AstCloneSpecialOmitInlineParams);
5834// AstNode *impl_decl_node = impl_fn_def_node->data.fn_def.fn_proto;
5835// impl_decl_node->data.fn_proto.inline_arg_count = 0;
5836// impl_decl_node->data.fn_proto.inline_or_var_type_arg_count = 0;
5837// impl_decl_node->data.fn_proto.generic_proto_node = decl_node;
5838//
5839// // replace var arg types with actual types
5840// for (size_t generic_arg_i = 0; generic_arg_i < inline_or_var_type_arg_count; generic_arg_i += 1) {
5841// GenericParamValue *generic_param_value = &generic_fn_type_id->generic_params[generic_arg_i];
5842// if (!generic_param_value->node) {
5843// size_t impl_i = generic_param_value->impl_index;
5844// AstNode *impl_param_decl_node = impl_decl_node->data.fn_proto.params.at(impl_i);
5845// assert(impl_param_decl_node->type == NodeTypeParamDecl);
5846//
5847// impl_param_decl_node->data.param_decl.type = create_ast_type_node(g, import,
5848// generic_param_value->type, impl_param_decl_node);
5849// normalize_parent_ptrs(impl_param_decl_node);
5850// }
5851// }
5852//
5853// preview_fn_proto_instance(g, import, impl_decl_node, child_context);
5854// g->generic_table.put(generic_fn_type_id, impl_decl_node);
5855// impl_fn = impl_decl_node->data.fn_proto.fn_table_entry;
5856// }
5857//
5858// call_node->data.fn_call_expr.fn_entry = impl_fn;
5859// return analyze_fn_call_ptr(g, import, parent_context, expected_type, call_node,
5860// impl_fn->type_entry, struct_node);
5861//}
5862//
5863//static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context,
5864// TypeTableEntry *expected_type, AstNode *node, TypeTableEntry *generic_fn_type)
5865//{
5866// assert(node->type == NodeTypeFnCallExpr);
5867// assert(generic_fn_type->id == TypeTableEntryIdGenericFn);
5868//
5869// AstNode *decl_node = generic_fn_type->data.generic_fn.decl_node;
5870// assert(decl_node->type == NodeTypeContainerDecl);
5871// ZigList<AstNode *> *generic_params = &decl_node->data.struct_decl.generic_params;
5872//
5873// size_t expected_param_count = generic_params->length;
5874// size_t actual_param_count = node->data.fn_call_expr.params.length;
5875//
5876// if (actual_param_count != expected_param_count) {
5877// add_node_error(g, first_executing_node(node),
5878// buf_sprintf("expected %zu arguments, got %zu", expected_param_count, actual_param_count));
5879// return g->builtin_types.entry_invalid;
5880// }
5881//
5882// GenericFnTypeId *generic_fn_type_id = allocate<GenericFnTypeId>(1);
5883// generic_fn_type_id->decl_node = decl_node;
5884// generic_fn_type_id->generic_param_count = actual_param_count;
5885// generic_fn_type_id->generic_params = allocate<GenericParamValue>(actual_param_count);
5886//
5887// BlockContext *child_context = decl_node->owner->block_context;
5888// for (size_t i = 0; i < actual_param_count; i += 1) {
5889// AstNode *generic_param_decl_node = generic_params->at(i);
5890// assert(generic_param_decl_node->type == NodeTypeParamDecl);
5891//
5892// AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type;
5893//
5894// TypeTableEntry *expected_param_type = analyze_type_expr(g, decl_node->owner,
5895// child_context, *generic_param_type_node);
5896// if (expected_param_type->id == TypeTableEntryIdInvalid) {
5897// return expected_param_type;
5898// }
5899//
5900//
5901//
5902// AstNode **param_node = &node->data.fn_call_expr.params.at(i);
5903//
5904// TypeTableEntry *param_type = analyze_expression(g, import, parent_context, expected_param_type,
5905// *param_node);
5906// if (param_type->id == TypeTableEntryIdInvalid) {
5907// return param_type;
5908// }
5909//
5910// // set child_context so that the previous param is in scope
5911// child_context = new_block_context(generic_param_decl_node, child_context);
5912//
5913// ConstExprValue *const_val = &get_resolved_expr(*param_node)->const_val;
5914// if (const_val->ok) {
5915// VariableTableEntry *var = add_local_var(g, generic_param_decl_node, decl_node->owner, child_context,
5916// generic_param_decl_node->data.param_decl.name, param_type, true, *param_node);
5917// var->force_depends_on_compile_var = true;
5918// } else {
5919// add_node_error(g, *param_node, buf_sprintf("unable to evaluate constant expression"));
5920//
5921// return g->builtin_types.entry_invalid;
5922// }
5923//
5924// GenericParamValue *generic_param_value = &generic_fn_type_id->generic_params[i];
5925// generic_param_value->type = param_type;
5926// generic_param_value->node = *param_node;
5927// }
5928//
5929// auto entry = g->generic_table.maybe_get(generic_fn_type_id);
5930// if (entry) {
5931// AstNode *impl_decl_node = entry->value;
5932// assert(impl_decl_node->type == NodeTypeContainerDecl);
5933// TypeTableEntry *type_entry = impl_decl_node->data.struct_decl.type_entry;
5934// return resolve_expr_const_val_as_type(g, node, type_entry, false);
5935// }
5936//
5937// // make a type from the generic parameters supplied
5938// assert(decl_node->type == NodeTypeContainerDecl);
5939// AstNode *impl_decl_node = ast_clone_subtree(decl_node, &g->next_node_index);
5940// g->generic_table.put(generic_fn_type_id, impl_decl_node);
5941// scan_struct_decl(g, import, child_context, impl_decl_node);
5942// TypeTableEntry *type_entry = impl_decl_node->data.struct_decl.type_entry;
5943// resolve_struct_type(g, import, type_entry);
5944// return resolve_expr_const_val_as_type(g, node, type_entry, false);
5945//}
5946//
5947//static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
5948// TypeTableEntry *expected_type, AstNode *node)
5949//{
5950// AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
5951//
5952// if (node->data.fn_call_expr.is_builtin) {
5953// zig_panic("moved builtin fn call code to ir.cpp");
5954// }
5955//
5956// TypeTableEntry *invoke_type_entry = analyze_expression(g, import, context, nullptr, fn_ref_expr);
5957// if (invoke_type_entry->id == TypeTableEntryIdInvalid) {
5958// return g->builtin_types.entry_invalid;
5959// }
5960//
5961// // use constant expression evaluator to figure out the function at compile time.
5962// // otherwise we treat this as a function pointer.
5963// ConstExprValue *const_val = &get_resolved_expr(fn_ref_expr)->const_val;
5964//
5965// if (const_val->ok) {
5966// if (invoke_type_entry->id == TypeTableEntryIdMetaType) {
5967// zig_unreachable();
5968// } else if (invoke_type_entry->id == TypeTableEntryIdFn) {
5969// AstNode *struct_node;
5970// if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&
5971// fn_ref_expr->data.field_access_expr.is_member_fn)
5972// {
5973// struct_node = fn_ref_expr->data.field_access_expr.struct_expr;
5974// } else {
5975// struct_node = nullptr;
5976// }
5977//
5978// FnTableEntry *fn_table_entry = const_val->data.x_fn;
5979// node->data.fn_call_expr.fn_entry = fn_table_entry;
5980// return analyze_fn_call_ptr(g, import, context, expected_type, node,
5981// fn_table_entry->type_entry, struct_node);
5982// } else if (invoke_type_entry->id == TypeTableEntryIdGenericFn) {
5983// TypeTableEntry *generic_fn_type = const_val->data.x_type;
5984// AstNode *decl_node = generic_fn_type->data.generic_fn.decl_node;
5985// if (decl_node->type == NodeTypeFnProto) {
5986// AstNode *struct_node;
5987// if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&
5988// fn_ref_expr->data.field_access_expr.is_member_fn)
5989// {
5990// struct_node = fn_ref_expr->data.field_access_expr.struct_expr;
5991// } else {
5992// struct_node = nullptr;
5993// }
5994//
5995// FnTableEntry *fn_table_entry = decl_node->data.fn_proto.fn_table_entry;
5996// if (fn_table_entry->proto_node->data.fn_proto.skip) {
5997// return g->builtin_types.entry_invalid;
5998// }
5999// return analyze_fn_call_with_inline_args(g, import, context, expected_type, node,
6000// fn_table_entry, struct_node);
6001// } else {
6002// return analyze_generic_fn_call(g, import, context, expected_type, node, const_val->data.x_type);
6003// }
6004// } else {
6005// add_node_error(g, fn_ref_expr,
6006// buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name)));
6007// return g->builtin_types.entry_invalid;
6008// }
6009// }
6010//
6011// // function pointer
6012// if (invoke_type_entry->id == TypeTableEntryIdFn) {
6013// return analyze_fn_call_ptr(g, import, context, expected_type, node, invoke_type_entry, nullptr);
6014// } else {
6015// add_node_error(g, fn_ref_expr,
6016// buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name)));
6017// return g->builtin_types.entry_invalid;
6018// }
6019//}
6020//static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6021// TypeTableEntry *expected_type, AstNode *node)
6022//{
6023// AstNode **expr_node = &node->data.switch_expr.expr;
6024// TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node);
6025// ConstExprValue *expr_val = &get_resolved_expr(*expr_node)->const_val;
6026// if (expr_val->ok && !expr_val->depends_on_compile_var) {
6027// add_node_error(g, first_executing_node(*expr_node),
6028// buf_sprintf("value is constant; unnecessary switch statement"));
6029// }
6030// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
6031//
6032//
6033// size_t prong_count = node->data.switch_expr.prongs.length;
6034// AstNode **peer_nodes = allocate<AstNode*>(prong_count);
6035// TypeTableEntry **peer_types = allocate<TypeTableEntry*>(prong_count);
6036//
6037// bool any_errors = false;
6038// if (expr_type->id == TypeTableEntryIdInvalid) {
6039// return expr_type;
6040// } else if (expr_type->id == TypeTableEntryIdUnreachable) {
6041// add_node_error(g, first_executing_node(*expr_node),
6042// buf_sprintf("switch on unreachable expression not allowed"));
6043// return g->builtin_types.entry_invalid;
6044// }
6045//
6046//
6047// size_t *field_use_counts = nullptr;
6048// HashMap<int, AstNode *, int_hash, int_eq> err_use_nodes = {};
6049// if (expr_type->id == TypeTableEntryIdEnum) {
6050// field_use_counts = allocate<size_t>(expr_type->data.enumeration.src_field_count);
6051// } else if (expr_type->id == TypeTableEntryIdErrorUnion) {
6052// err_use_nodes.init(10);
6053// }
6054//
6055// size_t *const_chosen_prong_index = &node->data.switch_expr.const_chosen_prong_index;
6056// *const_chosen_prong_index = SIZE_MAX;
6057// AstNode *else_prong = nullptr;
6058// for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) {
6059// AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
6060//
6061// TypeTableEntry *var_type;
6062// bool var_is_target_expr;
6063// if (prong_node->data.switch_prong.items.length == 0) {
6064// if (else_prong) {
6065// add_node_error(g, prong_node, buf_sprintf("multiple else prongs in switch expression"));
6066// any_errors = true;
6067// } else {
6068// else_prong = prong_node;
6069// }
6070// var_type = expr_type;
6071// var_is_target_expr = true;
6072// if (*const_chosen_prong_index == SIZE_MAX && expr_val->ok) {
6073// *const_chosen_prong_index = prong_i;
6074// }
6075// } else {
6076// bool all_agree_on_var_type = true;
6077// var_type = nullptr;
6078//
6079// for (size_t item_i = 0; item_i < prong_node->data.switch_prong.items.length; item_i += 1) {
6080// AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
6081// if (item_node->type == NodeTypeSwitchRange) {
6082// zig_panic("TODO range in switch statement");
6083// }
6084//
6085// if (expr_type->id == TypeTableEntryIdEnum) {
6086// if (item_node->type == NodeTypeSymbol) {
6087// Buf *field_name = item_node->data.symbol_expr.symbol;
6088// TypeEnumField *type_enum_field = find_enum_type_field(expr_type, field_name);
6089// if (type_enum_field) {
6090// item_node->data.symbol_expr.enum_field = type_enum_field;
6091// if (!var_type) {
6092// var_type = type_enum_field->type_entry;
6093// }
6094// if (type_enum_field->type_entry != var_type) {
6095// all_agree_on_var_type = false;
6096// }
6097// uint32_t field_index = type_enum_field->value;
6098// assert(field_use_counts);
6099// field_use_counts[field_index] += 1;
6100// if (field_use_counts[field_index] > 1) {
6101// add_node_error(g, item_node,
6102// buf_sprintf("duplicate switch value: '%s'",
6103// buf_ptr(type_enum_field->name)));
6104// any_errors = true;
6105// }
6106// if (!any_errors && expr_val->ok) {
6107// if (expr_val->data.x_enum.tag == type_enum_field->value) {
6108// *const_chosen_prong_index = prong_i;
6109// }
6110// }
6111// } else {
6112// add_node_error(g, item_node,
6113// buf_sprintf("enum '%s' has no field '%s'",
6114// buf_ptr(&expr_type->name), buf_ptr(field_name)));
6115// any_errors = true;
6116// }
6117// } else {
6118// add_node_error(g, item_node, buf_sprintf("expected enum tag name"));
6119// any_errors = true;
6120// }
6121// } else if (expr_type->id == TypeTableEntryIdErrorUnion) {
6122// if (item_node->type == NodeTypeSymbol) {
6123// Buf *err_name = item_node->data.symbol_expr.symbol;
6124// bool is_ok_case = buf_eql_str(err_name, "Ok");
6125// auto err_table_entry = is_ok_case ? nullptr: g->error_table.maybe_get(err_name);
6126// if (is_ok_case || err_table_entry) {
6127// uint32_t err_value = is_ok_case ? 0 : err_table_entry->value->value;
6128// item_node->data.symbol_expr.err_value = err_value;
6129// TypeTableEntry *this_var_type;
6130// if (is_ok_case) {
6131// this_var_type = expr_type->data.error.child_type;
6132// } else {
6133// this_var_type = g->builtin_types.entry_pure_error;
6134// }
6135// if (!var_type) {
6136// var_type = this_var_type;
6137// }
6138// if (this_var_type != var_type) {
6139// all_agree_on_var_type = false;
6140// }
6141//
6142// // detect duplicate switch values
6143// auto existing_entry = err_use_nodes.maybe_get(err_value);
6144// if (existing_entry) {
6145// add_node_error(g, existing_entry->value,
6146// buf_sprintf("duplicate switch value: '%s'", buf_ptr(err_name)));
6147// any_errors = true;
6148// } else {
6149// err_use_nodes.put(err_value, item_node);
6150// }
6151//
6152// if (!any_errors && expr_val->ok) {
6153// if (expr_val->data.x_err.err->value == err_value) {
6154// *const_chosen_prong_index = prong_i;
6155// }
6156// }
6157// } else {
6158// add_node_error(g, item_node,
6159// buf_sprintf("use of undeclared error value '%s'", buf_ptr(err_name)));
6160// any_errors = true;
6161// }
6162// } else {
6163// add_node_error(g, item_node, buf_sprintf("expected error value name"));
6164// any_errors = true;
6165// }
6166// } else {
6167// if (!any_errors && expr_val->ok) {
6168// // note: there is now a function in eval.cpp for doing const expr comparison
6169// zig_panic("TODO determine if const exprs are equal");
6170// }
6171// TypeTableEntry *item_type = analyze_expression(g, import, context, expr_type, item_node);
6172// if (item_type->id != TypeTableEntryIdInvalid) {
6173// ConstExprValue *const_val = &get_resolved_expr(item_node)->const_val;
6174// if (!const_val->ok) {
6175// add_node_error(g, item_node,
6176// buf_sprintf("unable to evaluate constant expression"));
6177// any_errors = true;
6178// }
6179// }
6180// }
6181// }
6182// if (!var_type || !all_agree_on_var_type) {
6183// var_type = expr_type;
6184// var_is_target_expr = true;
6185// } else {
6186// var_is_target_expr = false;
6187// }
6188// }
6189//
6190// BlockContext *child_context = new_block_context(node, context);
6191// prong_node->data.switch_prong.block_context = child_context;
6192// AstNode *var_node = prong_node->data.switch_prong.var_symbol;
6193// if (var_node) {
6194// assert(var_node->type == NodeTypeSymbol);
6195// Buf *var_name = var_node->data.symbol_expr.symbol;
6196// var_node->block_context = child_context;
6197// prong_node->data.switch_prong.var = add_local_var(g, var_node, import,
6198// child_context, var_name, var_type, true, nullptr);
6199// prong_node->data.switch_prong.var_is_target_expr = var_is_target_expr;
6200// }
6201// }
6202//
6203// for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) {
6204// AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
6205// BlockContext *child_context = prong_node->data.switch_prong.block_context;
6206// child_context->codegen_excluded = expr_val->ok && (*const_chosen_prong_index != prong_i);
6207//
6208// if (child_context->codegen_excluded) {
6209// peer_types[prong_i] = g->builtin_types.entry_unreachable;
6210// } else {
6211// peer_types[prong_i] = analyze_expression(g, import, child_context, expected_type,
6212// prong_node->data.switch_prong.expr);
6213// }
6214// // This must go after the analyze_expression for
6215// // prong_node->data.switch_prong.expr because of AST rewriting.
6216// peer_nodes[prong_i] = prong_node->data.switch_prong.expr;
6217// }
6218//
6219// if (expr_type->id == TypeTableEntryIdEnum && !else_prong) {
6220// for (uint32_t i = 0; i < expr_type->data.enumeration.src_field_count; i += 1) {
6221// if (field_use_counts[i] == 0) {
6222// add_node_error(g, node,
6223// buf_sprintf("enumeration value '%s' not handled in switch",
6224// buf_ptr(expr_type->data.enumeration.fields[i].name)));
6225// any_errors = true;
6226// }
6227// }
6228// }
6229//
6230// if (any_errors) {
6231// return g->builtin_types.entry_invalid;
6232// }
6233//
6234// if (prong_count == 0) {
6235// add_node_error(g, node, buf_sprintf("switch statement has no prongs"));
6236// return g->builtin_types.entry_invalid;
6237// }
6238//
6239// TypeTableEntry *result_type = resolve_peer_type_compatibility(g, import, context, node,
6240// peer_nodes, peer_types, prong_count);
6241//
6242// if (expr_val->ok) {
6243// assert(*const_chosen_prong_index != SIZE_MAX);
6244//
6245// *const_val = get_resolved_expr(peer_nodes[*const_chosen_prong_index])->const_val;
6246// // the target expr depends on a compile var because we have an error on unnecessary
6247// // switch statement, so the entire switch statement does too
6248// const_val->depends_on_compile_var = true;
6249//
6250// if (!const_val->ok) {
6251// return add_error_if_type_is_num_lit(g, result_type, node);
6252// }
6253// } else {
6254// return add_error_if_type_is_num_lit(g, result_type, node);
6255// }
6256//
6257// return result_type;
6258//}
6259//
6260//static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6261// TypeTableEntry *expected_type, AstNode *node)
6262//{
6263// if (!node->data.return_expr.expr) {
6264// node->data.return_expr.expr = create_ast_void_node(g, import, node);
6265// normalize_parent_ptrs(node);
6266// }
6267//
6268// TypeTableEntry *expected_return_type = get_return_type(context);
6269//
6270// switch (node->data.return_expr.kind) {
6271// case ReturnKindUnconditional:
6272// zig_panic("TODO moved to ir.cpp");
6273// case ReturnKindError:
6274// {
6275// TypeTableEntry *expected_err_type;
6276// if (expected_type) {
6277// expected_err_type = get_error_type(g, expected_type);
6278// } else {
6279// expected_err_type = nullptr;
6280// }
6281// TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_err_type,
6282// node->data.return_expr.expr);
6283// if (resolved_type->id == TypeTableEntryIdInvalid) {
6284// return resolved_type;
6285// } else if (resolved_type->id == TypeTableEntryIdErrorUnion) {
6286// if (expected_return_type->id != TypeTableEntryIdErrorUnion &&
6287// expected_return_type->id != TypeTableEntryIdPureError)
6288// {
6289// ErrorMsg *msg = add_node_error(g, node,
6290// buf_sprintf("%%return statement in function with return type '%s'",
6291// buf_ptr(&expected_return_type->name)));
6292// AstNode *return_type_node = context->fn_entry->fn_def_node->data.fn_def.fn_proto->data.fn_proto.return_type;
6293// add_error_note(g, msg, return_type_node, buf_sprintf("function return type here"));
6294// }
6295//
6296// return resolved_type->data.error.child_type;
6297// } else {
6298// add_node_error(g, node->data.return_expr.expr,
6299// buf_sprintf("expected error type, got '%s'", buf_ptr(&resolved_type->name)));
6300// return g->builtin_types.entry_invalid;
6301// }
6302// }
6303// case ReturnKindMaybe:
6304// {
6305// TypeTableEntry *expected_maybe_type;
6306// if (expected_type) {
6307// expected_maybe_type = get_maybe_type(g, expected_type);
6308// } else {
6309// expected_maybe_type = nullptr;
6310// }
6311// TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_maybe_type,
6312// node->data.return_expr.expr);
6313// if (resolved_type->id == TypeTableEntryIdInvalid) {
6314// return resolved_type;
6315// } else if (resolved_type->id == TypeTableEntryIdMaybe) {
6316// if (expected_return_type->id != TypeTableEntryIdMaybe) {
6317// ErrorMsg *msg = add_node_error(g, node,
6318// buf_sprintf("?return statement in function with return type '%s'",
6319// buf_ptr(&expected_return_type->name)));
6320// AstNode *return_type_node = context->fn_entry->fn_def_node->data.fn_def.fn_proto->data.fn_proto.return_type;
6321// add_error_note(g, msg, return_type_node, buf_sprintf("function return type here"));
6322// }
6323//
6324// return resolved_type->data.maybe.child_type;
6325// } else {
6326// add_node_error(g, node->data.return_expr.expr,
6327// buf_sprintf("expected maybe type, got '%s'", buf_ptr(&resolved_type->name)));
6328// return g->builtin_types.entry_invalid;
6329// }
6330// }
6331// }
6332// zig_unreachable();
6333//}
6334//static TypeTableEntry *analyze_goto_pass1(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6335// TypeTableEntry *expected_type, AstNode *node)
6336//{
6337// assert(node->type == NodeTypeGoto);
6338//
6339// FnTableEntry *fn_table_entry = context->fn_entry;
6340// assert(fn_table_entry);
6341//
6342// fn_table_entry->goto_list.append(node);
6343//
6344// return g->builtin_types.entry_unreachable;
6345//}
6346//
6347//static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6348// AstNode *field_access_node, AstNode *value_node, TypeTableEntry *enum_type, Buf *field_name,
6349// AstNode *out_node)
6350//{
6351// assert(field_access_node->type == NodeTypeFieldAccessExpr);
6352//
6353// TypeEnumField *type_enum_field = find_enum_type_field(enum_type, field_name);
6354// if (type_enum_field->type_entry->id == TypeTableEntryIdInvalid) {
6355// return g->builtin_types.entry_invalid;
6356// }
6357//
6358// field_access_node->data.field_access_expr.type_enum_field = type_enum_field;
6359//
6360// if (type_enum_field) {
6361// if (value_node) {
6362// AstNode **value_node_ptr = value_node->parent_field;
6363// TypeTableEntry *value_type = analyze_expression(g, import, context,
6364// type_enum_field->type_entry, value_node);
6365//
6366// if (value_type->id == TypeTableEntryIdInvalid) {
6367// return g->builtin_types.entry_invalid;
6368// }
6369//
6370// StructValExprCodeGen *codegen = &field_access_node->data.field_access_expr.resolved_struct_val_expr;
6371// codegen->type_entry = enum_type;
6372// codegen->source_node = field_access_node;
6373//
6374// ConstExprValue *value_const_val = &get_resolved_expr(*value_node_ptr)->const_val;
6375// if (value_const_val->ok) {
6376// ConstExprValue *const_val = &get_resolved_expr(out_node)->const_val;
6377// const_val->ok = true;
6378// const_val->data.x_enum.tag = type_enum_field->value;
6379// const_val->data.x_enum.payload = value_const_val;
6380// } else {
6381// if (context->fn_entry) {
6382// context->fn_entry->struct_val_expr_alloca_list.append(codegen);
6383// } else {
6384// add_node_error(g, *value_node_ptr, buf_sprintf("unable to evaluate constant expression"));
6385// return g->builtin_types.entry_invalid;
6386// }
6387// }
6388// } else if (type_enum_field->type_entry->id != TypeTableEntryIdVoid) {
6389// add_node_error(g, field_access_node,
6390// buf_sprintf("enum value '%s.%s' requires parameter of type '%s'",
6391// buf_ptr(&enum_type->name),
6392// buf_ptr(field_name),
6393// buf_ptr(&type_enum_field->type_entry->name)));
6394// } else {
6395// Expr *expr = get_resolved_expr(out_node);
6396// expr->const_val.ok = true;
6397// expr->const_val.data.x_enum.tag = type_enum_field->value;
6398// expr->const_val.data.x_enum.payload = nullptr;
6399// }
6400// } else {
6401// add_node_error(g, field_access_node,
6402// buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
6403// buf_ptr(&enum_type->name)));
6404// }
6405// return enum_type;
6406//}
6407//
6408//static TypeTableEntry *analyze_container_member_access_inner(CodeGen *g,
6409// TypeTableEntry *bare_struct_type, Buf *field_name, AstNode *node, TypeTableEntry *struct_type)
6410//{
6411// assert(node->type == NodeTypeFieldAccessExpr);
6412// if (!is_slice(bare_struct_type)) {
6413// BlockContext *container_block_context = get_container_block_context(bare_struct_type);
6414// assert(container_block_context);
6415// auto entry = container_block_context->decl_table.maybe_get(field_name);
6416// AstNode *fn_decl_node = entry ? entry->value : nullptr;
6417// if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) {
6418// resolve_top_level_decl(g, fn_decl_node, false);
6419// TopLevelDecl *tld = get_as_top_level_decl(fn_decl_node);
6420// if (tld->resolution == TldResolutionInvalid) {
6421// return g->builtin_types.entry_invalid;
6422// }
6423//
6424// node->data.field_access_expr.is_member_fn = true;
6425// FnTableEntry *fn_entry = fn_decl_node->data.fn_proto.fn_table_entry;
6426// if (fn_entry->type_entry->id == TypeTableEntryIdGenericFn) {
6427// return resolve_expr_const_val_as_generic_fn(g, node, fn_entry->type_entry, false);
6428// } else {
6429// return resolve_expr_const_val_as_fn(g, node, fn_entry, false);
6430// }
6431// }
6432// }
6433// add_node_error(g, node,
6434// buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&bare_struct_type->name)));
6435// return g->builtin_types.entry_invalid;
6436//}
6437//
6438//static TypeTableEntry *analyze_container_member_access(CodeGen *g,
6439// Buf *field_name, AstNode *node, TypeTableEntry *struct_type)
6440//{
6441// TypeTableEntry *bare_type = container_ref_type(struct_type);
6442// if (!type_is_complete(bare_type)) {
6443// resolve_container_type(g, bare_type);
6444// }
6445//
6446// node->data.field_access_expr.bare_container_type = bare_type;
6447//
6448// if (bare_type->id == TypeTableEntryIdStruct) {
6449// node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_type, field_name);
6450// if (node->data.field_access_expr.type_struct_field) {
6451// return node->data.field_access_expr.type_struct_field->type_entry;
6452// } else {
6453// return analyze_container_member_access_inner(g, bare_type, field_name,
6454// node, struct_type);
6455// }
6456// } else if (bare_type->id == TypeTableEntryIdEnum) {
6457// node->data.field_access_expr.type_enum_field = find_enum_type_field(bare_type, field_name);
6458// if (node->data.field_access_expr.type_enum_field) {
6459// return node->data.field_access_expr.type_enum_field->type_entry;
6460// } else {
6461// return analyze_container_member_access_inner(g, bare_type, field_name,
6462// node, struct_type);
6463// }
6464// } else if (bare_type->id == TypeTableEntryIdUnion) {
6465// zig_panic("TODO");
6466// } else {
6467// zig_unreachable();
6468// }
6469//}
6470//
6471//static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6472// AstNode *node)
6473//{
6474// assert(node->type == NodeTypeSliceExpr);
6475//
6476// TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr,
6477// node->data.slice_expr.array_ref_expr);
6478//
6479// TypeTableEntry *return_type;
6480//
6481// if (array_type->id == TypeTableEntryIdInvalid) {
6482// return_type = g->builtin_types.entry_invalid;
6483// } else if (array_type->id == TypeTableEntryIdArray) {
6484// return_type = get_slice_type(g, array_type->data.array.child_type,
6485// node->data.slice_expr.is_const);
6486// } else if (array_type->id == TypeTableEntryIdPointer) {
6487// return_type = get_slice_type(g, array_type->data.pointer.child_type,
6488// node->data.slice_expr.is_const);
6489// } else if (array_type->id == TypeTableEntryIdStruct &&
6490// array_type->data.structure.is_slice)
6491// {
6492// return_type = get_slice_type(g,
6493// array_type->data.structure.fields[0].type_entry->data.pointer.child_type,
6494// node->data.slice_expr.is_const);
6495// } else {
6496// add_node_error(g, node,
6497// buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name)));
6498// return_type = g->builtin_types.entry_invalid;
6499// }
6500//
6501// if (return_type->id != TypeTableEntryIdInvalid) {
6502// node->data.slice_expr.resolved_struct_val_expr.type_entry = return_type;
6503// node->data.slice_expr.resolved_struct_val_expr.source_node = node;
6504// context->fn_entry->struct_val_expr_alloca_list.append(&node->data.slice_expr.resolved_struct_val_expr);
6505// }
6506//
6507// analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.slice_expr.start);
6508//
6509// if (node->data.slice_expr.end) {
6510// analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.slice_expr.end);
6511// }
6512//
6513// return return_type;
6514//}
6515//
6516//static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6517// AstNode *node, LValPurpose purpose)
6518//{
6519// TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr,
6520// node->data.array_access_expr.array_ref_expr);
6521//
6522// TypeTableEntry *return_type;
6523//
6524// if (array_type->id == TypeTableEntryIdInvalid) {
6525// return_type = g->builtin_types.entry_invalid;
6526// } else if (array_type->id == TypeTableEntryIdArray) {
6527// if (array_type->data.array.len == 0) {
6528// add_node_error(g, node, buf_sprintf("out of bounds array access"));
6529// }
6530// return_type = array_type->data.array.child_type;
6531// } else if (array_type->id == TypeTableEntryIdPointer) {
6532// if (array_type->data.pointer.is_const && purpose == LValPurposeAssign) {
6533// add_node_error(g, node, buf_sprintf("cannot assign to constant"));
6534// return g->builtin_types.entry_invalid;
6535// }
6536// return_type = array_type->data.pointer.child_type;
6537// } else if (array_type->id == TypeTableEntryIdStruct &&
6538// array_type->data.structure.is_slice)
6539// {
6540// TypeTableEntry *pointer_type = array_type->data.structure.fields[0].type_entry;
6541// if (pointer_type->data.pointer.is_const && purpose == LValPurposeAssign) {
6542// add_node_error(g, node, buf_sprintf("cannot assign to constant"));
6543// return g->builtin_types.entry_invalid;
6544// }
6545// return_type = pointer_type->data.pointer.child_type;
6546// } else {
6547// add_node_error(g, node,
6548// buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name)));
6549// return_type = g->builtin_types.entry_invalid;
6550// }
6551//
6552// analyze_expression(g, import, context, g->builtin_types.entry_usize, node->data.array_access_expr.subscript);
6553//
6554// return return_type;
6555//}
6556//
6557//static TypeTableEntry *analyze_logic_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6558// AstNode *node)
6559//{
6560// assert(node->type == NodeTypeBinOpExpr);
6561// BinOpType bin_op_type = node->data.bin_op_expr.bin_op;
6562//
6563// AstNode *op1 = node->data.bin_op_expr.op1;
6564// AstNode *op2 = node->data.bin_op_expr.op2;
6565// TypeTableEntry *op1_type = analyze_expression(g, import, context, g->builtin_types.entry_bool, op1);
6566// TypeTableEntry *op2_type = analyze_expression(g, import, context, g->builtin_types.entry_bool, op2);
6567//
6568// if (op1_type->id == TypeTableEntryIdInvalid ||
6569// op2_type->id == TypeTableEntryIdInvalid)
6570// {
6571// return g->builtin_types.entry_invalid;
6572// }
6573//
6574// ConstExprValue *op1_val = &get_resolved_expr(op1)->const_val;
6575// ConstExprValue *op2_val = &get_resolved_expr(op2)->const_val;
6576// if (!op1_val->ok || !op2_val->ok) {
6577// return g->builtin_types.entry_bool;
6578// }
6579//
6580// ConstExprValue *out_val = &get_resolved_expr(node)->const_val;
6581// eval_const_expr_bin_op(op1_val, op1_type, bin_op_type, op2_val, op2_type, out_val);
6582// return g->builtin_types.entry_bool;
6583//}
6584//
6585//static TypeTableEntry *analyze_array_mult(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6586// TypeTableEntry *expected_type, AstNode *node)
6587//{
6588// assert(node->type == NodeTypeBinOpExpr);
6589// assert(node->data.bin_op_expr.bin_op == BinOpTypeArrayMult);
6590//
6591// AstNode **op1 = node->data.bin_op_expr.op1->parent_field;
6592// AstNode **op2 = node->data.bin_op_expr.op2->parent_field;
6593//
6594// TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1);
6595// TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2);
6596//
6597// if (op1_type->id == TypeTableEntryIdInvalid ||
6598// op2_type->id == TypeTableEntryIdInvalid)
6599// {
6600// return g->builtin_types.entry_invalid;
6601// }
6602//
6603// ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;
6604// ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;
6605//
6606// AstNode *bad_node;
6607// if (!op1_val->ok) {
6608// bad_node = *op1;
6609// } else if (!op2_val->ok) {
6610// bad_node = *op2;
6611// } else {
6612// bad_node = nullptr;
6613// }
6614// if (bad_node) {
6615// add_node_error(g, bad_node, buf_sprintf("array multiplication requires constant expression"));
6616// return g->builtin_types.entry_invalid;
6617// }
6618//
6619// if (op1_type->id != TypeTableEntryIdArray) {
6620// add_node_error(g, *op1,
6621// buf_sprintf("expected array type, got '%s'", buf_ptr(&op1_type->name)));
6622// return g->builtin_types.entry_invalid;
6623// }
6624//
6625// if (op2_type->id != TypeTableEntryIdNumLitInt &&
6626// op2_type->id != TypeTableEntryIdInt)
6627// {
6628// add_node_error(g, *op2, buf_sprintf("expected integer type, got '%s'", buf_ptr(&op2_type->name)));
6629// return g->builtin_types.entry_invalid;
6630// }
6631//
6632// if (op2_val->data.x_bignum.is_negative) {
6633// add_node_error(g, *op2, buf_sprintf("expected positive number"));
6634// return g->builtin_types.entry_invalid;
6635// }
6636//
6637// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
6638// const_val->ok = true;
6639// const_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
6640//
6641// TypeTableEntry *child_type = op1_type->data.array.child_type;
6642// BigNum old_array_len;
6643// bignum_init_unsigned(&old_array_len, op1_type->data.array.len);
6644//
6645// BigNum new_array_len;
6646// if (bignum_mul(&new_array_len, &old_array_len, &op2_val->data.x_bignum)) {
6647// add_node_error(g, node, buf_sprintf("operation results in overflow"));
6648// return g->builtin_types.entry_invalid;
6649// }
6650//
6651// uint64_t old_array_len_bare = op1_type->data.array.len;
6652// uint64_t operand_amt = op2_val->data.x_bignum.data.x_uint;
6653//
6654// uint64_t new_array_len_bare = new_array_len.data.x_uint;
6655// const_val->data.x_array.fields = allocate<ConstExprValue*>(new_array_len_bare);
6656//
6657// uint64_t i = 0;
6658// for (uint64_t x = 0; x < operand_amt; x += 1) {
6659// for (uint64_t y = 0; y < old_array_len_bare; y += 1) {
6660// const_val->data.x_array.fields[i] = op1_val->data.x_array.fields[y];
6661// i += 1;
6662// }
6663// }
6664//
6665// return get_array_type(g, child_type, new_array_len_bare);
6666//}
6667//
6668//static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *import,
6669// BlockContext *parent_context, TypeTableEntry *expected_type, AstNode *node)
6670//{
6671// AstNode *op1 = node->data.unwrap_err_expr.op1;
6672// AstNode *op2 = node->data.unwrap_err_expr.op2;
6673// AstNode *var_node = node->data.unwrap_err_expr.symbol;
6674//
6675// TypeTableEntry *lhs_type = analyze_expression(g, import, parent_context, nullptr, op1);
6676// if (lhs_type->id == TypeTableEntryIdInvalid) {
6677// return lhs_type;
6678// } else if (lhs_type->id == TypeTableEntryIdErrorUnion) {
6679// TypeTableEntry *child_type = lhs_type->data.error.child_type;
6680// BlockContext *child_context;
6681// if (var_node) {
6682// child_context = new_block_context(node, parent_context);
6683// var_node->block_context = child_context;
6684// Buf *var_name = var_node->data.symbol_expr.symbol;
6685// node->data.unwrap_err_expr.var = add_local_var(g, var_node, import, child_context, var_name,
6686// g->builtin_types.entry_pure_error, true, nullptr);
6687// } else {
6688// child_context = parent_context;
6689// }
6690//
6691// analyze_expression(g, import, child_context, child_type, op2);
6692// return child_type;
6693// } else {
6694// add_node_error(g, op1,
6695// buf_sprintf("expected error type, got '%s'", buf_ptr(&lhs_type->name)));
6696// return g->builtin_types.entry_invalid;
6697// }
6698//}
6699//
6700//
6701//static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,
6702// BlockContext *context, AstNode *source_node,
6703// AstNodeVariableDeclaration *variable_declaration,
6704// bool expr_is_maybe, AstNode *decl_node, bool var_is_ptr)
6705//{
6706// bool is_const = variable_declaration->is_const;
6707// bool is_export = (variable_declaration->top_level_decl.visib_mod == VisibModExport);
6708// bool is_extern = variable_declaration->is_extern;
6709//
6710// TypeTableEntry *explicit_type = nullptr;
6711// if (variable_declaration->type != nullptr) {
6712// explicit_type = analyze_type_expr(g, import, context, variable_declaration->type);
6713// if (explicit_type->id == TypeTableEntryIdUnreachable) {
6714// add_node_error(g, variable_declaration->type,
6715// buf_sprintf("variable of type 'unreachable' not allowed"));
6716// explicit_type = g->builtin_types.entry_invalid;
6717// }
6718// }
6719//
6720// TypeTableEntry *implicit_type = nullptr;
6721// if (explicit_type && explicit_type->id == TypeTableEntryIdInvalid) {
6722// implicit_type = explicit_type;
6723// } else if (variable_declaration->expr) {
6724// implicit_type = analyze_expression(g, import, context, explicit_type, variable_declaration->expr);
6725// if (implicit_type->id == TypeTableEntryIdInvalid) {
6726// // ignore the poison value
6727// } else if (expr_is_maybe) {
6728// if (implicit_type->id == TypeTableEntryIdMaybe) {
6729// if (var_is_ptr) {
6730// // TODO if the expression is constant, can't get pointer to it
6731// implicit_type = get_pointer_to_type(g, implicit_type->data.maybe.child_type, false);
6732// } else {
6733// implicit_type = implicit_type->data.maybe.child_type;
6734// }
6735// } else {
6736// add_node_error(g, variable_declaration->expr, buf_sprintf("expected maybe type"));
6737// implicit_type = g->builtin_types.entry_invalid;
6738// }
6739// } else if (implicit_type->id == TypeTableEntryIdUnreachable) {
6740// add_node_error(g, source_node,
6741// buf_sprintf("variable initialization is unreachable"));
6742// implicit_type = g->builtin_types.entry_invalid;
6743// } else if ((!is_const || is_export) &&
6744// (implicit_type->id == TypeTableEntryIdNumLitFloat ||
6745// implicit_type->id == TypeTableEntryIdNumLitInt))
6746// {
6747// add_node_error(g, source_node, buf_sprintf("unable to infer variable type"));
6748// implicit_type = g->builtin_types.entry_invalid;
6749// } else if (implicit_type->id == TypeTableEntryIdMetaType && !is_const) {
6750// add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));
6751// implicit_type = g->builtin_types.entry_invalid;
6752// }
6753// if (implicit_type->id != TypeTableEntryIdInvalid && !context->fn_entry) {
6754// ConstExprValue *const_val = &get_resolved_expr(variable_declaration->expr)->const_val;
6755// if (!const_val->ok) {
6756// add_node_error(g, first_executing_node(variable_declaration->expr),
6757// buf_sprintf("global variable initializer requires constant expression"));
6758// }
6759// }
6760// } else if (!is_extern) {
6761// add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
6762// implicit_type = g->builtin_types.entry_invalid;
6763// }
6764//
6765// TypeTableEntry *type = explicit_type != nullptr ? explicit_type : implicit_type;
6766// assert(type != nullptr); // should have been caught by the parser
6767//
6768// VariableTableEntry *var = add_local_var(g, source_node, import, context,
6769// variable_declaration->symbol, type, is_const,
6770// expr_is_maybe ? nullptr : variable_declaration->expr);
6771//
6772// variable_declaration->variable = var;
6773//
6774// return var;
6775//}
6776//
6777//static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,
6778// BlockContext *context, TypeTableEntry *expected_type, AstNode *node)
6779//{
6780// AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration;
6781// return analyze_variable_declaration_raw(g, import, context, node, variable_declaration,
6782// false, nullptr, false);
6783//}
6784//
6785//static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6786// TypeTableEntry *expected_type, AstNode *node)
6787//{
6788// AstNode *size_node = node->data.array_type.size;
6789//
6790// TypeTableEntry *child_type = analyze_type_expr_pointer_only(g, import, context,
6791// node->data.array_type.child_type, true);
6792//
6793// if (child_type->id == TypeTableEntryIdUnreachable) {
6794// add_node_error(g, node, buf_create_from_str("array of unreachable not allowed"));
6795// return g->builtin_types.entry_invalid;
6796// } else if (child_type->id == TypeTableEntryIdInvalid) {
6797// return g->builtin_types.entry_invalid;
6798// }
6799//
6800// if (size_node) {
6801// child_type = analyze_type_expr(g, import, context, node->data.array_type.child_type);
6802// TypeTableEntry *size_type = analyze_expression(g, import, context,
6803// g->builtin_types.entry_usize, size_node);
6804// if (size_type->id == TypeTableEntryIdInvalid) {
6805// return g->builtin_types.entry_invalid;
6806// }
6807//
6808// ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
6809// if (const_val->ok) {
6810// if (const_val->data.x_bignum.is_negative) {
6811// add_node_error(g, size_node,
6812// buf_sprintf("array size %s is negative",
6813// buf_ptr(bignum_to_buf(&const_val->data.x_bignum))));
6814// return g->builtin_types.entry_invalid;
6815// } else {
6816// return resolve_expr_const_val_as_type(g, node,
6817// get_array_type(g, child_type, const_val->data.x_bignum.data.x_uint), false);
6818// }
6819// } else if (context->fn_entry) {
6820// return resolve_expr_const_val_as_type(g, node,
6821// get_slice_type(g, child_type, node->data.array_type.is_const), false);
6822// } else {
6823// add_node_error(g, first_executing_node(size_node),
6824// buf_sprintf("unable to evaluate constant expression"));
6825// return g->builtin_types.entry_invalid;
6826// }
6827// } else {
6828// TypeTableEntry *slice_type = get_slice_type(g, child_type, node->data.array_type.is_const);
6829// return resolve_expr_const_val_as_type(g, node, slice_type, false);
6830// }
6831//}
6832//
6833//static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6834// TypeTableEntry *expected_type, AstNode *node)
6835//{
6836// assert(node->type == NodeTypeWhileExpr);
6837//
6838// AstNode **condition_node = &node->data.while_expr.condition;
6839// AstNode *while_body_node = node->data.while_expr.body;
6840// AstNode **continue_expr_node = &node->data.while_expr.continue_expr;
6841//
6842// TypeTableEntry *condition_type = analyze_expression(g, import, context,
6843// g->builtin_types.entry_bool, *condition_node);
6844//
6845// if (*continue_expr_node) {
6846// analyze_expression(g, import, context, g->builtin_types.entry_void, *continue_expr_node);
6847// }
6848//
6849// BlockContext *child_context = new_block_context(node, context);
6850// child_context->parent_loop_node = node;
6851//
6852// analyze_expression(g, import, child_context, g->builtin_types.entry_void, while_body_node);
6853//
6854//
6855// TypeTableEntry *expr_return_type = g->builtin_types.entry_void;
6856//
6857// if (condition_type->id == TypeTableEntryIdInvalid) {
6858// expr_return_type = g->builtin_types.entry_invalid;
6859// } else {
6860// // if the condition is a simple constant expression and there are no break statements
6861// // then the return type is unreachable
6862// ConstExprValue *const_val = &get_resolved_expr(*condition_node)->const_val;
6863// if (const_val->ok) {
6864// if (const_val->data.x_bool) {
6865// node->data.while_expr.condition_always_true = true;
6866// if (!node->data.while_expr.contains_break) {
6867// expr_return_type = g->builtin_types.entry_unreachable;
6868// }
6869// }
6870// }
6871// }
6872//
6873// return expr_return_type;
6874//}
6875//
6876//static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6877// TypeTableEntry *expected_type, AstNode *node)
6878//{
6879// assert(node->type == NodeTypeBreak);
6880//
6881// AstNode *loop_node = context->parent_loop_node;
6882// if (loop_node) {
6883// if (loop_node->type == NodeTypeWhileExpr) {
6884// loop_node->data.while_expr.contains_break = true;
6885// } else if (loop_node->type == NodeTypeForExpr) {
6886// loop_node->data.for_expr.contains_break = true;
6887// } else {
6888// zig_unreachable();
6889// }
6890// } else {
6891// add_node_error(g, node, buf_sprintf("'break' expression outside loop"));
6892// }
6893// return g->builtin_types.entry_unreachable;
6894//}
6895//
6896//static TypeTableEntry *analyze_continue_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6897// TypeTableEntry *expected_type, AstNode *node)
6898//{
6899// AstNode *loop_node = context->parent_loop_node;
6900// if (loop_node) {
6901// if (loop_node->type == NodeTypeWhileExpr) {
6902// loop_node->data.while_expr.contains_continue = true;
6903// } else if (loop_node->type == NodeTypeForExpr) {
6904// loop_node->data.for_expr.contains_continue = true;
6905// } else {
6906// zig_unreachable();
6907// }
6908// } else {
6909// add_node_error(g, node, buf_sprintf("'continue' expression outside loop"));
6910// }
6911// return g->builtin_types.entry_unreachable;
6912//}
6913//
6914//static TypeTableEntry *analyze_defer(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context,
6915// TypeTableEntry *expected_type, AstNode *node)
6916//{
6917// if (!parent_context->fn_entry) {
6918// add_node_error(g, node, buf_sprintf("defer expression outside function definition"));
6919// return g->builtin_types.entry_invalid;
6920// }
6921//
6922// if (!node->data.defer.expr) {
6923// add_node_error(g, node, buf_sprintf("defer expects an expression"));
6924// return g->builtin_types.entry_void;
6925// }
6926//
6927// node->data.defer.child_block = new_block_context(node, parent_context);
6928//
6929// TypeTableEntry *resolved_type = analyze_expression(g, import, parent_context, nullptr,
6930// node->data.defer.expr);
6931// validate_voided_expr(g, node->data.defer.expr, resolved_type);
6932//
6933// return g->builtin_types.entry_void;
6934//}
6935//
6936//static TypeTableEntry *analyze_string_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6937// TypeTableEntry *expected_type, AstNode *node)
6938//{
6939// if (node->data.string_literal.c) {
6940// return resolve_expr_const_val_as_c_string_lit(g, node, node->data.string_literal.buf);
6941// } else {
6942// return resolve_expr_const_val_as_string_lit(g, node, node->data.string_literal.buf);
6943// }
6944//}
6945//
6946//static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context,
6947// TypeTableEntry *expected_type, AstNode *node)
6948//{
6949// BlockContext *child_context = new_block_context(node, parent_context);
6950// node->data.block.child_block = child_context;
6951// TypeTableEntry *return_type = g->builtin_types.entry_void;
6952//
6953// for (size_t i = 0; i < node->data.block.statements.length; i += 1) {
6954// AstNode *child = node->data.block.statements.at(i);
6955// if (child->type == NodeTypeLabel) {
6956// FnTableEntry *fn_table_entry = child_context->fn_entry;
6957// assert(fn_table_entry);
6958//
6959// LabelTableEntry *label = allocate<LabelTableEntry>(1);
6960// label->decl_node = child;
6961// label->entered_from_fallthrough = (return_type->id != TypeTableEntryIdUnreachable);
6962//
6963// child->block_context = child_context;
6964// child->data.label.label_entry = label;
6965// fn_table_entry->all_labels.append(label);
6966//
6967// child_context->label_table.put(child->data.label.name, label);
6968//
6969// return_type = g->builtin_types.entry_void;
6970// continue;
6971// }
6972// if (return_type->id == TypeTableEntryIdUnreachable) {
6973// if (is_node_void_expr(child)) {
6974// // {unreachable;void;void} is allowed.
6975// // ignore void statements once we enter unreachable land.
6976// analyze_expression(g, import, child_context, g->builtin_types.entry_void, child);
6977// continue;
6978// }
6979// add_node_error(g, first_executing_node(child), buf_sprintf("unreachable code"));
6980// break;
6981// }
6982// bool is_last = (i == node->data.block.statements.length - 1);
6983// TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
6984// return_type = analyze_expression(g, import, child_context, passed_expected_type, child);
6985// if (child->type == NodeTypeDefer && return_type->id != TypeTableEntryIdInvalid) {
6986// // defer starts a new block context
6987// child_context = child->data.defer.child_block;
6988// assert(child_context);
6989// }
6990// if (!is_last) {
6991// validate_voided_expr(g, child, return_type);
6992// }
6993// }
6994// node->data.block.nested_block = child_context;
6995//
6996// ConstExprValue *const_val = &node->data.block.resolved_expr.const_val;
6997// if (node->data.block.statements.length == 0) {
6998// const_val->ok = true;
6999// } else if (node->data.block.statements.length == 1) {
7000// AstNode *only_node = node->data.block.statements.at(0);
7001// ConstExprValue *other_const_val = &get_resolved_expr(only_node)->const_val;
7002// if (other_const_val->ok) {
7003// *const_val = *other_const_val;
7004// }
7005// }
7006//
7007// return return_type;
7008//}
7009//
7010//static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
7011// TypeTableEntry *expected_type, AstNode *node)
7012//{
7013// mark_impure_fn(g, context, node);
7014//
7015// node->data.asm_expr.return_count = 0;
7016// TypeTableEntry *return_type = g->builtin_types.entry_void;
7017// for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1) {
7018// AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
7019// if (asm_output->return_type) {
7020// node->data.asm_expr.return_count += 1;
7021// return_type = analyze_type_expr(g, import, context, asm_output->return_type);
7022// if (node->data.asm_expr.return_count > 1) {
7023// add_node_error(g, node,
7024// buf_sprintf("inline assembly allows up to one output value"));
7025// break;
7026// }
7027// } else {
7028// Buf *variable_name = asm_output->variable_name;
7029// VariableTableEntry *var = find_variable(g, context, variable_name);
7030// if (var) {
7031// asm_output->variable = var;
7032// return var->type;
7033// } else {
7034// add_node_error(g, node,
7035// buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
7036// return g->builtin_types.entry_invalid;
7037// }
7038// }
7039// }
7040// for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1) {
7041// AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
7042// analyze_expression(g, import, context, nullptr, asm_input->expr);
7043// }
7044//
7045// return return_type;
7046//}
7047//
7048//static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
7049// BlockContext *context, AstNode *node, Buf *err_name)
7050//{
7051// auto err_table_entry = g->error_table.maybe_get(err_name);
7052//
7053// if (err_table_entry) {
7054// return resolve_expr_const_val_as_err(g, node, err_table_entry->value);
7055// }
7056//
7057// add_node_error(g, node,
7058// buf_sprintf("use of undeclared error value '%s'", buf_ptr(err_name)));
7059//
7060// return g->builtin_types.entry_invalid;
7061//}
7062//
7063//static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
7064// TypeTableEntry *expected_type, AstNode *node, bool pointer_only)
7065//{
7066// Buf *variable_name = node->data.symbol_expr.symbol;
7067//
7068// auto primitive_table_entry = g->primitive_type_table.maybe_get(variable_name);
7069// if (primitive_table_entry) {
7070// return resolve_expr_const_val_as_type(g, node, primitive_table_entry->value, false);
7071// }
7072//
7073// VariableTableEntry *var = find_variable(g, context, variable_name);
7074// if (var) {
7075// TypeTableEntry *var_type = analyze_var_ref(g, node, var, context, false);
7076// return var_type;
7077// }
7078//
7079// AstNode *decl_node = find_decl(context, variable_name);
7080// if (decl_node) {
7081// return analyze_decl_ref(g, node, decl_node, pointer_only, context, false);
7082// }
7083//
7084// if (import->any_imports_failed) {
7085// // skip the error message since we had a failing import in this file
7086// // if an import breaks we don't need 9999 undeclared identifier errors
7087// return g->builtin_types.entry_invalid;
7088// }
7089//
7090// mark_impure_fn(g, context, node);
7091// add_node_error(g, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
7092// return g->builtin_types.entry_invalid;
7093//}
7094//
7095//static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node,
7096// bool pointer_only, BlockContext *block_context, bool depends_on_compile_var)
7097//{
7098// resolve_top_level_decl(g, decl_node, pointer_only);
7099// TopLevelDecl *tld = get_as_top_level_decl(decl_node);
7100// if (tld->resolution == TldResolutionInvalid) {
7101// return g->builtin_types.entry_invalid;
7102// }
7103//
7104// if (decl_node->type == NodeTypeVariableDeclaration) {
7105// VariableTableEntry *var = decl_node->data.variable_declaration.variable;
7106// return analyze_var_ref(g, source_node, var, block_context, depends_on_compile_var);
7107// } else if (decl_node->type == NodeTypeFnProto) {
7108// FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry;
7109// assert(fn_entry->type_entry);
7110// if (fn_entry->type_entry->id == TypeTableEntryIdGenericFn) {
7111// return resolve_expr_const_val_as_generic_fn(g, source_node, fn_entry->type_entry, depends_on_compile_var);
7112// } else {
7113// return resolve_expr_const_val_as_fn(g, source_node, fn_entry, depends_on_compile_var);
7114// }
7115// } else if (decl_node->type == NodeTypeContainerDecl) {
7116// if (decl_node->data.struct_decl.generic_params.length > 0) {
7117// TypeTableEntry *type_entry = decl_node->data.struct_decl.generic_fn_type;
7118// assert(type_entry);
7119// return resolve_expr_const_val_as_generic_fn(g, source_node, type_entry, depends_on_compile_var);
7120// } else {
7121// return resolve_expr_const_val_as_type(g, source_node, decl_node->data.struct_decl.type_entry,
7122// depends_on_compile_var);
7123// }
7124// } else if (decl_node->type == NodeTypeTypeDecl) {
7125// return resolve_expr_const_val_as_type(g, source_node, decl_node->data.type_decl.child_type_entry,
7126// depends_on_compile_var);
7127// } else {
7128// zig_unreachable();
7129// }
7130//}
7131//
7132//static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, VariableTableEntry *var,
7133// BlockContext *context, bool depends_on_compile_var)
7134//{
7135// get_resolved_expr(source_node)->variable = var;
7136// if (!var_is_pure(var, context)) {
7137// mark_impure_fn(g, context, source_node);
7138// }
7139// if (var->src_is_const && var->val_node) {
7140// ConstExprValue *other_const_val = &get_resolved_expr(var->val_node)->const_val;
7141// if (other_const_val->ok) {
7142// return resolve_expr_const_val_as_other_expr(g, source_node, var->val_node,
7143// depends_on_compile_var || var->force_depends_on_compile_var);
7144// }
7145// }
7146// return var->type;
7147//}
7148//
7149//static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *import,
7150// BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node)
7151//{
7152// assert(node->type == NodeTypeNullLiteral);
7153//
7154// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
7155// const_val->ok = true;
7156//
7157// return g->builtin_types.entry_null;
7158//}
7159//
7160//static TypeTableEntry *analyze_undefined_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
7161// TypeTableEntry *expected_type, AstNode *node)
7162//{
7163// assert(node->type == NodeTypeUndefinedLiteral);
7164//
7165// Expr *expr = get_resolved_expr(node);
7166// ConstExprValue *const_val = &expr->const_val;
7167//
7168// const_val->ok = true;
7169// const_val->special = ConstValSpecialUndef;
7170//
7171// return expected_type ? expected_type : g->builtin_types.entry_undef;
7172//}
7173//
7174//static TypeTableEntry *analyze_zeroes_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
7175// TypeTableEntry *expected_type, AstNode *node)
7176//{
7177// Expr *expr = get_resolved_expr(node);
7178// ConstExprValue *const_val = &expr->const_val;
7179//
7180// const_val->ok = true;
7181// const_val->special = ConstValSpecialZeroes;
7182//
7183// return expected_type ? expected_type : g->builtin_types.entry_undef;
7184//}
7185//
7186//static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import,
7187// BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node)
7188//{
7189// return resolve_expr_const_val_as_bignum(g, node, expected_type, node->data.number_literal.bignum, false);
7190//}
7191//
7192//static TypeTableEntry *analyze_fn_proto_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
7193// TypeTableEntry *expected_type, AstNode *node)
7194//{
7195// TypeTableEntry *type_entry = analyze_fn_proto_type(g, import, context, expected_type, node,
7196// false, false, nullptr);
7197//
7198// if (type_entry->id == TypeTableEntryIdInvalid) {
7199// return type_entry;
7200// }
7201//
7202// return resolve_expr_const_val_as_type(g, node, type_entry, false);
7203//}
7204//
7205//static bool var_is_pure(VariableTableEntry *var, BlockContext *context) {
7206// if (var->block_context->fn_entry == context->fn_entry) {
7207// // variable was declared in the current function, so it's OK.
7208// return true;
7209// }
7210// return var->src_is_const && var->type->deep_const;
7211//}
7212//
7213//static void validate_voided_expr(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry) {
7214// if (type_entry->id == TypeTableEntryIdMetaType) {
7215// add_node_error(g, first_executing_node(source_node), buf_sprintf("expected expression, found type"));
7216// } else if (type_entry->id == TypeTableEntryIdErrorUnion) {
7217// add_node_error(g, first_executing_node(source_node), buf_sprintf("statement ignores error value"));
7218// }
7219//}
7220//
src/ir_print.cpp+17-16
...@@ -78,6 +78,12 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const...@@ -78,6 +78,12 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
78 fprintf(irp->f, "%s", buf_ptr(&fn_entry->symbol_name));78 fprintf(irp->f, "%s", buf_ptr(&fn_entry->symbol_name));
79 break;79 break;
80 }80 }
81 case TypeTableEntryIdBlock:
82 {
83 AstNode *node = const_val->data.x_block->node;
84 fprintf(irp->f, "(scope:%zu:%zu)", node->line + 1, node->column + 1);
85 break;
86 }
81 case TypeTableEntryIdVar:87 case TypeTableEntryIdVar:
82 case TypeTableEntryIdFloat:88 case TypeTableEntryIdFloat:
83 case TypeTableEntryIdArray:89 case TypeTableEntryIdArray:
...@@ -91,7 +97,6 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const...@@ -91,7 +97,6 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
91 case TypeTableEntryIdUnion:97 case TypeTableEntryIdUnion:
92 case TypeTableEntryIdTypeDecl:98 case TypeTableEntryIdTypeDecl:
93 case TypeTableEntryIdNamespace:99 case TypeTableEntryIdNamespace:
94 case TypeTableEntryIdBlock:
95 case TypeTableEntryIdGenericFn:100 case TypeTableEntryIdGenericFn:
96 zig_panic("TODO render more constant types in IR printer");101 zig_panic("TODO render more constant types in IR printer");
97 }102 }
...@@ -263,18 +268,6 @@ static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {...@@ -263,18 +268,6 @@ static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
263 fprintf(irp->f, ")");268 fprintf(irp->f, ")");
264}269}
265270
266static void ir_print_builtin_call(IrPrint *irp, IrInstructionBuiltinCall *call_instruction) {
267 fprintf(irp->f, "@%s(", buf_ptr(&call_instruction->fn->name));
268 for (size_t i = 0; i < call_instruction->fn->param_count; i += 1) {
269 IrInstruction *arg = call_instruction->args[i];
270 if (i != 0)
271 fprintf(irp->f, ", ");
272 ir_print_other_instruction(irp, arg);
273 }
274 fprintf(irp->f, ")");
275}
276
277
278static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {271static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {
279 const char *inline_kw = cond_br_instruction->is_inline ? "inline " : "";272 const char *inline_kw = cond_br_instruction->is_inline ? "inline " : "";
280 fprintf(irp->f, "%sif (", inline_kw);273 fprintf(irp->f, "%sif (", inline_kw);
...@@ -393,6 +386,14 @@ static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr...@@ -393,6 +386,14 @@ static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr
393 fprintf(irp->f, ")");386 fprintf(irp->f, ")");
394}387}
395388
389static void ir_print_set_fn_test(IrPrint *irp, IrInstructionSetFnTest *instruction) {
390 fprintf(irp->f, "@setFnTest(");
391 ir_print_other_instruction(irp, instruction->fn_value);
392 fprintf(irp->f, ", ");
393 ir_print_other_instruction(irp, instruction->is_test);
394 fprintf(irp->f, ")");
395}
396
396static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {397static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
397 ir_print_prefix(irp, instruction);398 ir_print_prefix(irp, instruction);
398 switch (instruction->id) {399 switch (instruction->id) {
...@@ -425,9 +426,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -425,9 +426,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
425 case IrInstructionIdBr:426 case IrInstructionIdBr:
426 ir_print_br(irp, (IrInstructionBr *)instruction);427 ir_print_br(irp, (IrInstructionBr *)instruction);
427 break;428 break;
428 case IrInstructionIdBuiltinCall:
429 ir_print_builtin_call(irp, (IrInstructionBuiltinCall *)instruction);
430 break;
431 case IrInstructionIdPhi:429 case IrInstructionIdPhi:
432 ir_print_phi(irp, (IrInstructionPhi *)instruction);430 ir_print_phi(irp, (IrInstructionPhi *)instruction);
433 break;431 break;
...@@ -470,6 +468,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -470,6 +468,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
470 case IrInstructionIdStructFieldPtr:468 case IrInstructionIdStructFieldPtr:
471 ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction);469 ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction);
472 break;470 break;
471 case IrInstructionIdSetFnTest:
472 ir_print_set_fn_test(irp, (IrInstructionSetFnTest *)instruction);
473 break;
473 case IrInstructionIdSwitchBr:474 case IrInstructionIdSwitchBr:
474 zig_panic("TODO print more IR instructions");475 zig_panic("TODO print more IR instructions");
475 }476 }
src/parseh.cpp+1-3
...@@ -230,9 +230,7 @@ static AstNode *create_type_decl_node(Context *c, const char *name, AstNode *chi...@@ -230,9 +230,7 @@ static AstNode *create_type_decl_node(Context *c, const char *name, AstNode *chi
230}230}
231231
232static AstNode *make_type_node(Context *c, TypeTableEntry *type_entry) {232static AstNode *make_type_node(Context *c, TypeTableEntry *type_entry) {
233 AstNode *node = create_node(c, NodeTypeSymbol);233 zig_panic("TODO bypass AST in parseh");
234 node->data.symbol_expr.override_type_entry = type_entry;
235 return node;
236}234}
237235
238static AstNode *create_fn_proto_node(Context *c, Buf *name, TypeTableEntry *fn_type) {236static AstNode *create_fn_proto_node(Context *c, Buf *name, TypeTableEntry *fn_type) {