| author | |
| committer | |
| log | 5161d70620342749b1995fdaabb39220654cc941 |
| tree | ba940c1a85386f1866cd75aab67809b4c0c95755 |
| parent | 40ca39d3d5a556e3b5d7298e3a5182f4351bdd17 |
14 files changed, 949 insertions(+), 499 deletions(-)
doc/langref.html.in+8-8| ... | @@ -1281,7 +1281,7 @@ const ptr = &x; | ... | @@ -1281,7 +1281,7 @@ const ptr = &x; |
| 1281 | <pre><code>x() x[] x.y | 1281 | <pre><code>x() x[] x.y |
| 1282 | !x -x -%x ~x *x &amp;x ?x %x ??x | 1282 | !x -x -%x ~x *x &amp;x ?x %x ??x |
| 1283 | x{} | 1283 | x{} |
| 1284 | * / % ** *% | 1284 | ! * / % ** *% |
| 1285 | + - ++ +% -% | 1285 | + - ++ +% -% |
| 1286 | &lt;&lt; &gt;&gt; | 1286 | &lt;&lt; &gt;&gt; |
| 1287 | &amp; | 1287 | &amp; |
| ... | @@ -5566,14 +5566,12 @@ fn readU32Be() u32 {} | ... | @@ -5566,14 +5566,12 @@ fn readU32Be() u32 {} |
| 5566 | {#header_open|Grammar#} | 5566 | {#header_open|Grammar#} |
| 5567 | <pre><code class="nohighlight">Root = many(TopLevelItem) EOF | 5567 | <pre><code class="nohighlight">Root = many(TopLevelItem) EOF |
| 5568 | 5568 | ||
| 5569 | TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl | 5569 | TopLevelItem = CompTimeExpression(Block) | TopLevelDecl | TestDecl |
| 5570 | 5570 | ||
| 5571 | TestDecl = "test" String Block | 5571 | TestDecl = "test" String Block |
| 5572 | 5572 | ||
| 5573 | TopLevelDecl = option("pub") (FnDef | ExternDecl | GlobalVarDecl | UseDecl) | 5573 | TopLevelDecl = option("pub") (FnDef | ExternDecl | GlobalVarDecl | UseDecl) |
| 5574 | 5574 | ||
| 5575 | ErrorValueDecl = "error" Symbol ";" | ||
| 5576 | |||
| 5577 | GlobalVarDecl = option("export") VariableDeclaration ";" | 5575 | GlobalVarDecl = option("export") VariableDeclaration ";" |
| 5578 | 5576 | ||
| 5579 | LocalVarDecl = option("comptime") VariableDeclaration | 5577 | LocalVarDecl = option("comptime") VariableDeclaration |
| ... | @@ -5588,7 +5586,7 @@ UseDecl = "use" Expression ";" | ... | @@ -5588,7 +5586,7 @@ UseDecl = "use" Expression ";" |
| 5588 | 5586 | ||
| 5589 | ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";" | 5587 | ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";" |
| 5590 | 5588 | ||
| 5591 | FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") TypeExpr | 5589 | FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr |
| 5592 | 5590 | ||
| 5593 | FnDef = option("inline" | "export") FnProto Block | 5591 | FnDef = option("inline" | "export") FnProto Block |
| 5594 | 5592 | ||
| ... | @@ -5682,7 +5680,7 @@ MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression | | ... | @@ -5682,7 +5680,7 @@ MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression | |
| 5682 | 5680 | ||
| 5683 | CurlySuffixExpression = TypeExpr option(ContainerInitExpression) | 5681 | CurlySuffixExpression = TypeExpr option(ContainerInitExpression) |
| 5684 | 5682 | ||
| 5685 | MultiplyOperator = "*" | "/" | "%" | "**" | "*%" | 5683 | MultiplyOperator = "!" | "*" | "/" | "%" | "**" | "*%" |
| 5686 | 5684 | ||
| 5687 | PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression | 5685 | PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression |
| 5688 | 5686 | ||
| ... | @@ -5702,9 +5700,9 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",") | ... | @@ -5702,9 +5700,9 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",") |
| 5702 | 5700 | ||
| 5703 | StructLiteralField = "." Symbol "=" Expression | 5701 | StructLiteralField = "." Symbol "=" Expression |
| 5704 | 5702 | ||
| 5705 | PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "%" | "??" | "-%" | "try" | 5703 | PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" |
| 5706 | 5704 | ||
| 5707 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." Symbol) | ContainerDecl | ("continue" option(":" Symbol)) | 5705 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl |
| 5708 | 5706 | ||
| 5709 | ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":" Integer ":" Integer) ")")) option("const") option("volatile") TypeExpr | 5707 | ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":" Integer ":" Integer) ")")) option("const") option("volatile") TypeExpr |
| 5710 | 5708 | ||
| ... | @@ -5712,6 +5710,8 @@ GroupedExpression = "(" Expression ")" | ... | @@ -5712,6 +5710,8 @@ GroupedExpression = "(" Expression ")" |
| 5712 | 5710 | ||
| 5713 | KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" | 5711 | KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" |
| 5714 | 5712 | ||
| 5713 | ErrorSetDecl = "error" "{" list(Symbol, ",") "}" | ||
| 5714 | |||
| 5715 | ContainerDecl = option("extern" | "packed") | 5715 | ContainerDecl = option("extern" | "packed") |
| 5716 | ("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression))) | 5716 | ("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression))) |
| 5717 | "{" many(ContainerMember) "}"</code></pre> | 5717 | "{" many(ContainerMember) "}"</code></pre> |
src/all_types.hpp+41-19| ... | @@ -236,7 +236,7 @@ struct ConstExprValue { | ... | @@ -236,7 +236,7 @@ struct ConstExprValue { |
| 236 | TypeTableEntry *x_type; | 236 | TypeTableEntry *x_type; |
| 237 | ConstExprValue *x_maybe; | 237 | ConstExprValue *x_maybe; |
| 238 | ConstErrValue x_err_union; | 238 | ConstErrValue x_err_union; |
| 239 | ErrorTableEntry *x_pure_err; | 239 | ErrorTableEntry *x_err_set; |
| 240 | BigInt x_enum_tag; | 240 | BigInt x_enum_tag; |
| 241 | ConstStructValue x_struct; | 241 | ConstStructValue x_struct; |
| 242 | ConstUnionValue x_union; | 242 | ConstUnionValue x_union; |
| ... | @@ -353,7 +353,6 @@ enum NodeType { | ... | @@ -353,7 +353,6 @@ enum NodeType { |
| 353 | NodeTypeReturnExpr, | 353 | NodeTypeReturnExpr, |
| 354 | NodeTypeDefer, | 354 | NodeTypeDefer, |
| 355 | NodeTypeVariableDeclaration, | 355 | NodeTypeVariableDeclaration, |
| 356 | NodeTypeErrorValueDecl, | ||
| 357 | NodeTypeTestDecl, | 356 | NodeTypeTestDecl, |
| 358 | NodeTypeBinOpExpr, | 357 | NodeTypeBinOpExpr, |
| 359 | NodeTypeUnwrapErrorExpr, | 358 | NodeTypeUnwrapErrorExpr, |
| ... | @@ -393,6 +392,7 @@ enum NodeType { | ... | @@ -393,6 +392,7 @@ enum NodeType { |
| 393 | NodeTypeVarLiteral, | 392 | NodeTypeVarLiteral, |
| 394 | NodeTypeIfErrorExpr, | 393 | NodeTypeIfErrorExpr, |
| 395 | NodeTypeTestExpr, | 394 | NodeTypeTestExpr, |
| 395 | NodeTypeErrorSetDecl, | ||
| 396 | }; | 396 | }; |
| 397 | 397 | ||
| 398 | struct AstNodeRoot { | 398 | struct AstNodeRoot { |
| ... | @@ -424,6 +424,8 @@ struct AstNodeFnProto { | ... | @@ -424,6 +424,8 @@ struct AstNodeFnProto { |
| 424 | AstNode *align_expr; | 424 | AstNode *align_expr; |
| 425 | // populated if the "section(S)" is present | 425 | // populated if the "section(S)" is present |
| 426 | AstNode *section_expr; | 426 | AstNode *section_expr; |
| 427 | |||
| 428 | bool auto_err_set; | ||
| 427 | }; | 429 | }; |
| 428 | 430 | ||
| 429 | struct AstNodeFnDef { | 431 | struct AstNodeFnDef { |
| ... | @@ -486,12 +488,6 @@ struct AstNodeVariableDeclaration { | ... | @@ -486,12 +488,6 @@ struct AstNodeVariableDeclaration { |
| 486 | AstNode *section_expr; | 488 | AstNode *section_expr; |
| 487 | }; | 489 | }; |
| 488 | 490 | ||
| 489 | struct AstNodeErrorValueDecl { | ||
| 490 | Buf *name; | ||
| 491 | |||
| 492 | ErrorTableEntry *err; | ||
| 493 | }; | ||
| 494 | |||
| 495 | struct AstNodeTestDecl { | 491 | struct AstNodeTestDecl { |
| 496 | Buf *name; | 492 | Buf *name; |
| 497 | 493 | ||
| ... | @@ -540,6 +536,7 @@ enum BinOpType { | ... | @@ -540,6 +536,7 @@ enum BinOpType { |
| 540 | BinOpTypeUnwrapMaybe, | 536 | BinOpTypeUnwrapMaybe, |
| 541 | BinOpTypeArrayCat, | 537 | BinOpTypeArrayCat, |
| 542 | BinOpTypeArrayMult, | 538 | BinOpTypeArrayMult, |
| 539 | BinOpTypeErrorUnion, | ||
| 543 | }; | 540 | }; |
| 544 | 541 | ||
| 545 | struct AstNodeBinOpExpr { | 542 | struct AstNodeBinOpExpr { |
| ... | @@ -595,7 +592,6 @@ enum PrefixOp { | ... | @@ -595,7 +592,6 @@ enum PrefixOp { |
| 595 | PrefixOpNegationWrap, | 592 | PrefixOpNegationWrap, |
| 596 | PrefixOpDereference, | 593 | PrefixOpDereference, |
| 597 | PrefixOpMaybe, | 594 | PrefixOpMaybe, |
| 598 | PrefixOpError, | ||
| 599 | PrefixOpUnwrapMaybe, | 595 | PrefixOpUnwrapMaybe, |
| 600 | }; | 596 | }; |
| 601 | 597 | ||
| ... | @@ -762,6 +758,10 @@ struct AstNodeContainerDecl { | ... | @@ -762,6 +758,10 @@ struct AstNodeContainerDecl { |
| 762 | bool auto_enum; // union(enum) | 758 | bool auto_enum; // union(enum) |
| 763 | }; | 759 | }; |
| 764 | 760 | ||
| 761 | struct AstNodeErrorSetDecl { | ||
| 762 | ZigList<AstNode *> decls; | ||
| 763 | }; | ||
| 764 | |||
| 765 | struct AstNodeStructField { | 765 | struct AstNodeStructField { |
| 766 | VisibMod visib_mod; | 766 | VisibMod visib_mod; |
| 767 | Buf *name; | 767 | Buf *name; |
| ... | @@ -858,7 +858,6 @@ struct AstNode { | ... | @@ -858,7 +858,6 @@ struct AstNode { |
| 858 | AstNodeReturnExpr return_expr; | 858 | AstNodeReturnExpr return_expr; |
| 859 | AstNodeDefer defer; | 859 | AstNodeDefer defer; |
| 860 | AstNodeVariableDeclaration variable_declaration; | 860 | AstNodeVariableDeclaration variable_declaration; |
| 861 | AstNodeErrorValueDecl error_value_decl; | ||
| 862 | AstNodeTestDecl test_decl; | 861 | AstNodeTestDecl test_decl; |
| 863 | AstNodeBinOpExpr bin_op_expr; | 862 | AstNodeBinOpExpr bin_op_expr; |
| 864 | AstNodeCatchExpr unwrap_err_expr; | 863 | AstNodeCatchExpr unwrap_err_expr; |
| ... | @@ -899,6 +898,7 @@ struct AstNode { | ... | @@ -899,6 +898,7 @@ struct AstNode { |
| 899 | AstNodeArrayType array_type; | 898 | AstNodeArrayType array_type; |
| 900 | AstNodeErrorType error_type; | 899 | AstNodeErrorType error_type; |
| 901 | AstNodeVarLiteral var_literal; | 900 | AstNodeVarLiteral var_literal; |
| 901 | AstNodeErrorSetDecl err_set_decl; | ||
| 902 | } data; | 902 | } data; |
| 903 | }; | 903 | }; |
| 904 | 904 | ||
| ... | @@ -993,8 +993,15 @@ struct TypeTableEntryMaybe { | ... | @@ -993,8 +993,15 @@ struct TypeTableEntryMaybe { |
| 993 | TypeTableEntry *child_type; | 993 | TypeTableEntry *child_type; |
| 994 | }; | 994 | }; |
| 995 | 995 | ||
| 996 | struct TypeTableEntryError { | 996 | struct TypeTableEntryErrorUnion { |
| 997 | TypeTableEntry *child_type; | 997 | TypeTableEntry *err_set_type; |
| 998 | TypeTableEntry *payload_type; | ||
| 999 | }; | ||
| 1000 | |||
| 1001 | struct TypeTableEntryErrorSet { | ||
| 1002 | uint32_t err_count; | ||
| 1003 | ErrorTableEntry **errors; | ||
| 1004 | FnTableEntry *infer_fn; | ||
| 998 | }; | 1005 | }; |
| 999 | 1006 | ||
| 1000 | struct TypeTableEntryEnum { | 1007 | struct TypeTableEntryEnum { |
| ... | @@ -1097,7 +1104,7 @@ enum TypeTableEntryId { | ... | @@ -1097,7 +1104,7 @@ enum TypeTableEntryId { |
| 1097 | TypeTableEntryIdNullLit, | 1104 | TypeTableEntryIdNullLit, |
| 1098 | TypeTableEntryIdMaybe, | 1105 | TypeTableEntryIdMaybe, |
| 1099 | TypeTableEntryIdErrorUnion, | 1106 | TypeTableEntryIdErrorUnion, |
| 1100 | TypeTableEntryIdPureError, | 1107 | TypeTableEntryIdErrorSet, |
| 1101 | TypeTableEntryIdEnum, | 1108 | TypeTableEntryIdEnum, |
| 1102 | TypeTableEntryIdUnion, | 1109 | TypeTableEntryIdUnion, |
| 1103 | TypeTableEntryIdFn, | 1110 | TypeTableEntryIdFn, |
| ... | @@ -1126,7 +1133,8 @@ struct TypeTableEntry { | ... | @@ -1126,7 +1133,8 @@ struct TypeTableEntry { |
| 1126 | TypeTableEntryArray array; | 1133 | TypeTableEntryArray array; |
| 1127 | TypeTableEntryStruct structure; | 1134 | TypeTableEntryStruct structure; |
| 1128 | TypeTableEntryMaybe maybe; | 1135 | TypeTableEntryMaybe maybe; |
| 1129 | TypeTableEntryError error; | 1136 | TypeTableEntryErrorUnion error_union; |
| 1137 | TypeTableEntryErrorSet error_set; | ||
| 1130 | TypeTableEntryEnum enumeration; | 1138 | TypeTableEntryEnum enumeration; |
| 1131 | TypeTableEntryUnion unionation; | 1139 | TypeTableEntryUnion unionation; |
| 1132 | TypeTableEntryFn fn; | 1140 | TypeTableEntryFn fn; |
| ... | @@ -1136,7 +1144,6 @@ struct TypeTableEntry { | ... | @@ -1136,7 +1144,6 @@ struct TypeTableEntry { |
| 1136 | // use these fields to make sure we don't duplicate type table entries for the same type | 1144 | // use these fields to make sure we don't duplicate type table entries for the same type |
| 1137 | TypeTableEntry *pointer_parent[2]; // [0 - mut, 1 - const] | 1145 | TypeTableEntry *pointer_parent[2]; // [0 - mut, 1 - const] |
| 1138 | TypeTableEntry *maybe_parent; | 1146 | TypeTableEntry *maybe_parent; |
| 1139 | TypeTableEntry *error_parent; | ||
| 1140 | // If we generate a constant name value for this type, we memoize it here. | 1147 | // If we generate a constant name value for this type, we memoize it here. |
| 1141 | // The type of this is array | 1148 | // The type of this is array |
| 1142 | ConstExprValue *cached_const_name_val; | 1149 | ConstExprValue *cached_const_name_val; |
| ... | @@ -1340,6 +1347,10 @@ struct TypeId { | ... | @@ -1340,6 +1347,10 @@ struct TypeId { |
| 1340 | bool is_signed; | 1347 | bool is_signed; |
| 1341 | uint32_t bit_count; | 1348 | uint32_t bit_count; |
| 1342 | } integer; | 1349 | } integer; |
| 1350 | struct { | ||
| 1351 | TypeTableEntry *err_set_type; | ||
| 1352 | TypeTableEntry *payload_type; | ||
| 1353 | } error_union; | ||
| 1343 | } data; | 1354 | } data; |
| 1344 | }; | 1355 | }; |
| 1345 | 1356 | ||
| ... | @@ -1481,7 +1492,7 @@ struct CodeGen { | ... | @@ -1481,7 +1492,7 @@ struct CodeGen { |
| 1481 | TypeTableEntry *entry_undef; | 1492 | TypeTableEntry *entry_undef; |
| 1482 | TypeTableEntry *entry_null; | 1493 | TypeTableEntry *entry_null; |
| 1483 | TypeTableEntry *entry_var; | 1494 | TypeTableEntry *entry_var; |
| 1484 | TypeTableEntry *entry_pure_error; | 1495 | TypeTableEntry *entry_global_error_set; |
| 1485 | TypeTableEntry *entry_arg_tuple; | 1496 | TypeTableEntry *entry_arg_tuple; |
| 1486 | } builtin_types; | 1497 | } builtin_types; |
| 1487 | 1498 | ||
| ... | @@ -1570,7 +1581,6 @@ struct CodeGen { | ... | @@ -1570,7 +1581,6 @@ struct CodeGen { |
| 1570 | LLVMValueRef return_address_fn_val; | 1581 | LLVMValueRef return_address_fn_val; |
| 1571 | LLVMValueRef frame_address_fn_val; | 1582 | LLVMValueRef frame_address_fn_val; |
| 1572 | bool error_during_imports; | 1583 | bool error_during_imports; |
| 1573 | TypeTableEntry *err_tag_type; | ||
| 1574 | 1584 | ||
| 1575 | const char **clang_argv; | 1585 | const char **clang_argv; |
| 1576 | size_t clang_argv_len; | 1586 | size_t clang_argv_len; |
| ... | @@ -1584,7 +1594,9 @@ struct CodeGen { | ... | @@ -1584,7 +1594,9 @@ struct CodeGen { |
| 1584 | 1594 | ||
| 1585 | bool each_lib_rpath; | 1595 | bool each_lib_rpath; |
| 1586 | 1596 | ||
| 1587 | ZigList<AstNode *> error_decls; | 1597 | TypeTableEntry *err_tag_type; |
| 1598 | ZigList<ZigLLVMDIEnumerator *> err_enumerators; | ||
| 1599 | ZigList<ErrorTableEntry *> errors_by_index; | ||
| 1588 | bool generate_error_name_table; | 1600 | bool generate_error_name_table; |
| 1589 | LLVMValueRef err_name_table; | 1601 | LLVMValueRef err_name_table; |
| 1590 | size_t largest_err_name_len; | 1602 | size_t largest_err_name_len; |
| ... | @@ -1617,6 +1629,8 @@ struct CodeGen { | ... | @@ -1617,6 +1629,8 @@ struct CodeGen { |
| 1617 | TypeTableEntry *align_amt_type; | 1629 | TypeTableEntry *align_amt_type; |
| 1618 | TypeTableEntry *stack_trace_type; | 1630 | TypeTableEntry *stack_trace_type; |
| 1619 | TypeTableEntry *ptr_to_stack_trace_type; | 1631 | TypeTableEntry *ptr_to_stack_trace_type; |
| 1632 | |||
| 1633 | ZigList<ZigLLVMDIType **> error_di_types; | ||
| 1620 | }; | 1634 | }; |
| 1621 | 1635 | ||
| 1622 | enum VarLinkage { | 1636 | enum VarLinkage { |
| ... | @@ -1653,6 +1667,7 @@ struct ErrorTableEntry { | ... | @@ -1653,6 +1667,7 @@ struct ErrorTableEntry { |
| 1653 | Buf name; | 1667 | Buf name; |
| 1654 | uint32_t value; | 1668 | uint32_t value; |
| 1655 | AstNode *decl_node; | 1669 | AstNode *decl_node; |
| 1670 | TypeTableEntry *set_with_only_this_in_it; | ||
| 1656 | // If we generate a constant error name value for this error, we memoize it here. | 1671 | // If we generate a constant error name value for this error, we memoize it here. |
| 1657 | // The type of this is array | 1672 | // The type of this is array |
| 1658 | ConstExprValue *cached_error_name_val; | 1673 | ConstExprValue *cached_error_name_val; |
| ... | @@ -1920,6 +1935,7 @@ enum IrInstructionId { | ... | @@ -1920,6 +1935,7 @@ enum IrInstructionId { |
| 1920 | IrInstructionIdArgType, | 1935 | IrInstructionIdArgType, |
| 1921 | IrInstructionIdExport, | 1936 | IrInstructionIdExport, |
| 1922 | IrInstructionIdErrorReturnTrace, | 1937 | IrInstructionIdErrorReturnTrace, |
| 1938 | IrInstructionIdErrorUnion, | ||
| 1923 | }; | 1939 | }; |
| 1924 | 1940 | ||
| 1925 | struct IrInstruction { | 1941 | struct IrInstruction { |
| ... | @@ -1996,7 +2012,6 @@ enum IrUnOp { | ... | @@ -1996,7 +2012,6 @@ enum IrUnOp { |
| 1996 | IrUnOpNegation, | 2012 | IrUnOpNegation, |
| 1997 | IrUnOpNegationWrap, | 2013 | IrUnOpNegationWrap, |
| 1998 | IrUnOpDereference, | 2014 | IrUnOpDereference, |
| 1999 | IrUnOpError, | ||
| 2000 | IrUnOpMaybe, | 2015 | IrUnOpMaybe, |
| 2001 | }; | 2016 | }; |
| 2002 | 2017 | ||
| ... | @@ -2750,6 +2765,13 @@ struct IrInstructionErrorReturnTrace { | ... | @@ -2750,6 +2765,13 @@ struct IrInstructionErrorReturnTrace { |
| 2750 | IrInstruction base; | 2765 | IrInstruction base; |
| 2751 | }; | 2766 | }; |
| 2752 | 2767 | ||
| 2768 | struct IrInstructionErrorUnion { | ||
| 2769 | IrInstruction base; | ||
| 2770 | |||
| 2771 | IrInstruction *err_set; | ||
| 2772 | IrInstruction *payload; | ||
| 2773 | }; | ||
| 2774 | |||
| 2753 | static const size_t slice_ptr_index = 0; | 2775 | static const size_t slice_ptr_index = 0; |
| 2754 | static const size_t slice_len_index = 1; | 2776 | static const size_t slice_len_index = 1; |
| 2755 | 2777 |
src/analyze.cpp+124-88| ... | @@ -224,7 +224,7 @@ bool type_is_complete(TypeTableEntry *type_entry) { | ... | @@ -224,7 +224,7 @@ bool type_is_complete(TypeTableEntry *type_entry) { |
| 224 | case TypeTableEntryIdNullLit: | 224 | case TypeTableEntryIdNullLit: |
| 225 | case TypeTableEntryIdMaybe: | 225 | case TypeTableEntryIdMaybe: |
| 226 | case TypeTableEntryIdErrorUnion: | 226 | case TypeTableEntryIdErrorUnion: |
| 227 | case TypeTableEntryIdPureError: | 227 | case TypeTableEntryIdErrorSet: |
| 228 | case TypeTableEntryIdFn: | 228 | case TypeTableEntryIdFn: |
| 229 | case TypeTableEntryIdNamespace: | 229 | case TypeTableEntryIdNamespace: |
| 230 | case TypeTableEntryIdBlock: | 230 | case TypeTableEntryIdBlock: |
| ... | @@ -260,7 +260,7 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) { | ... | @@ -260,7 +260,7 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) { |
| 260 | case TypeTableEntryIdNullLit: | 260 | case TypeTableEntryIdNullLit: |
| 261 | case TypeTableEntryIdMaybe: | 261 | case TypeTableEntryIdMaybe: |
| 262 | case TypeTableEntryIdErrorUnion: | 262 | case TypeTableEntryIdErrorUnion: |
| 263 | case TypeTableEntryIdPureError: | 263 | case TypeTableEntryIdErrorSet: |
| 264 | case TypeTableEntryIdFn: | 264 | case TypeTableEntryIdFn: |
| 265 | case TypeTableEntryIdNamespace: | 265 | case TypeTableEntryIdNamespace: |
| 266 | case TypeTableEntryIdBlock: | 266 | case TypeTableEntryIdBlock: |
| ... | @@ -514,29 +514,39 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) { | ... | @@ -514,29 +514,39 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) { |
| 514 | } | 514 | } |
| 515 | } | 515 | } |
| 516 | 516 | ||
| 517 | TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) { | 517 | TypeTableEntry *get_error_union_type(CodeGen *g, TypeTableEntry *err_set_type, TypeTableEntry *payload_type) { |
| 518 | if (child_type->error_parent) | 518 | assert(err_set_type->id == TypeTableEntryIdErrorSet); |
| 519 | return child_type->error_parent; | 519 | |
| 520 | TypeId type_id = {}; | ||
| 521 | type_id.id = TypeTableEntryIdErrorUnion; | ||
| 522 | type_id.data.error_union.err_set_type = err_set_type; | ||
| 523 | type_id.data.error_union.payload_type = payload_type; | ||
| 524 | |||
| 525 | auto existing_entry = g->type_table.maybe_get(type_id); | ||
| 526 | if (existing_entry) { | ||
| 527 | return existing_entry->value; | ||
| 528 | } | ||
| 520 | 529 | ||
| 521 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdErrorUnion); | 530 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdErrorUnion); |
| 522 | entry->is_copyable = true; | 531 | entry->is_copyable = true; |
| 523 | assert(child_type->type_ref); | 532 | assert(payload_type->type_ref); |
| 524 | assert(child_type->di_type); | 533 | assert(payload_type->di_type); |
| 525 | ensure_complete_type(g, child_type); | 534 | ensure_complete_type(g, payload_type); |
| 526 | 535 | ||
| 527 | buf_resize(&entry->name, 0); | 536 | buf_resize(&entry->name, 0); |
| 528 | buf_appendf(&entry->name, "%%%s", buf_ptr(&child_type->name)); | 537 | buf_appendf(&entry->name, "%s!%s", buf_ptr(&err_set_type->name), buf_ptr(&payload_type->name)); |
| 529 | 538 | ||
| 530 | entry->data.error.child_type = child_type; | 539 | entry->data.error_union.err_set_type = err_set_type; |
| 540 | entry->data.error_union.payload_type = payload_type; | ||
| 531 | 541 | ||
| 532 | if (!type_has_bits(child_type)) { | 542 | if (!type_has_bits(payload_type)) { |
| 533 | entry->type_ref = g->err_tag_type->type_ref; | 543 | entry->type_ref = err_set_type->type_ref; |
| 534 | entry->di_type = g->err_tag_type->di_type; | 544 | entry->di_type = err_set_type->di_type; |
| 535 | 545 | ||
| 536 | } else { | 546 | } else { |
| 537 | LLVMTypeRef elem_types[] = { | 547 | LLVMTypeRef elem_types[] = { |
| 538 | g->err_tag_type->type_ref, | 548 | err_set_type->type_ref, |
| 539 | child_type->type_ref, | 549 | payload_type->type_ref, |
| 540 | }; | 550 | }; |
| 541 | entry->type_ref = LLVMStructType(elem_types, 2, false); | 551 | entry->type_ref = LLVMStructType(elem_types, 2, false); |
| 542 | 552 | ||
| ... | @@ -547,12 +557,12 @@ TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) { | ... | @@ -547,12 +557,12 @@ TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) { |
| 547 | ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name), | 557 | ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name), |
| 548 | compile_unit_scope, di_file, line); | 558 | compile_unit_scope, di_file, line); |
| 549 | 559 | ||
| 550 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, g->err_tag_type->type_ref); | 560 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, err_set_type->type_ref); |
| 551 | uint64_t tag_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, g->err_tag_type->type_ref); | 561 | uint64_t tag_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, err_set_type->type_ref); |
| 552 | uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, err_union_err_index); | 562 | uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, err_union_err_index); |
| 553 | 563 | ||
| 554 | uint64_t value_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, child_type->type_ref); | 564 | uint64_t value_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, payload_type->type_ref); |
| 555 | uint64_t value_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, child_type->type_ref); | 565 | uint64_t value_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, payload_type->type_ref); |
| 556 | uint64_t value_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, | 566 | uint64_t value_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, |
| 557 | err_union_payload_index); | 567 | err_union_payload_index); |
| 558 | 568 | ||
| ... | @@ -565,13 +575,13 @@ TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) { | ... | @@ -565,13 +575,13 @@ TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) { |
| 565 | tag_debug_size_in_bits, | 575 | tag_debug_size_in_bits, |
| 566 | tag_debug_align_in_bits, | 576 | tag_debug_align_in_bits, |
| 567 | tag_offset_in_bits, | 577 | tag_offset_in_bits, |
| 568 | 0, child_type->di_type), | 578 | 0, err_set_type->di_type), |
| 569 | ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), | 579 | ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), |
| 570 | "value", di_file, line, | 580 | "value", di_file, line, |
| 571 | value_debug_size_in_bits, | 581 | value_debug_size_in_bits, |
| 572 | value_debug_align_in_bits, | 582 | value_debug_align_in_bits, |
| 573 | value_offset_in_bits, | 583 | value_offset_in_bits, |
| 574 | 0, child_type->di_type), | 584 | 0, payload_type->di_type), |
| 575 | }; | 585 | }; |
| 576 | 586 | ||
| 577 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, | 587 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, |
| ... | @@ -587,7 +597,7 @@ TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) { | ... | @@ -587,7 +597,7 @@ TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) { |
| 587 | entry->di_type = replacement_di_type; | 597 | entry->di_type = replacement_di_type; |
| 588 | } | 598 | } |
| 589 | 599 | ||
| 590 | child_type->error_parent = entry; | 600 | g->type_table.put(type_id, entry); |
| 591 | return entry; | 601 | return entry; |
| 592 | } | 602 | } |
| 593 | 603 | ||
| ... | @@ -937,7 +947,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { | ... | @@ -937,7 +947,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 937 | handle_is_ptr(fn_type_id->return_type); | 947 | handle_is_ptr(fn_type_id->return_type); |
| 938 | bool prefix_arg_error_return_trace = g->have_err_ret_tracing && | 948 | bool prefix_arg_error_return_trace = g->have_err_ret_tracing && |
| 939 | (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion || | 949 | (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion || |
| 940 | fn_type_id->return_type->id == TypeTableEntryIdPureError); | 950 | fn_type_id->return_type->id == TypeTableEntryIdErrorSet); |
| 941 | // +1 for maybe making the first argument the return value | 951 | // +1 for maybe making the first argument the return value |
| 942 | // +1 for maybe last argument the error return trace | 952 | // +1 for maybe last argument the error return trace |
| 943 | LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(2 + fn_type_id->param_count); | 953 | LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(2 + fn_type_id->param_count); |
| ... | @@ -1177,7 +1187,7 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { | ... | @@ -1177,7 +1187,7 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { |
| 1177 | case TypeTableEntryIdUndefLit: | 1187 | case TypeTableEntryIdUndefLit: |
| 1178 | case TypeTableEntryIdNullLit: | 1188 | case TypeTableEntryIdNullLit: |
| 1179 | case TypeTableEntryIdErrorUnion: | 1189 | case TypeTableEntryIdErrorUnion: |
| 1180 | case TypeTableEntryIdPureError: | 1190 | case TypeTableEntryIdErrorSet: |
| 1181 | case TypeTableEntryIdNamespace: | 1191 | case TypeTableEntryIdNamespace: |
| 1182 | case TypeTableEntryIdBlock: | 1192 | case TypeTableEntryIdBlock: |
| 1183 | case TypeTableEntryIdBoundFn: | 1193 | case TypeTableEntryIdBoundFn: |
| ... | @@ -1218,7 +1228,7 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) { | ... | @@ -1218,7 +1228,7 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) { |
| 1218 | case TypeTableEntryIdUndefLit: | 1228 | case TypeTableEntryIdUndefLit: |
| 1219 | case TypeTableEntryIdNullLit: | 1229 | case TypeTableEntryIdNullLit: |
| 1220 | case TypeTableEntryIdErrorUnion: | 1230 | case TypeTableEntryIdErrorUnion: |
| 1221 | case TypeTableEntryIdPureError: | 1231 | case TypeTableEntryIdErrorSet: |
| 1222 | case TypeTableEntryIdNamespace: | 1232 | case TypeTableEntryIdNamespace: |
| 1223 | case TypeTableEntryIdBlock: | 1233 | case TypeTableEntryIdBlock: |
| 1224 | case TypeTableEntryIdBoundFn: | 1234 | case TypeTableEntryIdBoundFn: |
| ... | @@ -1263,7 +1273,23 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) { | ... | @@ -1263,7 +1273,23 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) { |
| 1263 | zig_unreachable(); | 1273 | zig_unreachable(); |
| 1264 | } | 1274 | } |
| 1265 | 1275 | ||
| 1266 | static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope) { | 1276 | static TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry) { |
| 1277 | TypeTableEntry *err_set_type = new_type_table_entry(TypeTableEntryIdErrorSet); | ||
| 1278 | buf_resize(&err_set_type->name, 0); | ||
| 1279 | buf_appendf(&err_set_type->name, "%s.errors", buf_ptr(&fn_entry->symbol_name)); | ||
| 1280 | err_set_type->is_copyable = true; | ||
| 1281 | err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref; | ||
| 1282 | err_set_type->di_type = g->builtin_types.entry_global_error_set->di_type; | ||
| 1283 | err_set_type->data.error_set.err_count = 0; | ||
| 1284 | err_set_type->data.error_set.errors = nullptr; | ||
| 1285 | err_set_type->data.error_set.infer_fn = fn_entry; | ||
| 1286 | |||
| 1287 | g->error_di_types.append(&err_set_type->di_type); | ||
| 1288 | |||
| 1289 | return err_set_type; | ||
| 1290 | } | ||
| 1291 | |||
| 1292 | static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope, FnTableEntry *fn_entry) { | ||
| 1267 | assert(proto_node->type == NodeTypeFnProto); | 1293 | assert(proto_node->type == NodeTypeFnProto); |
| 1268 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; | 1294 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 1269 | 1295 | ||
| ... | @@ -1359,7 +1385,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c | ... | @@ -1359,7 +1385,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1359 | case TypeTableEntryIdStruct: | 1385 | case TypeTableEntryIdStruct: |
| 1360 | case TypeTableEntryIdMaybe: | 1386 | case TypeTableEntryIdMaybe: |
| 1361 | case TypeTableEntryIdErrorUnion: | 1387 | case TypeTableEntryIdErrorUnion: |
| 1362 | case TypeTableEntryIdPureError: | 1388 | case TypeTableEntryIdErrorSet: |
| 1363 | case TypeTableEntryIdEnum: | 1389 | case TypeTableEntryIdEnum: |
| 1364 | case TypeTableEntryIdUnion: | 1390 | case TypeTableEntryIdUnion: |
| 1365 | case TypeTableEntryIdFn: | 1391 | case TypeTableEntryIdFn: |
| ... | @@ -1382,8 +1408,13 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c | ... | @@ -1382,8 +1408,13 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1382 | } | 1408 | } |
| 1383 | } | 1409 | } |
| 1384 | 1410 | ||
| 1385 | fn_type_id.return_type = (fn_proto->return_type == nullptr) ? | 1411 | TypeTableEntry *specified_return_type = analyze_type_expr(g, child_scope, fn_proto->return_type); |
| 1386 | g->builtin_types.entry_void : analyze_type_expr(g, child_scope, fn_proto->return_type); | 1412 | if (fn_proto->auto_err_set) { |
| 1413 | TypeTableEntry *inferred_err_set_type = get_auto_err_set_type(g, fn_entry); | ||
| 1414 | fn_type_id.return_type = get_error_union_type(g, inferred_err_set_type, specified_return_type); | ||
| 1415 | } else { | ||
| 1416 | fn_type_id.return_type = specified_return_type; | ||
| 1417 | } | ||
| 1387 | 1418 | ||
| 1388 | if (type_is_invalid(fn_type_id.return_type)) { | 1419 | if (type_is_invalid(fn_type_id.return_type)) { |
| 1389 | return g->builtin_types.entry_invalid; | 1420 | return g->builtin_types.entry_invalid; |
| ... | @@ -1434,7 +1465,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c | ... | @@ -1434,7 +1465,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1434 | case TypeTableEntryIdStruct: | 1465 | case TypeTableEntryIdStruct: |
| 1435 | case TypeTableEntryIdMaybe: | 1466 | case TypeTableEntryIdMaybe: |
| 1436 | case TypeTableEntryIdErrorUnion: | 1467 | case TypeTableEntryIdErrorUnion: |
| 1437 | case TypeTableEntryIdPureError: | 1468 | case TypeTableEntryIdErrorSet: |
| 1438 | case TypeTableEntryIdEnum: | 1469 | case TypeTableEntryIdEnum: |
| 1439 | case TypeTableEntryIdUnion: | 1470 | case TypeTableEntryIdUnion: |
| 1440 | case TypeTableEntryIdFn: | 1471 | case TypeTableEntryIdFn: |
| ... | @@ -2756,7 +2787,8 @@ TypeTableEntry *get_test_fn_type(CodeGen *g) { | ... | @@ -2756,7 +2787,8 @@ TypeTableEntry *get_test_fn_type(CodeGen *g) { |
| 2756 | return g->test_fn_type; | 2787 | return g->test_fn_type; |
| 2757 | 2788 | ||
| 2758 | FnTypeId fn_type_id = {0}; | 2789 | FnTypeId fn_type_id = {0}; |
| 2759 | fn_type_id.return_type = get_error_type(g, g->builtin_types.entry_void); | 2790 | fn_type_id.return_type = get_error_union_type(g, g->builtin_types.entry_global_error_set, |
| 2791 | g->builtin_types.entry_void); | ||
| 2760 | g->test_fn_type = get_fn_type(g, &fn_type_id); | 2792 | g->test_fn_type = get_fn_type(g, &fn_type_id); |
| 2761 | return g->test_fn_type; | 2793 | return g->test_fn_type; |
| 2762 | } | 2794 | } |
| ... | @@ -2824,7 +2856,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { | ... | @@ -2824,7 +2856,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 2824 | 2856 | ||
| 2825 | Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope; | 2857 | Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope; |
| 2826 | 2858 | ||
| 2827 | fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope); | 2859 | fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, fn_table_entry); |
| 2828 | 2860 | ||
| 2829 | if (fn_proto->section_expr != nullptr) { | 2861 | if (fn_proto->section_expr != nullptr) { |
| 2830 | if (fn_table_entry->body_node == nullptr) { | 2862 | if (fn_table_entry->body_node == nullptr) { |
| ... | @@ -2949,29 +2981,6 @@ static void preview_test_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope | ... | @@ -2949,29 +2981,6 @@ static void preview_test_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope |
| 2949 | g->resolve_queue.append(&tld_fn->base); | 2981 | g->resolve_queue.append(&tld_fn->base); |
| 2950 | } | 2982 | } |
| 2951 | 2983 | ||
| 2952 | static void preview_error_value_decl(CodeGen *g, AstNode *node) { | ||
| 2953 | assert(node->type == NodeTypeErrorValueDecl); | ||
| 2954 | |||
| 2955 | ErrorTableEntry *err = allocate<ErrorTableEntry>(1); | ||
| 2956 | |||
| 2957 | err->decl_node = node; | ||
| 2958 | buf_init_from_buf(&err->name, node->data.error_value_decl.name); | ||
| 2959 | |||
| 2960 | auto existing_entry = g->error_table.maybe_get(&err->name); | ||
| 2961 | if (existing_entry) { | ||
| 2962 | // duplicate error definitions allowed and they get the same value | ||
| 2963 | err->value = existing_entry->value->value; | ||
| 2964 | } else { | ||
| 2965 | size_t error_value_count = g->error_decls.length; | ||
| 2966 | assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)g->err_tag_type->data.integral.bit_count)); | ||
| 2967 | err->value = (uint32_t)error_value_count; | ||
| 2968 | g->error_decls.append(node); | ||
| 2969 | g->error_table.put(&err->name, err); | ||
| 2970 | } | ||
| 2971 | |||
| 2972 | node->data.error_value_decl.err = err; | ||
| 2973 | } | ||
| 2974 | |||
| 2975 | static void preview_comptime_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) { | 2984 | static void preview_comptime_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) { |
| 2976 | assert(node->type == NodeTypeCompTime); | 2985 | assert(node->type == NodeTypeCompTime); |
| 2977 | 2986 | ||
| ... | @@ -3045,10 +3054,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { | ... | @@ -3045,10 +3054,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 3045 | import->use_decls.append(node); | 3054 | import->use_decls.append(node); |
| 3046 | break; | 3055 | break; |
| 3047 | } | 3056 | } |
| 3048 | case NodeTypeErrorValueDecl: | ||
| 3049 | // error value declarations do not depend on other top level decls | ||
| 3050 | preview_error_value_decl(g, node); | ||
| 3051 | break; | ||
| 3052 | case NodeTypeTestDecl: | 3057 | case NodeTypeTestDecl: |
| 3053 | preview_test_decl(g, node, decls_scope); | 3058 | preview_test_decl(g, node, decls_scope); |
| 3054 | break; | 3059 | break; |
| ... | @@ -3097,6 +3102,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { | ... | @@ -3097,6 +3102,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 3097 | case NodeTypeVarLiteral: | 3102 | case NodeTypeVarLiteral: |
| 3098 | case NodeTypeIfErrorExpr: | 3103 | case NodeTypeIfErrorExpr: |
| 3099 | case NodeTypeTestExpr: | 3104 | case NodeTypeTestExpr: |
| 3105 | case NodeTypeErrorSetDecl: | ||
| 3100 | zig_unreachable(); | 3106 | zig_unreachable(); |
| 3101 | } | 3107 | } |
| 3102 | } | 3108 | } |
| ... | @@ -3147,7 +3153,7 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt | ... | @@ -3147,7 +3153,7 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt |
| 3147 | case TypeTableEntryIdStruct: | 3153 | case TypeTableEntryIdStruct: |
| 3148 | case TypeTableEntryIdMaybe: | 3154 | case TypeTableEntryIdMaybe: |
| 3149 | case TypeTableEntryIdErrorUnion: | 3155 | case TypeTableEntryIdErrorUnion: |
| 3150 | case TypeTableEntryIdPureError: | 3156 | case TypeTableEntryIdErrorSet: |
| 3151 | case TypeTableEntryIdEnum: | 3157 | case TypeTableEntryIdEnum: |
| 3152 | case TypeTableEntryIdUnion: | 3158 | case TypeTableEntryIdUnion: |
| 3153 | case TypeTableEntryIdFn: | 3159 | case TypeTableEntryIdFn: |
| ... | @@ -3403,13 +3409,16 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry * | ... | @@ -3403,13 +3409,16 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry * |
| 3403 | actual_type->data.maybe.child_type); | 3409 | actual_type->data.maybe.child_type); |
| 3404 | } | 3410 | } |
| 3405 | 3411 | ||
| 3406 | // error | 3412 | // error union |
| 3407 | if (expected_type->id == TypeTableEntryIdErrorUnion && | 3413 | if (expected_type->id == TypeTableEntryIdErrorUnion && |
| 3408 | actual_type->id == TypeTableEntryIdErrorUnion) | 3414 | actual_type->id == TypeTableEntryIdErrorUnion) |
| 3409 | { | 3415 | { |
| 3410 | return types_match_const_cast_only( | 3416 | return types_match_const_cast_only( |
| 3411 | expected_type->data.error.child_type, | 3417 | expected_type->data.error_union.payload_type, |
| 3412 | actual_type->data.error.child_type); | 3418 | actual_type->data.error_union.payload_type) && |
| 3419 | types_match_const_cast_only( | ||
| 3420 | expected_type->data.error_union.err_set_type, | ||
| 3421 | actual_type->data.error_union.err_set_type); | ||
| 3413 | } | 3422 | } |
| 3414 | 3423 | ||
| 3415 | // fn | 3424 | // fn |
| ... | @@ -3625,7 +3634,7 @@ static bool is_container(TypeTableEntry *type_entry) { | ... | @@ -3625,7 +3634,7 @@ static bool is_container(TypeTableEntry *type_entry) { |
| 3625 | case TypeTableEntryIdNullLit: | 3634 | case TypeTableEntryIdNullLit: |
| 3626 | case TypeTableEntryIdMaybe: | 3635 | case TypeTableEntryIdMaybe: |
| 3627 | case TypeTableEntryIdErrorUnion: | 3636 | case TypeTableEntryIdErrorUnion: |
| 3628 | case TypeTableEntryIdPureError: | 3637 | case TypeTableEntryIdErrorSet: |
| 3629 | case TypeTableEntryIdFn: | 3638 | case TypeTableEntryIdFn: |
| 3630 | case TypeTableEntryIdNamespace: | 3639 | case TypeTableEntryIdNamespace: |
| 3631 | case TypeTableEntryIdBlock: | 3640 | case TypeTableEntryIdBlock: |
| ... | @@ -3673,7 +3682,7 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) { | ... | @@ -3673,7 +3682,7 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) { |
| 3673 | case TypeTableEntryIdNullLit: | 3682 | case TypeTableEntryIdNullLit: |
| 3674 | case TypeTableEntryIdMaybe: | 3683 | case TypeTableEntryIdMaybe: |
| 3675 | case TypeTableEntryIdErrorUnion: | 3684 | case TypeTableEntryIdErrorUnion: |
| 3676 | case TypeTableEntryIdPureError: | 3685 | case TypeTableEntryIdErrorSet: |
| 3677 | case TypeTableEntryIdFn: | 3686 | case TypeTableEntryIdFn: |
| 3678 | case TypeTableEntryIdNamespace: | 3687 | case TypeTableEntryIdNamespace: |
| 3679 | case TypeTableEntryIdBlock: | 3688 | case TypeTableEntryIdBlock: |
| ... | @@ -3774,14 +3783,36 @@ void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_typ | ... | @@ -3774,14 +3783,36 @@ void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_typ |
| 3774 | &fn_table_entry->analyzed_executable, fn_type_id->return_type, return_type_node); | 3783 | &fn_table_entry->analyzed_executable, fn_type_id->return_type, return_type_node); |
| 3775 | fn_table_entry->implicit_return_type = block_return_type; | 3784 | fn_table_entry->implicit_return_type = block_return_type; |
| 3776 | 3785 | ||
| 3777 | if (block_return_type->id == TypeTableEntryIdInvalid || | 3786 | if (type_is_invalid(block_return_type) || fn_table_entry->analyzed_executable.invalid) { |
| 3778 | fn_table_entry->analyzed_executable.invalid) | ||
| 3779 | { | ||
| 3780 | assert(g->errors.length > 0); | 3787 | assert(g->errors.length > 0); |
| 3781 | fn_table_entry->anal_state = FnAnalStateInvalid; | 3788 | fn_table_entry->anal_state = FnAnalStateInvalid; |
| 3782 | return; | 3789 | return; |
| 3783 | } | 3790 | } |
| 3784 | 3791 | ||
| 3792 | if (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion) { | ||
| 3793 | TypeTableEntry *return_err_set_type = fn_type_id->return_type->data.error_union.err_set_type; | ||
| 3794 | if (return_err_set_type->data.error_set.infer_fn != nullptr) { | ||
| 3795 | TypeTableEntry *inferred_err_set_type; | ||
| 3796 | if (fn_table_entry->implicit_return_type->id == TypeTableEntryIdErrorSet) { | ||
| 3797 | inferred_err_set_type = fn_table_entry->implicit_return_type; | ||
| 3798 | } else if (fn_table_entry->implicit_return_type->id == TypeTableEntryIdErrorUnion) { | ||
| 3799 | inferred_err_set_type = fn_table_entry->implicit_return_type->data.error_union.err_set_type; | ||
| 3800 | } else { | ||
| 3801 | add_node_error(g, return_type_node, | ||
| 3802 | buf_sprintf("function with inferred error set must return at least one possible error")); | ||
| 3803 | fn_table_entry->anal_state = FnAnalStateInvalid; | ||
| 3804 | return; | ||
| 3805 | } | ||
| 3806 | |||
| 3807 | return_err_set_type->data.error_set.infer_fn = nullptr; | ||
| 3808 | return_err_set_type->data.error_set.err_count = inferred_err_set_type->data.error_set.err_count; | ||
| 3809 | return_err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(inferred_err_set_type->data.error_set.err_count); | ||
| 3810 | for (uint32_t i = 0; i < inferred_err_set_type->data.error_set.err_count; i += 1) { | ||
| 3811 | return_err_set_type->data.error_set.errors[i] = inferred_err_set_type->data.error_set.errors[i]; | ||
| 3812 | } | ||
| 3813 | } | ||
| 3814 | } | ||
| 3815 | |||
| 3785 | if (g->verbose_ir) { | 3816 | if (g->verbose_ir) { |
| 3786 | fprintf(stderr, "{ // (analyzed)\n"); | 3817 | fprintf(stderr, "{ // (analyzed)\n"); |
| 3787 | ir_print(g, stderr, &fn_table_entry->analyzed_executable, 4); | 3818 | ir_print(g, stderr, &fn_table_entry->analyzed_executable, 4); |
| ... | @@ -3791,7 +3822,7 @@ void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_typ | ... | @@ -3791,7 +3822,7 @@ void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_typ |
| 3791 | fn_table_entry->anal_state = FnAnalStateComplete; | 3822 | fn_table_entry->anal_state = FnAnalStateComplete; |
| 3792 | } | 3823 | } |
| 3793 | 3824 | ||
| 3794 | static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { | 3825 | void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 3795 | assert(fn_table_entry->anal_state != FnAnalStateProbing); | 3826 | assert(fn_table_entry->anal_state != FnAnalStateProbing); |
| 3796 | if (fn_table_entry->anal_state != FnAnalStateReady) | 3827 | if (fn_table_entry->anal_state != FnAnalStateReady) |
| 3797 | return; | 3828 | return; |
| ... | @@ -4022,7 +4053,8 @@ void semantic_analyze(CodeGen *g) { | ... | @@ -4022,7 +4053,8 @@ void semantic_analyze(CodeGen *g) { |
| 4022 | for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) { | 4053 | for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) { |
| 4023 | Tld *tld = g->resolve_queue.at(g->resolve_queue_index); | 4054 | Tld *tld = g->resolve_queue.at(g->resolve_queue_index); |
| 4024 | bool pointer_only = false; | 4055 | bool pointer_only = false; |
| 4025 | resolve_top_level_decl(g, tld, pointer_only, nullptr); | 4056 | AstNode *source_node = nullptr; |
| 4057 | resolve_top_level_decl(g, tld, pointer_only, source_node); | ||
| 4026 | } | 4058 | } |
| 4027 | 4059 | ||
| 4028 | for (; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) { | 4060 | for (; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) { |
| ... | @@ -4114,7 +4146,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { | ... | @@ -4114,7 +4146,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { |
| 4114 | case TypeTableEntryIdInt: | 4146 | case TypeTableEntryIdInt: |
| 4115 | case TypeTableEntryIdFloat: | 4147 | case TypeTableEntryIdFloat: |
| 4116 | case TypeTableEntryIdPointer: | 4148 | case TypeTableEntryIdPointer: |
| 4117 | case TypeTableEntryIdPureError: | 4149 | case TypeTableEntryIdErrorSet: |
| 4118 | case TypeTableEntryIdFn: | 4150 | case TypeTableEntryIdFn: |
| 4119 | case TypeTableEntryIdEnum: | 4151 | case TypeTableEntryIdEnum: |
| 4120 | return false; | 4152 | return false; |
| ... | @@ -4122,7 +4154,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { | ... | @@ -4122,7 +4154,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { |
| 4122 | case TypeTableEntryIdStruct: | 4154 | case TypeTableEntryIdStruct: |
| 4123 | return type_has_bits(type_entry); | 4155 | return type_has_bits(type_entry); |
| 4124 | case TypeTableEntryIdErrorUnion: | 4156 | case TypeTableEntryIdErrorUnion: |
| 4125 | return type_has_bits(type_entry->data.error.child_type); | 4157 | return type_has_bits(type_entry->data.error_union.payload_type); |
| 4126 | case TypeTableEntryIdMaybe: | 4158 | case TypeTableEntryIdMaybe: |
| 4127 | return type_has_bits(type_entry->data.maybe.child_type) && | 4159 | return type_has_bits(type_entry->data.maybe.child_type) && |
| 4128 | type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer && | 4160 | type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer && |
| ... | @@ -4386,9 +4418,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { | ... | @@ -4386,9 +4418,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4386 | case TypeTableEntryIdErrorUnion: | 4418 | case TypeTableEntryIdErrorUnion: |
| 4387 | // TODO better hashing algorithm | 4419 | // TODO better hashing algorithm |
| 4388 | return 3415065496; | 4420 | return 3415065496; |
| 4389 | case TypeTableEntryIdPureError: | 4421 | case TypeTableEntryIdErrorSet: |
| 4390 | // TODO better hashing algorithm | 4422 | assert(const_val->data.x_err_set != nullptr); |
| 4391 | return 2630160122; | 4423 | return const_val->data.x_err_set->value ^ 2630160122; |
| 4392 | case TypeTableEntryIdFn: | 4424 | case TypeTableEntryIdFn: |
| 4393 | return 4133894920 ^ hash_ptr(const_val->data.x_fn.fn_entry); | 4425 | return 4133894920 ^ hash_ptr(const_val->data.x_fn.fn_entry); |
| 4394 | case TypeTableEntryIdNamespace: | 4426 | case TypeTableEntryIdNamespace: |
| ... | @@ -4515,7 +4547,7 @@ bool type_requires_comptime(TypeTableEntry *type_entry) { | ... | @@ -4515,7 +4547,7 @@ bool type_requires_comptime(TypeTableEntry *type_entry) { |
| 4515 | case TypeTableEntryIdMaybe: | 4547 | case TypeTableEntryIdMaybe: |
| 4516 | case TypeTableEntryIdErrorUnion: | 4548 | case TypeTableEntryIdErrorUnion: |
| 4517 | case TypeTableEntryIdEnum: | 4549 | case TypeTableEntryIdEnum: |
| 4518 | case TypeTableEntryIdPureError: | 4550 | case TypeTableEntryIdErrorSet: |
| 4519 | case TypeTableEntryIdFn: | 4551 | case TypeTableEntryIdFn: |
| 4520 | case TypeTableEntryIdBool: | 4552 | case TypeTableEntryIdBool: |
| 4521 | case TypeTableEntryIdInt: | 4553 | case TypeTableEntryIdInt: |
| ... | @@ -4894,8 +4926,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -4894,8 +4926,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 4894 | return a->data.x_type == b->data.x_type; | 4926 | return a->data.x_type == b->data.x_type; |
| 4895 | case TypeTableEntryIdVoid: | 4927 | case TypeTableEntryIdVoid: |
| 4896 | return true; | 4928 | return true; |
| 4897 | case TypeTableEntryIdPureError: | 4929 | case TypeTableEntryIdErrorSet: |
| 4898 | return a->data.x_pure_err == b->data.x_pure_err; | 4930 | return a->data.x_err_set->value == b->data.x_err_set->value; |
| 4899 | case TypeTableEntryIdFn: | 4931 | case TypeTableEntryIdFn: |
| 4900 | return a->data.x_fn.fn_entry == b->data.x_fn.fn_entry; | 4932 | return a->data.x_fn.fn_entry == b->data.x_fn.fn_entry; |
| 4901 | case TypeTableEntryIdBool: | 4933 | case TypeTableEntryIdBool: |
| ... | @@ -5256,9 +5288,9 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -5256,9 +5288,9 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5256 | buf_appendf(buf, "(union %s constant)", buf_ptr(&type_entry->name)); | 5288 | buf_appendf(buf, "(union %s constant)", buf_ptr(&type_entry->name)); |
| 5257 | return; | 5289 | return; |
| 5258 | } | 5290 | } |
| 5259 | case TypeTableEntryIdPureError: | 5291 | case TypeTableEntryIdErrorSet: |
| 5260 | { | 5292 | { |
| 5261 | buf_appendf(buf, "(pure error constant)"); | 5293 | buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name)); |
| 5262 | return; | 5294 | return; |
| 5263 | } | 5295 | } |
| 5264 | case TypeTableEntryIdArgTuple: | 5296 | case TypeTableEntryIdArgTuple: |
| ... | @@ -5319,8 +5351,7 @@ uint32_t type_id_hash(TypeId x) { | ... | @@ -5319,8 +5351,7 @@ uint32_t type_id_hash(TypeId x) { |
| 5319 | case TypeTableEntryIdUndefLit: | 5351 | case TypeTableEntryIdUndefLit: |
| 5320 | case TypeTableEntryIdNullLit: | 5352 | case TypeTableEntryIdNullLit: |
| 5321 | case TypeTableEntryIdMaybe: | 5353 | case TypeTableEntryIdMaybe: |
| 5322 | case TypeTableEntryIdErrorUnion: | 5354 | case TypeTableEntryIdErrorSet: |
| 5323 | case TypeTableEntryIdPureError: | ||
| 5324 | case TypeTableEntryIdEnum: | 5355 | case TypeTableEntryIdEnum: |
| 5325 | case TypeTableEntryIdUnion: | 5356 | case TypeTableEntryIdUnion: |
| 5326 | case TypeTableEntryIdFn: | 5357 | case TypeTableEntryIdFn: |
| ... | @@ -5329,6 +5360,8 @@ uint32_t type_id_hash(TypeId x) { | ... | @@ -5329,6 +5360,8 @@ uint32_t type_id_hash(TypeId x) { |
| 5329 | case TypeTableEntryIdBoundFn: | 5360 | case TypeTableEntryIdBoundFn: |
| 5330 | case TypeTableEntryIdArgTuple: | 5361 | case TypeTableEntryIdArgTuple: |
| 5331 | zig_unreachable(); | 5362 | zig_unreachable(); |
| 5363 | case TypeTableEntryIdErrorUnion: | ||
| 5364 | return hash_ptr(x.data.error_union.err_set_type) ^ hash_ptr(x.data.error_union.payload_type); | ||
| 5332 | case TypeTableEntryIdPointer: | 5365 | case TypeTableEntryIdPointer: |
| 5333 | return hash_ptr(x.data.pointer.child_type) + | 5366 | return hash_ptr(x.data.pointer.child_type) + |
| 5334 | (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) + | 5367 | (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) + |
| ... | @@ -5363,8 +5396,7 @@ bool type_id_eql(TypeId a, TypeId b) { | ... | @@ -5363,8 +5396,7 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 5363 | case TypeTableEntryIdUndefLit: | 5396 | case TypeTableEntryIdUndefLit: |
| 5364 | case TypeTableEntryIdNullLit: | 5397 | case TypeTableEntryIdNullLit: |
| 5365 | case TypeTableEntryIdMaybe: | 5398 | case TypeTableEntryIdMaybe: |
| 5366 | case TypeTableEntryIdErrorUnion: | 5399 | case TypeTableEntryIdErrorSet: |
| 5367 | case TypeTableEntryIdPureError: | ||
| 5368 | case TypeTableEntryIdEnum: | 5400 | case TypeTableEntryIdEnum: |
| 5369 | case TypeTableEntryIdUnion: | 5401 | case TypeTableEntryIdUnion: |
| 5370 | case TypeTableEntryIdFn: | 5402 | case TypeTableEntryIdFn: |
| ... | @@ -5374,6 +5406,10 @@ bool type_id_eql(TypeId a, TypeId b) { | ... | @@ -5374,6 +5406,10 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 5374 | case TypeTableEntryIdArgTuple: | 5406 | case TypeTableEntryIdArgTuple: |
| 5375 | case TypeTableEntryIdOpaque: | 5407 | case TypeTableEntryIdOpaque: |
| 5376 | zig_unreachable(); | 5408 | zig_unreachable(); |
| 5409 | case TypeTableEntryIdErrorUnion: | ||
| 5410 | return a.data.error_union.err_set_type == b.data.error_union.err_set_type && | ||
| 5411 | a.data.error_union.payload_type == b.data.error_union.payload_type; | ||
| 5412 | |||
| 5377 | case TypeTableEntryIdPointer: | 5413 | case TypeTableEntryIdPointer: |
| 5378 | return a.data.pointer.child_type == b.data.pointer.child_type && | 5414 | return a.data.pointer.child_type == b.data.pointer.child_type && |
| 5379 | a.data.pointer.is_const == b.data.pointer.is_const && | 5415 | a.data.pointer.is_const == b.data.pointer.is_const && |
| ... | @@ -5478,7 +5514,7 @@ static const TypeTableEntryId all_type_ids[] = { | ... | @@ -5478,7 +5514,7 @@ static const TypeTableEntryId all_type_ids[] = { |
| 5478 | TypeTableEntryIdNullLit, | 5514 | TypeTableEntryIdNullLit, |
| 5479 | TypeTableEntryIdMaybe, | 5515 | TypeTableEntryIdMaybe, |
| 5480 | TypeTableEntryIdErrorUnion, | 5516 | TypeTableEntryIdErrorUnion, |
| 5481 | TypeTableEntryIdPureError, | 5517 | TypeTableEntryIdErrorSet, |
| 5482 | TypeTableEntryIdEnum, | 5518 | TypeTableEntryIdEnum, |
| 5483 | TypeTableEntryIdUnion, | 5519 | TypeTableEntryIdUnion, |
| 5484 | TypeTableEntryIdFn, | 5520 | TypeTableEntryIdFn, |
| ... | @@ -5533,7 +5569,7 @@ size_t type_id_index(TypeTableEntryId id) { | ... | @@ -5533,7 +5569,7 @@ size_t type_id_index(TypeTableEntryId id) { |
| 5533 | return 13; | 5569 | return 13; |
| 5534 | case TypeTableEntryIdErrorUnion: | 5570 | case TypeTableEntryIdErrorUnion: |
| 5535 | return 14; | 5571 | return 14; |
| 5536 | case TypeTableEntryIdPureError: | 5572 | case TypeTableEntryIdErrorSet: |
| 5537 | return 15; | 5573 | return 15; |
| 5538 | case TypeTableEntryIdEnum: | 5574 | case TypeTableEntryIdEnum: |
| 5539 | return 16; | 5575 | return 16; |
| ... | @@ -5590,8 +5626,8 @@ const char *type_id_name(TypeTableEntryId id) { | ... | @@ -5590,8 +5626,8 @@ const char *type_id_name(TypeTableEntryId id) { |
| 5590 | return "Nullable"; | 5626 | return "Nullable"; |
| 5591 | case TypeTableEntryIdErrorUnion: | 5627 | case TypeTableEntryIdErrorUnion: |
| 5592 | return "ErrorUnion"; | 5628 | return "ErrorUnion"; |
| 5593 | case TypeTableEntryIdPureError: | 5629 | case TypeTableEntryIdErrorSet: |
| 5594 | return "Error"; | 5630 | return "ErrorSet"; |
| 5595 | case TypeTableEntryIdEnum: | 5631 | case TypeTableEntryIdEnum: |
| 5596 | return "Enum"; | 5632 | return "Enum"; |
| 5597 | case TypeTableEntryIdUnion: | 5633 | case TypeTableEntryIdUnion: |
src/analyze.hpp+2-2| ... | @@ -30,7 +30,7 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type); | ... | @@ -30,7 +30,7 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type); |
| 30 | TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, | 30 | TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, |
| 31 | AstNode *decl_node, const char *name, ContainerLayout layout); | 31 | AstNode *decl_node, const char *name, ContainerLayout layout); |
| 32 | TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x); | 32 | TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x); |
| 33 | TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type); | 33 | TypeTableEntry *get_error_union_type(CodeGen *g, TypeTableEntry *err_set_type, TypeTableEntry *payload_type); |
| 34 | TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry); | 34 | TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry); |
| 35 | TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name); | 35 | TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name); |
| 36 | TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[], | 36 | TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[], |
| ... | @@ -46,7 +46,6 @@ bool type_has_bits(TypeTableEntry *type_entry); | ... | @@ -46,7 +46,6 @@ bool type_has_bits(TypeTableEntry *type_entry); |
| 46 | ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code); | 46 | ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code); |
| 47 | 47 | ||
| 48 | 48 | ||
| 49 | // TODO move these over, these used to be static | ||
| 50 | bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type); | 49 | bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type); |
| 51 | VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name); | 50 | VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name); |
| 52 | Tld *find_decl(CodeGen *g, Scope *scope, Buf *name); | 51 | Tld *find_decl(CodeGen *g, Scope *scope, Buf *name); |
| ... | @@ -188,6 +187,7 @@ void add_fn_export(CodeGen *g, FnTableEntry *fn_table_entry, Buf *symbol_name, G | ... | @@ -188,6 +187,7 @@ void add_fn_export(CodeGen *g, FnTableEntry *fn_table_entry, Buf *symbol_name, G |
| 188 | 187 | ||
| 189 | ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name); | 188 | ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name); |
| 190 | TypeTableEntry *get_ptr_to_stack_trace_type(CodeGen *g); | 189 | TypeTableEntry *get_ptr_to_stack_trace_type(CodeGen *g); |
| 190 | void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry); | ||
| 191 | 191 | ||
| 192 | 192 | ||
| 193 | #endif | 193 | #endif |
src/ast_render.cpp+24-5| ... | @@ -54,6 +54,7 @@ static const char *bin_op_str(BinOpType bin_op) { | ... | @@ -54,6 +54,7 @@ static const char *bin_op_str(BinOpType bin_op) { |
| 54 | case BinOpTypeUnwrapMaybe: return "??"; | 54 | case BinOpTypeUnwrapMaybe: return "??"; |
| 55 | case BinOpTypeArrayCat: return "++"; | 55 | case BinOpTypeArrayCat: return "++"; |
| 56 | case BinOpTypeArrayMult: return "**"; | 56 | case BinOpTypeArrayMult: return "**"; |
| 57 | case BinOpTypeErrorUnion: return "!"; | ||
| 57 | } | 58 | } |
| 58 | zig_unreachable(); | 59 | zig_unreachable(); |
| 59 | } | 60 | } |
| ... | @@ -67,7 +68,6 @@ static const char *prefix_op_str(PrefixOp prefix_op) { | ... | @@ -67,7 +68,6 @@ static const char *prefix_op_str(PrefixOp prefix_op) { |
| 67 | case PrefixOpBinNot: return "~"; | 68 | case PrefixOpBinNot: return "~"; |
| 68 | case PrefixOpDereference: return "*"; | 69 | case PrefixOpDereference: return "*"; |
| 69 | case PrefixOpMaybe: return "?"; | 70 | case PrefixOpMaybe: return "?"; |
| 70 | case PrefixOpError: return "%"; | ||
| 71 | case PrefixOpUnwrapMaybe: return "??"; | 71 | case PrefixOpUnwrapMaybe: return "??"; |
| 72 | } | 72 | } |
| 73 | zig_unreachable(); | 73 | zig_unreachable(); |
| ... | @@ -174,8 +174,6 @@ static const char *node_type_str(NodeType node_type) { | ... | @@ -174,8 +174,6 @@ static const char *node_type_str(NodeType node_type) { |
| 174 | return "Defer"; | 174 | return "Defer"; |
| 175 | case NodeTypeVariableDeclaration: | 175 | case NodeTypeVariableDeclaration: |
| 176 | return "VariableDeclaration"; | 176 | return "VariableDeclaration"; |
| 177 | case NodeTypeErrorValueDecl: | ||
| 178 | return "ErrorValueDecl"; | ||
| 179 | case NodeTypeTestDecl: | 177 | case NodeTypeTestDecl: |
| 180 | return "TestDecl"; | 178 | return "TestDecl"; |
| 181 | case NodeTypeIntLiteral: | 179 | case NodeTypeIntLiteral: |
| ... | @@ -244,6 +242,8 @@ static const char *node_type_str(NodeType node_type) { | ... | @@ -244,6 +242,8 @@ static const char *node_type_str(NodeType node_type) { |
| 244 | return "IfErrorExpr"; | 242 | return "IfErrorExpr"; |
| 245 | case NodeTypeTestExpr: | 243 | case NodeTypeTestExpr: |
| 246 | return "TestExpr"; | 244 | return "TestExpr"; |
| 245 | case NodeTypeErrorSetDecl: | ||
| 246 | return "ErrorSetDecl"; | ||
| 247 | } | 247 | } |
| 248 | zig_unreachable(); | 248 | zig_unreachable(); |
| 249 | } | 249 | } |
| ... | @@ -396,7 +396,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -396,7 +396,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 396 | 396 | ||
| 397 | if (child->type == NodeTypeUse || | 397 | if (child->type == NodeTypeUse || |
| 398 | child->type == NodeTypeVariableDeclaration || | 398 | child->type == NodeTypeVariableDeclaration || |
| 399 | child->type == NodeTypeErrorValueDecl || | ||
| 400 | child->type == NodeTypeFnProto) | 399 | child->type == NodeTypeFnProto) |
| 401 | { | 400 | { |
| 402 | fprintf(ar->f, ";"); | 401 | fprintf(ar->f, ";"); |
| ... | @@ -452,6 +451,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -452,6 +451,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 452 | AstNode *return_type_node = node->data.fn_proto.return_type; | 451 | AstNode *return_type_node = node->data.fn_proto.return_type; |
| 453 | assert(return_type_node != nullptr); | 452 | assert(return_type_node != nullptr); |
| 454 | fprintf(ar->f, " "); | 453 | fprintf(ar->f, " "); |
| 454 | if (node->data.fn_proto.auto_err_set) { | ||
| 455 | fprintf(ar->f, "!"); | ||
| 456 | } | ||
| 455 | render_node_grouped(ar, return_type_node); | 457 | render_node_grouped(ar, return_type_node); |
| 456 | break; | 458 | break; |
| 457 | } | 459 | } |
| ... | @@ -1017,9 +1019,26 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -1017,9 +1019,26 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 1017 | render_node_ungrouped(ar, node->data.unwrap_err_expr.op2); | 1019 | render_node_ungrouped(ar, node->data.unwrap_err_expr.op2); |
| 1018 | break; | 1020 | break; |
| 1019 | } | 1021 | } |
| 1022 | case NodeTypeErrorSetDecl: | ||
| 1023 | { | ||
| 1024 | fprintf(ar->f, "error {\n"); | ||
| 1025 | ar->indent += ar->indent_size; | ||
| 1026 | |||
| 1027 | for (size_t i = 0; i < node->data.err_set_decl.decls.length; i += 1) { | ||
| 1028 | AstNode *field_node = node->data.err_set_decl.decls.at(i); | ||
| 1029 | assert(field_node->type == NodeTypeSymbol); | ||
| 1030 | print_indent(ar); | ||
| 1031 | print_symbol(ar, field_node->data.symbol_expr.symbol); | ||
| 1032 | fprintf(ar->f, ",\n"); | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | ar->indent -= ar->indent_size; | ||
| 1036 | print_indent(ar); | ||
| 1037 | fprintf(ar->f, "}"); | ||
| 1038 | break; | ||
| 1039 | } | ||
| 1020 | case NodeTypeFnDecl: | 1040 | case NodeTypeFnDecl: |
| 1021 | case NodeTypeParamDecl: | 1041 | case NodeTypeParamDecl: |
| 1022 | case NodeTypeErrorValueDecl: | ||
| 1023 | case NodeTypeTestDecl: | 1042 | case NodeTypeTestDecl: |
| 1024 | case NodeTypeStructField: | 1043 | case NodeTypeStructField: |
| 1025 | case NodeTypeUse: | 1044 | case NodeTypeUse: |
src/codegen.cpp+76-51| ... | @@ -92,9 +92,6 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out | ... | @@ -92,9 +92,6 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out |
| 92 | g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib); | 92 | g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib); |
| 93 | buf_resize(&g->global_asm, 0); | 93 | buf_resize(&g->global_asm, 0); |
| 94 | 94 | ||
| 95 | // reserve index 0 to indicate no error | ||
| 96 | g->error_decls.append(nullptr); | ||
| 97 | |||
| 98 | if (root_src_path) { | 95 | if (root_src_path) { |
| 99 | Buf *src_basename = buf_alloc(); | 96 | Buf *src_basename = buf_alloc(); |
| 100 | Buf *src_dir = buf_alloc(); | 97 | Buf *src_dir = buf_alloc(); |
| ... | @@ -410,7 +407,7 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_e | ... | @@ -410,7 +407,7 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_e |
| 410 | } | 407 | } |
| 411 | TypeTableEntry *fn_type = fn_table_entry->type_entry; | 408 | TypeTableEntry *fn_type = fn_table_entry->type_entry; |
| 412 | TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; | 409 | TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; |
| 413 | if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdPureError) { | 410 | if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdErrorSet) { |
| 414 | return UINT32_MAX; | 411 | return UINT32_MAX; |
| 415 | } | 412 | } |
| 416 | bool first_arg_ret = type_has_bits(return_type) && handle_is_ptr(return_type); | 413 | bool first_arg_ret = type_has_bits(return_type) && handle_is_ptr(return_type); |
| ... | @@ -1442,7 +1439,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns | ... | @@ -1442,7 +1439,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns |
| 1442 | is_err_return = return_instruction->value->value.data.rh_error_union == RuntimeHintErrorUnionError; | 1439 | is_err_return = return_instruction->value->value.data.rh_error_union == RuntimeHintErrorUnionError; |
| 1443 | // TODO: emit a branch to check if the return value is an error | 1440 | // TODO: emit a branch to check if the return value is an error |
| 1444 | } | 1441 | } |
| 1445 | } else if (return_type->id == TypeTableEntryIdPureError) { | 1442 | } else if (return_type->id == TypeTableEntryIdErrorSet) { |
| 1446 | is_err_return = true; | 1443 | is_err_return = true; |
| 1447 | } | 1444 | } |
| 1448 | if (is_err_return) { | 1445 | if (is_err_return) { |
| ... | @@ -1823,7 +1820,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, | ... | @@ -1823,7 +1820,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 1823 | } else if (type_entry->id == TypeTableEntryIdEnum) { | 1820 | } else if (type_entry->id == TypeTableEntryIdEnum) { |
| 1824 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false); | 1821 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false); |
| 1825 | return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); | 1822 | return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, ""); |
| 1826 | } else if (type_entry->id == TypeTableEntryIdPureError || | 1823 | } else if (type_entry->id == TypeTableEntryIdErrorSet || |
| 1827 | type_entry->id == TypeTableEntryIdPointer || | 1824 | type_entry->id == TypeTableEntryIdPointer || |
| 1828 | type_entry->id == TypeTableEntryIdBool) | 1825 | type_entry->id == TypeTableEntryIdBool) |
| 1829 | { | 1826 | { |
| ... | @@ -2139,7 +2136,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, | ... | @@ -2139,7 +2136,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, |
| 2139 | 2136 | ||
| 2140 | static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, IrInstructionIntToErr *instruction) { | 2137 | static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, IrInstructionIntToErr *instruction) { |
| 2141 | TypeTableEntry *wanted_type = instruction->base.value.type; | 2138 | TypeTableEntry *wanted_type = instruction->base.value.type; |
| 2142 | assert(wanted_type->id == TypeTableEntryIdPureError); | 2139 | assert(wanted_type->id == TypeTableEntryIdErrorSet); |
| 2143 | 2140 | ||
| 2144 | TypeTableEntry *actual_type = instruction->target->value.type; | 2141 | TypeTableEntry *actual_type = instruction->target->value.type; |
| 2145 | assert(actual_type->id == TypeTableEntryIdInt); | 2142 | assert(actual_type->id == TypeTableEntryIdInt); |
| ... | @@ -2156,11 +2153,11 @@ static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, I | ... | @@ -2156,11 +2153,11 @@ static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, I |
| 2156 | eval_min_max_value_int(g, actual_type, &biggest_possible_err_val, true); | 2153 | eval_min_max_value_int(g, actual_type, &biggest_possible_err_val, true); |
| 2157 | 2154 | ||
| 2158 | if (bigint_fits_in_bits(&biggest_possible_err_val, 64, false) && | 2155 | if (bigint_fits_in_bits(&biggest_possible_err_val, 64, false) && |
| 2159 | bigint_as_unsigned(&biggest_possible_err_val) < g->error_decls.length) | 2156 | bigint_as_unsigned(&biggest_possible_err_val) < g->errors_by_index.length) |
| 2160 | { | 2157 | { |
| 2161 | ok_bit = neq_zero_bit; | 2158 | ok_bit = neq_zero_bit; |
| 2162 | } else { | 2159 | } else { |
| 2163 | LLVMValueRef error_value_count = LLVMConstInt(actual_type->type_ref, g->error_decls.length, false); | 2160 | LLVMValueRef error_value_count = LLVMConstInt(actual_type->type_ref, g->errors_by_index.length, false); |
| 2164 | LLVMValueRef in_bounds_bit = LLVMBuildICmp(g->builder, LLVMIntULT, target_val, error_value_count, ""); | 2161 | LLVMValueRef in_bounds_bit = LLVMBuildICmp(g->builder, LLVMIntULT, target_val, error_value_count, ""); |
| 2165 | ok_bit = LLVMBuildAnd(g->builder, neq_zero_bit, in_bounds_bit, ""); | 2162 | ok_bit = LLVMBuildAnd(g->builder, neq_zero_bit, in_bounds_bit, ""); |
| 2166 | } | 2163 | } |
| ... | @@ -2187,15 +2184,15 @@ static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutable *executable, I | ... | @@ -2187,15 +2184,15 @@ static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutable *executable, I |
| 2187 | TypeTableEntry *actual_type = instruction->target->value.type; | 2184 | TypeTableEntry *actual_type = instruction->target->value.type; |
| 2188 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); | 2185 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); |
| 2189 | 2186 | ||
| 2190 | if (actual_type->id == TypeTableEntryIdPureError) { | 2187 | if (actual_type->id == TypeTableEntryIdErrorSet) { |
| 2191 | return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), | 2188 | return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), |
| 2192 | g->err_tag_type, wanted_type, target_val); | 2189 | g->err_tag_type, wanted_type, target_val); |
| 2193 | } else if (actual_type->id == TypeTableEntryIdErrorUnion) { | 2190 | } else if (actual_type->id == TypeTableEntryIdErrorUnion) { |
| 2194 | if (!type_has_bits(actual_type->data.error.child_type)) { | 2191 | if (!type_has_bits(actual_type->data.error_union.payload_type)) { |
| 2195 | return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), | 2192 | return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), |
| 2196 | g->err_tag_type, wanted_type, target_val); | 2193 | g->err_tag_type, wanted_type, target_val); |
| 2197 | } else { | 2194 | } else { |
| 2198 | zig_panic("TODO"); | 2195 | zig_panic("TODO err to int when error union payload type not void"); |
| 2199 | } | 2196 | } |
| 2200 | } else { | 2197 | } else { |
| 2201 | zig_unreachable(); | 2198 | zig_unreachable(); |
| ... | @@ -2235,7 +2232,6 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst | ... | @@ -2235,7 +2232,6 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst |
| 2235 | 2232 | ||
| 2236 | switch (op_id) { | 2233 | switch (op_id) { |
| 2237 | case IrUnOpInvalid: | 2234 | case IrUnOpInvalid: |
| 2238 | case IrUnOpError: | ||
| 2239 | case IrUnOpMaybe: | 2235 | case IrUnOpMaybe: |
| 2240 | case IrUnOpDereference: | 2236 | case IrUnOpDereference: |
| 2241 | zig_unreachable(); | 2237 | zig_unreachable(); |
| ... | @@ -2489,7 +2485,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -2489,7 +2485,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 2489 | TypeTableEntry *src_return_type = fn_type_id->return_type; | 2485 | TypeTableEntry *src_return_type = fn_type_id->return_type; |
| 2490 | bool ret_has_bits = type_has_bits(src_return_type); | 2486 | bool ret_has_bits = type_has_bits(src_return_type); |
| 2491 | bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type); | 2487 | bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type); |
| 2492 | bool prefix_arg_err_ret_stack = g->have_err_ret_tracing && (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdPureError); | 2488 | bool prefix_arg_err_ret_stack = g->have_err_ret_tracing && (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdErrorSet); |
| 2493 | size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0); | 2489 | size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0); |
| 2494 | bool is_var_args = fn_type_id->is_var_args; | 2490 | bool is_var_args = fn_type_id->is_var_args; |
| 2495 | LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count); | 2491 | LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count); |
| ... | @@ -2907,7 +2903,7 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstru | ... | @@ -2907,7 +2903,7 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutable *executable, IrInstru |
| 2907 | static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrInstructionErrName *instruction) { | 2903 | static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrInstructionErrName *instruction) { |
| 2908 | assert(g->generate_error_name_table); | 2904 | assert(g->generate_error_name_table); |
| 2909 | 2905 | ||
| 2910 | if (g->error_decls.length == 1) { | 2906 | if (g->errors_by_index.length == 1) { |
| 2911 | LLVMBuildUnreachable(g->builder); | 2907 | LLVMBuildUnreachable(g->builder); |
| 2912 | return nullptr; | 2908 | return nullptr; |
| 2913 | } | 2909 | } |
| ... | @@ -2915,7 +2911,7 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -2915,7 +2911,7 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrI |
| 2915 | LLVMValueRef err_val = ir_llvm_value(g, instruction->value); | 2911 | LLVMValueRef err_val = ir_llvm_value(g, instruction->value); |
| 2916 | if (ir_want_runtime_safety(g, &instruction->base)) { | 2912 | if (ir_want_runtime_safety(g, &instruction->base)) { |
| 2917 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val)); | 2913 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val)); |
| 2918 | LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->error_decls.length, false); | 2914 | LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->errors_by_index.length, false); |
| 2919 | add_bounds_check(g, err_val, LLVMIntNE, zero, LLVMIntULT, end_val); | 2915 | add_bounds_check(g, err_val, LLVMIntNE, zero, LLVMIntULT, end_val); |
| 2920 | } | 2916 | } |
| 2921 | 2917 | ||
| ... | @@ -3393,11 +3389,11 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable, | ... | @@ -3393,11 +3389,11 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable, |
| 3393 | 3389 | ||
| 3394 | static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErr *instruction) { | 3390 | static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrInstructionTestErr *instruction) { |
| 3395 | TypeTableEntry *err_union_type = instruction->value->value.type; | 3391 | TypeTableEntry *err_union_type = instruction->value->value.type; |
| 3396 | TypeTableEntry *child_type = err_union_type->data.error.child_type; | 3392 | TypeTableEntry *payload_type = err_union_type->data.error_union.payload_type; |
| 3397 | LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->value); | 3393 | LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->value); |
| 3398 | 3394 | ||
| 3399 | LLVMValueRef err_val; | 3395 | LLVMValueRef err_val; |
| 3400 | if (type_has_bits(child_type)) { | 3396 | if (type_has_bits(payload_type)) { |
| 3401 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); | 3397 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); |
| 3402 | err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); | 3398 | err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); |
| 3403 | } else { | 3399 | } else { |
| ... | @@ -3412,11 +3408,11 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab | ... | @@ -3412,11 +3408,11 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab |
| 3412 | TypeTableEntry *ptr_type = instruction->value->value.type; | 3408 | TypeTableEntry *ptr_type = instruction->value->value.type; |
| 3413 | assert(ptr_type->id == TypeTableEntryIdPointer); | 3409 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 3414 | TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type; | 3410 | TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type; |
| 3415 | TypeTableEntry *child_type = err_union_type->data.error.child_type; | 3411 | TypeTableEntry *payload_type = err_union_type->data.error_union.payload_type; |
| 3416 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); | 3412 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); |
| 3417 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); | 3413 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); |
| 3418 | 3414 | ||
| 3419 | if (type_has_bits(child_type)) { | 3415 | if (type_has_bits(payload_type)) { |
| 3420 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); | 3416 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); |
| 3421 | return gen_load_untyped(g, err_val_ptr, 0, false, ""); | 3417 | return gen_load_untyped(g, err_val_ptr, 0, false, ""); |
| 3422 | } else { | 3418 | } else { |
| ... | @@ -3428,13 +3424,13 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu | ... | @@ -3428,13 +3424,13 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu |
| 3428 | TypeTableEntry *ptr_type = instruction->value->value.type; | 3424 | TypeTableEntry *ptr_type = instruction->value->value.type; |
| 3429 | assert(ptr_type->id == TypeTableEntryIdPointer); | 3425 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 3430 | TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type; | 3426 | TypeTableEntry *err_union_type = ptr_type->data.pointer.child_type; |
| 3431 | TypeTableEntry *child_type = err_union_type->data.error.child_type; | 3427 | TypeTableEntry *payload_type = err_union_type->data.error_union.payload_type; |
| 3432 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); | 3428 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); |
| 3433 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); | 3429 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); |
| 3434 | 3430 | ||
| 3435 | if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->error_decls.length > 1) { | 3431 | if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) { |
| 3436 | LLVMValueRef err_val; | 3432 | LLVMValueRef err_val; |
| 3437 | if (type_has_bits(child_type)) { | 3433 | if (type_has_bits(payload_type)) { |
| 3438 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); | 3434 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); |
| 3439 | err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); | 3435 | err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); |
| 3440 | } else { | 3436 | } else { |
| ... | @@ -3452,7 +3448,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu | ... | @@ -3452,7 +3448,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu |
| 3452 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | 3448 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 3453 | } | 3449 | } |
| 3454 | 3450 | ||
| 3455 | if (type_has_bits(child_type)) { | 3451 | if (type_has_bits(payload_type)) { |
| 3456 | return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, ""); | 3452 | return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, ""); |
| 3457 | } else { | 3453 | } else { |
| 3458 | return nullptr; | 3454 | return nullptr; |
| ... | @@ -3493,10 +3489,10 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable | ... | @@ -3493,10 +3489,10 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutable *executable |
| 3493 | 3489 | ||
| 3494 | assert(wanted_type->id == TypeTableEntryIdErrorUnion); | 3490 | assert(wanted_type->id == TypeTableEntryIdErrorUnion); |
| 3495 | 3491 | ||
| 3496 | TypeTableEntry *child_type = wanted_type->data.error.child_type; | 3492 | TypeTableEntry *payload_type = wanted_type->data.error_union.payload_type; |
| 3497 | LLVMValueRef err_val = ir_llvm_value(g, instruction->value); | 3493 | LLVMValueRef err_val = ir_llvm_value(g, instruction->value); |
| 3498 | 3494 | ||
| 3499 | if (!type_has_bits(child_type)) | 3495 | if (!type_has_bits(payload_type)) |
| 3500 | return err_val; | 3496 | return err_val; |
| 3501 | 3497 | ||
| 3502 | assert(instruction->tmp_ptr); | 3498 | assert(instruction->tmp_ptr); |
| ... | @@ -3512,11 +3508,11 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa | ... | @@ -3512,11 +3508,11 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa |
| 3512 | 3508 | ||
| 3513 | assert(wanted_type->id == TypeTableEntryIdErrorUnion); | 3509 | assert(wanted_type->id == TypeTableEntryIdErrorUnion); |
| 3514 | 3510 | ||
| 3515 | TypeTableEntry *child_type = wanted_type->data.error.child_type; | 3511 | TypeTableEntry *payload_type = wanted_type->data.error_union.payload_type; |
| 3516 | 3512 | ||
| 3517 | LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref); | 3513 | LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref); |
| 3518 | 3514 | ||
| 3519 | if (!type_has_bits(child_type)) | 3515 | if (!type_has_bits(payload_type)) |
| 3520 | return ok_err_val; | 3516 | return ok_err_val; |
| 3521 | 3517 | ||
| 3522 | assert(instruction->tmp_ptr); | 3518 | assert(instruction->tmp_ptr); |
| ... | @@ -3527,7 +3523,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa | ... | @@ -3527,7 +3523,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa |
| 3527 | gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false); | 3523 | gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false); |
| 3528 | 3524 | ||
| 3529 | LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, ""); | 3525 | LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, ""); |
| 3530 | gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, child_type, false), payload_val); | 3526 | gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, payload_type, false), payload_val); |
| 3531 | 3527 | ||
| 3532 | return instruction->tmp_ptr; | 3528 | return instruction->tmp_ptr; |
| 3533 | } | 3529 | } |
| ... | @@ -3700,6 +3696,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -3700,6 +3696,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3700 | case IrInstructionIdArgType: | 3696 | case IrInstructionIdArgType: |
| 3701 | case IrInstructionIdTagType: | 3697 | case IrInstructionIdTagType: |
| 3702 | case IrInstructionIdExport: | 3698 | case IrInstructionIdExport: |
| 3699 | case IrInstructionIdErrorUnion: | ||
| 3703 | zig_unreachable(); | 3700 | zig_unreachable(); |
| 3704 | case IrInstructionIdReturn: | 3701 | case IrInstructionIdReturn: |
| 3705 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); | 3702 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); |
| ... | @@ -3933,7 +3930,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con | ... | @@ -3933,7 +3930,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con |
| 3933 | case TypeTableEntryIdUndefLit: | 3930 | case TypeTableEntryIdUndefLit: |
| 3934 | case TypeTableEntryIdNullLit: | 3931 | case TypeTableEntryIdNullLit: |
| 3935 | case TypeTableEntryIdErrorUnion: | 3932 | case TypeTableEntryIdErrorUnion: |
| 3936 | case TypeTableEntryIdPureError: | 3933 | case TypeTableEntryIdErrorSet: |
| 3937 | case TypeTableEntryIdNamespace: | 3934 | case TypeTableEntryIdNamespace: |
| 3938 | case TypeTableEntryIdBlock: | 3935 | case TypeTableEntryIdBlock: |
| 3939 | case TypeTableEntryIdBoundFn: | 3936 | case TypeTableEntryIdBoundFn: |
| ... | @@ -4026,10 +4023,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -4026,10 +4023,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 4026 | switch (type_entry->id) { | 4023 | switch (type_entry->id) { |
| 4027 | case TypeTableEntryIdInt: | 4024 | case TypeTableEntryIdInt: |
| 4028 | return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint); | 4025 | return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint); |
| 4029 | case TypeTableEntryIdPureError: | 4026 | case TypeTableEntryIdErrorSet: |
| 4030 | assert(const_val->data.x_pure_err); | 4027 | assert(const_val->data.x_err_set != nullptr); |
| 4031 | return LLVMConstInt(g->builtin_types.entry_pure_error->type_ref, | 4028 | return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, |
| 4032 | const_val->data.x_pure_err->value, false); | 4029 | const_val->data.x_err_set->value, false); |
| 4033 | case TypeTableEntryIdFloat: | 4030 | case TypeTableEntryIdFloat: |
| 4034 | switch (type_entry->data.floating.bit_count) { | 4031 | switch (type_entry->data.floating.bit_count) { |
| 4035 | case 32: | 4032 | case 32: |
| ... | @@ -4330,8 +4327,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -4330,8 +4327,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 4330 | } | 4327 | } |
| 4331 | case TypeTableEntryIdErrorUnion: | 4328 | case TypeTableEntryIdErrorUnion: |
| 4332 | { | 4329 | { |
| 4333 | TypeTableEntry *child_type = type_entry->data.error.child_type; | 4330 | TypeTableEntry *payload_type = type_entry->data.error_union.payload_type; |
| 4334 | if (!type_has_bits(child_type)) { | 4331 | if (!type_has_bits(payload_type)) { |
| 4335 | uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0; | 4332 | uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0; |
| 4336 | return LLVMConstInt(g->err_tag_type->type_ref, value, false); | 4333 | return LLVMConstInt(g->err_tag_type->type_ref, value, false); |
| 4337 | } else { | 4334 | } else { |
| ... | @@ -4340,7 +4337,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -4340,7 +4337,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 4340 | bool make_unnamed_struct; | 4337 | bool make_unnamed_struct; |
| 4341 | if (const_val->data.x_err_union.err) { | 4338 | if (const_val->data.x_err_union.err) { |
| 4342 | err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false); | 4339 | err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false); |
| 4343 | err_payload_value = LLVMConstNull(child_type->type_ref); | 4340 | err_payload_value = LLVMConstNull(payload_type->type_ref); |
| 4344 | make_unnamed_struct = false; | 4341 | make_unnamed_struct = false; |
| 4345 | } else { | 4342 | } else { |
| 4346 | err_tag_value = LLVMConstNull(g->err_tag_type->type_ref); | 4343 | err_tag_value = LLVMConstNull(g->err_tag_type->type_ref); |
| ... | @@ -4410,21 +4407,20 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const | ... | @@ -4410,21 +4407,20 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const |
| 4410 | } | 4407 | } |
| 4411 | 4408 | ||
| 4412 | static void generate_error_name_table(CodeGen *g) { | 4409 | static void generate_error_name_table(CodeGen *g) { |
| 4413 | if (g->err_name_table != nullptr || !g->generate_error_name_table || g->error_decls.length == 1) { | 4410 | if (g->err_name_table != nullptr || !g->generate_error_name_table || g->errors_by_index.length == 1) { |
| 4414 | return; | 4411 | return; |
| 4415 | } | 4412 | } |
| 4416 | 4413 | ||
| 4417 | assert(g->error_decls.length > 0); | 4414 | assert(g->errors_by_index.length > 0); |
| 4418 | 4415 | ||
| 4419 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); | 4416 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); |
| 4420 | TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type); | 4417 | TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type); |
| 4421 | 4418 | ||
| 4422 | LLVMValueRef *values = allocate<LLVMValueRef>(g->error_decls.length); | 4419 | LLVMValueRef *values = allocate<LLVMValueRef>(g->errors_by_index.length); |
| 4423 | values[0] = LLVMGetUndef(str_type->type_ref); | 4420 | values[0] = LLVMGetUndef(str_type->type_ref); |
| 4424 | for (size_t i = 1; i < g->error_decls.length; i += 1) { | 4421 | for (size_t i = 1; i < g->errors_by_index.length; i += 1) { |
| 4425 | AstNode *error_decl_node = g->error_decls.at(i); | 4422 | ErrorTableEntry *err_entry = g->errors_by_index.at(i); |
| 4426 | assert(error_decl_node->type == NodeTypeErrorValueDecl); | 4423 | Buf *name = &err_entry->name; |
| 4427 | Buf *name = error_decl_node->data.error_value_decl.name; | ||
| 4428 | 4424 | ||
| 4429 | g->largest_err_name_len = max(g->largest_err_name_len, buf_len(name)); | 4425 | g->largest_err_name_len = max(g->largest_err_name_len, buf_len(name)); |
| 4430 | 4426 | ||
| ... | @@ -4443,7 +4439,7 @@ static void generate_error_name_table(CodeGen *g) { | ... | @@ -4443,7 +4439,7 @@ static void generate_error_name_table(CodeGen *g) { |
| 4443 | values[i] = LLVMConstNamedStruct(str_type->type_ref, fields, 2); | 4439 | values[i] = LLVMConstNamedStruct(str_type->type_ref, fields, 2); |
| 4444 | } | 4440 | } |
| 4445 | 4441 | ||
| 4446 | LLVMValueRef err_name_table_init = LLVMConstArray(str_type->type_ref, values, (unsigned)g->error_decls.length); | 4442 | LLVMValueRef err_name_table_init = LLVMConstArray(str_type->type_ref, values, (unsigned)g->errors_by_index.length); |
| 4447 | 4443 | ||
| 4448 | g->err_name_table = LLVMAddGlobal(g->module, LLVMTypeOf(err_name_table_init), | 4444 | g->err_name_table = LLVMAddGlobal(g->module, LLVMTypeOf(err_name_table_init), |
| 4449 | buf_ptr(get_mangled_name(g, buf_create_from_str("__zig_err_name_table"), false))); | 4445 | buf_ptr(get_mangled_name(g, buf_create_from_str("__zig_err_name_table"), false))); |
| ... | @@ -4573,6 +4569,28 @@ static void validate_inline_fns(CodeGen *g) { | ... | @@ -4573,6 +4569,28 @@ static void validate_inline_fns(CodeGen *g) { |
| 4573 | static void do_code_gen(CodeGen *g) { | 4569 | static void do_code_gen(CodeGen *g) { |
| 4574 | assert(!g->errors.length); | 4570 | assert(!g->errors.length); |
| 4575 | 4571 | ||
| 4572 | { | ||
| 4573 | // create debug type for error sets | ||
| 4574 | assert(g->err_enumerators.length == g->errors_by_index.length); | ||
| 4575 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, g->err_tag_type->type_ref); | ||
| 4576 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, g->err_tag_type->type_ref); | ||
| 4577 | ZigLLVMDIFile *err_set_di_file = nullptr; | ||
| 4578 | ZigLLVMDIType *err_set_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | ||
| 4579 | ZigLLVMCompileUnitToScope(g->compile_unit), buf_ptr(&g->builtin_types.entry_global_error_set->name), | ||
| 4580 | err_set_di_file, 0, | ||
| 4581 | tag_debug_size_in_bits, | ||
| 4582 | tag_debug_align_in_bits, | ||
| 4583 | g->err_enumerators.items, g->err_enumerators.length, | ||
| 4584 | g->err_tag_type->di_type, ""); | ||
| 4585 | ZigLLVMReplaceTemporary(g->dbuilder, g->builtin_types.entry_global_error_set->di_type, err_set_di_type); | ||
| 4586 | g->builtin_types.entry_global_error_set->di_type = err_set_di_type; | ||
| 4587 | |||
| 4588 | for (size_t i = 0; i < g->error_di_types.length; i += 1) { | ||
| 4589 | ZigLLVMDIType **di_type_ptr = g->error_di_types.at(i); | ||
| 4590 | *di_type_ptr = err_set_di_type; | ||
| 4591 | } | ||
| 4592 | } | ||
| 4593 | |||
| 4576 | codegen_add_time_event(g, "Code Generation"); | 4594 | codegen_add_time_event(g, "Code Generation"); |
| 4577 | 4595 | ||
| 4578 | generate_error_name_table(g); | 4596 | generate_error_name_table(g); |
| ... | @@ -5176,16 +5194,23 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -5176,16 +5194,23 @@ static void define_builtin_types(CodeGen *g) { |
| 5176 | } | 5194 | } |
| 5177 | 5195 | ||
| 5178 | { | 5196 | { |
| 5179 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPureError); | 5197 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdErrorSet); |
| 5180 | buf_init_from_str(&entry->name, "error"); | 5198 | buf_init_from_str(&entry->name, "error"); |
| 5181 | 5199 | ||
| 5182 | // TODO allow overriding this type and keep track of max value and emit an | 5200 | // TODO allow overriding this type and keep track of max value and emit an |
| 5183 | // error if there are too many errors declared | 5201 | // error if there are too many errors declared |
| 5184 | g->err_tag_type = g->builtin_types.entry_u16; | 5202 | g->err_tag_type = g->builtin_types.entry_u16; |
| 5185 | 5203 | ||
| 5186 | g->builtin_types.entry_pure_error = entry; | 5204 | g->builtin_types.entry_global_error_set = entry; |
| 5187 | entry->type_ref = g->err_tag_type->type_ref; | 5205 | entry->type_ref = g->err_tag_type->type_ref; |
| 5188 | entry->di_type = g->err_tag_type->di_type; | 5206 | |
| 5207 | entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, | ||
| 5208 | ZigLLVMTag_DW_enumeration_type(), "error", | ||
| 5209 | ZigLLVMCompileUnitToScope(g->compile_unit), nullptr, 0); | ||
| 5210 | |||
| 5211 | // reserve index 0 to indicate no error | ||
| 5212 | g->err_enumerators.append(ZigLLVMCreateDebugEnumerator(g->dbuilder, "(none)", 0)); | ||
| 5213 | g->errors_by_index.append(nullptr); | ||
| 5189 | 5214 | ||
| 5190 | g->primitive_type_table.put(&entry->name, entry); | 5215 | g->primitive_type_table.put(&entry->name, entry); |
| 5191 | } | 5216 | } |
| ... | @@ -5815,7 +5840,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry | ... | @@ -5815,7 +5840,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry |
| 5815 | case TypeTableEntryIdBoundFn: | 5840 | case TypeTableEntryIdBoundFn: |
| 5816 | case TypeTableEntryIdArgTuple: | 5841 | case TypeTableEntryIdArgTuple: |
| 5817 | case TypeTableEntryIdErrorUnion: | 5842 | case TypeTableEntryIdErrorUnion: |
| 5818 | case TypeTableEntryIdPureError: | 5843 | case TypeTableEntryIdErrorSet: |
| 5819 | zig_unreachable(); | 5844 | zig_unreachable(); |
| 5820 | case TypeTableEntryIdVoid: | 5845 | case TypeTableEntryIdVoid: |
| 5821 | case TypeTableEntryIdUnreachable: | 5846 | case TypeTableEntryIdUnreachable: |
| ... | @@ -5988,7 +6013,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf | ... | @@ -5988,7 +6013,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf |
| 5988 | return; | 6013 | return; |
| 5989 | } | 6014 | } |
| 5990 | case TypeTableEntryIdErrorUnion: | 6015 | case TypeTableEntryIdErrorUnion: |
| 5991 | case TypeTableEntryIdPureError: | 6016 | case TypeTableEntryIdErrorSet: |
| 5992 | case TypeTableEntryIdFn: | 6017 | case TypeTableEntryIdFn: |
| 5993 | zig_panic("TODO implement get_c_type for more types"); | 6018 | zig_panic("TODO implement get_c_type for more types"); |
| 5994 | case TypeTableEntryIdInvalid: | 6019 | case TypeTableEntryIdInvalid: |
| ... | @@ -6155,7 +6180,7 @@ static void gen_h_file(CodeGen *g) { | ... | @@ -6155,7 +6180,7 @@ static void gen_h_file(CodeGen *g) { |
| 6155 | case TypeTableEntryIdUndefLit: | 6180 | case TypeTableEntryIdUndefLit: |
| 6156 | case TypeTableEntryIdNullLit: | 6181 | case TypeTableEntryIdNullLit: |
| 6157 | case TypeTableEntryIdErrorUnion: | 6182 | case TypeTableEntryIdErrorUnion: |
| 6158 | case TypeTableEntryIdPureError: | 6183 | case TypeTableEntryIdErrorSet: |
| 6159 | case TypeTableEntryIdNamespace: | 6184 | case TypeTableEntryIdNamespace: |
| 6160 | case TypeTableEntryIdBlock: | 6185 | case TypeTableEntryIdBlock: |
| 6161 | case TypeTableEntryIdBoundFn: | 6186 | case TypeTableEntryIdBoundFn: |
src/ir.cpp+533-163| ... | @@ -580,6 +580,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorReturnTrace | ... | @@ -580,6 +580,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorReturnTrace |
| 580 | return IrInstructionIdErrorReturnTrace; | 580 | return IrInstructionIdErrorReturnTrace; |
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorUnion *) { | ||
| 584 | return IrInstructionIdErrorUnion; | ||
| 585 | } | ||
| 586 | |||
| 583 | template<typename T> | 587 | template<typename T> |
| 584 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 588 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 585 | T *special_instruction = allocate<T>(1); | 589 | T *special_instruction = allocate<T>(1); |
| ... | @@ -2326,6 +2330,19 @@ static IrInstruction *ir_build_error_return_trace(IrBuilder *irb, Scope *scope, | ... | @@ -2326,6 +2330,19 @@ static IrInstruction *ir_build_error_return_trace(IrBuilder *irb, Scope *scope, |
| 2326 | return &instruction->base; | 2330 | return &instruction->base; |
| 2327 | } | 2331 | } |
| 2328 | 2332 | ||
| 2333 | static IrInstruction *ir_build_error_union(IrBuilder *irb, Scope *scope, AstNode *source_node, | ||
| 2334 | IrInstruction *err_set, IrInstruction *payload) | ||
| 2335 | { | ||
| 2336 | IrInstructionErrorUnion *instruction = ir_build_instruction<IrInstructionErrorUnion>(irb, scope, source_node); | ||
| 2337 | instruction->err_set = err_set; | ||
| 2338 | instruction->payload = payload; | ||
| 2339 | |||
| 2340 | ir_ref_instruction(err_set, irb->current_basic_block); | ||
| 2341 | ir_ref_instruction(payload, irb->current_basic_block); | ||
| 2342 | |||
| 2343 | return &instruction->base; | ||
| 2344 | } | ||
| 2345 | |||
| 2329 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 2346 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2330 | results[ReturnKindUnconditional] = 0; | 2347 | results[ReturnKindUnconditional] = 0; |
| 2331 | results[ReturnKindError] = 0; | 2348 | results[ReturnKindError] = 0; |
| ... | @@ -2800,6 +2817,23 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As | ... | @@ -2800,6 +2817,23 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As |
| 2800 | return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values); | 2817 | return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values); |
| 2801 | } | 2818 | } |
| 2802 | 2819 | ||
| 2820 | static IrInstruction *ir_gen_error_union(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | ||
| 2821 | assert(node->type == NodeTypeBinOpExpr); | ||
| 2822 | |||
| 2823 | AstNode *op1_node = node->data.bin_op_expr.op1; | ||
| 2824 | AstNode *op2_node = node->data.bin_op_expr.op2; | ||
| 2825 | |||
| 2826 | IrInstruction *err_set = ir_gen_node(irb, op1_node, parent_scope); | ||
| 2827 | if (err_set == irb->codegen->invalid_instruction) | ||
| 2828 | return irb->codegen->invalid_instruction; | ||
| 2829 | |||
| 2830 | IrInstruction *payload = ir_gen_node(irb, op2_node, parent_scope); | ||
| 2831 | if (payload == irb->codegen->invalid_instruction) | ||
| 2832 | return irb->codegen->invalid_instruction; | ||
| 2833 | |||
| 2834 | return ir_build_error_union(irb, parent_scope, node, err_set, payload); | ||
| 2835 | } | ||
| 2836 | |||
| 2803 | static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) { | 2837 | static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 2804 | assert(node->type == NodeTypeBinOpExpr); | 2838 | assert(node->type == NodeTypeBinOpExpr); |
| 2805 | 2839 | ||
| ... | @@ -2887,6 +2921,8 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) | ... | @@ -2887,6 +2921,8 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) |
| 2887 | return ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult); | 2921 | return ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult); |
| 2888 | case BinOpTypeUnwrapMaybe: | 2922 | case BinOpTypeUnwrapMaybe: |
| 2889 | return ir_gen_maybe_ok_or(irb, scope, node); | 2923 | return ir_gen_maybe_ok_or(irb, scope, node); |
| 2924 | case BinOpTypeErrorUnion: | ||
| 2925 | return ir_gen_error_union(irb, scope, node); | ||
| 2890 | } | 2926 | } |
| 2891 | zig_unreachable(); | 2927 | zig_unreachable(); |
| 2892 | } | 2928 | } |
| ... | @@ -3990,8 +4026,6 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod | ... | @@ -3990,8 +4026,6 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod |
| 3990 | return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval); | 4026 | return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval); |
| 3991 | case PrefixOpMaybe: | 4027 | case PrefixOpMaybe: |
| 3992 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe), lval); | 4028 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe), lval); |
| 3993 | case PrefixOpError: | ||
| 3994 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpError), lval); | ||
| 3995 | case PrefixOpUnwrapMaybe: | 4029 | case PrefixOpUnwrapMaybe: |
| 3996 | return ir_gen_maybe_assert_ok(irb, scope, node, lval); | 4030 | return ir_gen_maybe_assert_ok(irb, scope, node, lval); |
| 3997 | } | 4031 | } |
| ... | @@ -5165,7 +5199,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast | ... | @@ -5165,7 +5199,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast |
| 5165 | 5199 | ||
| 5166 | static IrInstruction *ir_gen_error_type(IrBuilder *irb, Scope *scope, AstNode *node) { | 5200 | static IrInstruction *ir_gen_error_type(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 5167 | assert(node->type == NodeTypeErrorType); | 5201 | assert(node->type == NodeTypeErrorType); |
| 5168 | return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_pure_error); | 5202 | return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_global_error_set); |
| 5169 | } | 5203 | } |
| 5170 | 5204 | ||
| 5171 | static IrInstruction *ir_gen_defer(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | 5205 | static IrInstruction *ir_gen_defer(IrBuilder *irb, Scope *parent_scope, AstNode *node) { |
| ... | @@ -5249,8 +5283,6 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN | ... | @@ -5249,8 +5283,6 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN |
| 5249 | Scope *err_scope; | 5283 | Scope *err_scope; |
| 5250 | if (var_node) { | 5284 | if (var_node) { |
| 5251 | assert(var_node->type == NodeTypeSymbol); | 5285 | assert(var_node->type == NodeTypeSymbol); |
| 5252 | IrInstruction *var_type = ir_build_const_type(irb, parent_scope, node, | ||
| 5253 | irb->codegen->builtin_types.entry_pure_error); | ||
| 5254 | Buf *var_name = var_node->data.symbol_expr.symbol; | 5286 | Buf *var_name = var_node->data.symbol_expr.symbol; |
| 5255 | bool is_const = true; | 5287 | bool is_const = true; |
| 5256 | bool is_shadowable = false; | 5288 | bool is_shadowable = false; |
| ... | @@ -5258,7 +5290,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN | ... | @@ -5258,7 +5290,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN |
| 5258 | is_const, is_const, is_shadowable, is_comptime); | 5290 | is_const, is_const, is_shadowable, is_comptime); |
| 5259 | err_scope = var->child_scope; | 5291 | err_scope = var->child_scope; |
| 5260 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr); | 5292 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr); |
| 5261 | ir_build_var_decl(irb, err_scope, var_node, var, var_type, nullptr, err_val); | 5293 | ir_build_var_decl(irb, err_scope, var_node, var, nullptr, nullptr, err_val); |
| 5262 | } else { | 5294 | } else { |
| 5263 | err_scope = parent_scope; | 5295 | err_scope = parent_scope; |
| 5264 | } | 5296 | } |
| ... | @@ -5348,6 +5380,70 @@ static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, | ... | @@ -5348,6 +5380,70 @@ static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, |
| 5348 | return ir_build_const_type(irb, parent_scope, node, container_type); | 5380 | return ir_build_const_type(irb, parent_scope, node, container_type); |
| 5349 | } | 5381 | } |
| 5350 | 5382 | ||
| 5383 | static TypeTableEntry *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstNode *node, | ||
| 5384 | ErrorTableEntry *err_entry) | ||
| 5385 | { | ||
| 5386 | TypeTableEntry *err_set_type = new_type_table_entry(TypeTableEntryIdErrorSet); | ||
| 5387 | buf_resize(&err_set_type->name, 0); | ||
| 5388 | buf_appendf(&err_set_type->name, "@typeOf(error.%s)", buf_ptr(&err_entry->name)); | ||
| 5389 | err_set_type->is_copyable = true; | ||
| 5390 | err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref; | ||
| 5391 | err_set_type->di_type = g->builtin_types.entry_global_error_set->di_type; | ||
| 5392 | err_set_type->data.error_set.err_count = 1; | ||
| 5393 | err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(1); | ||
| 5394 | |||
| 5395 | g->error_di_types.append(&err_set_type->di_type); | ||
| 5396 | |||
| 5397 | err_set_type->data.error_set.errors[0] = err_entry; | ||
| 5398 | |||
| 5399 | return err_set_type; | ||
| 5400 | } | ||
| 5401 | |||
| 5402 | static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | ||
| 5403 | assert(node->type == NodeTypeErrorSetDecl); | ||
| 5404 | |||
| 5405 | uint32_t err_count = node->data.err_set_decl.decls.length; | ||
| 5406 | |||
| 5407 | if (err_count == 0) { | ||
| 5408 | add_node_error(irb->codegen, node, buf_sprintf("empty error set")); | ||
| 5409 | return irb->codegen->invalid_instruction; | ||
| 5410 | } | ||
| 5411 | |||
| 5412 | Buf *type_name = get_anon_type_name(irb->codegen, irb->exec, "error set", node); | ||
| 5413 | TypeTableEntry *err_set_type = new_type_table_entry(TypeTableEntryIdErrorSet); | ||
| 5414 | buf_init_from_buf(&err_set_type->name, type_name); | ||
| 5415 | err_set_type->is_copyable = true; | ||
| 5416 | err_set_type->type_ref = irb->codegen->builtin_types.entry_global_error_set->type_ref; | ||
| 5417 | err_set_type->di_type = irb->codegen->builtin_types.entry_global_error_set->di_type; | ||
| 5418 | err_set_type->data.error_set.err_count = err_count; | ||
| 5419 | err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(err_count); | ||
| 5420 | |||
| 5421 | irb->codegen->error_di_types.append(&err_set_type->di_type); | ||
| 5422 | |||
| 5423 | for (uint32_t i = 0; i < err_count; i += 1) { | ||
| 5424 | AstNode *symbol_node = node->data.err_set_decl.decls.at(i); | ||
| 5425 | assert(symbol_node->type == NodeTypeSymbol); | ||
| 5426 | Buf *err_name = symbol_node->data.symbol_expr.symbol; | ||
| 5427 | ErrorTableEntry *err = allocate<ErrorTableEntry>(1); | ||
| 5428 | err->decl_node = symbol_node; | ||
| 5429 | buf_init_from_buf(&err->name, err_name); | ||
| 5430 | |||
| 5431 | auto existing_entry = irb->codegen->error_table.put_unique(err_name, err); | ||
| 5432 | if (existing_entry) { | ||
| 5433 | err->value = existing_entry->value->value; | ||
| 5434 | } else { | ||
| 5435 | size_t error_value_count = irb->codegen->errors_by_index.length; | ||
| 5436 | assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)irb->codegen->err_tag_type->data.integral.bit_count)); | ||
| 5437 | err->value = error_value_count; | ||
| 5438 | irb->codegen->errors_by_index.append(err); | ||
| 5439 | irb->codegen->err_enumerators.append(ZigLLVMCreateDebugEnumerator(irb->codegen->dbuilder, | ||
| 5440 | buf_ptr(err_name), error_value_count)); | ||
| 5441 | } | ||
| 5442 | err_set_type->data.error_set.errors[i] = err; | ||
| 5443 | } | ||
| 5444 | return ir_build_const_type(irb, parent_scope, node, err_set_type); | ||
| 5445 | } | ||
| 5446 | |||
| 5351 | static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | 5447 | static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNode *node) { |
| 5352 | assert(node->type == NodeTypeFnProto); | 5448 | assert(node->type == NodeTypeFnProto); |
| 5353 | 5449 | ||
| ... | @@ -5401,7 +5497,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop | ... | @@ -5401,7 +5497,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 5401 | case NodeTypeStructField: | 5497 | case NodeTypeStructField: |
| 5402 | case NodeTypeFnDef: | 5498 | case NodeTypeFnDef: |
| 5403 | case NodeTypeFnDecl: | 5499 | case NodeTypeFnDecl: |
| 5404 | case NodeTypeErrorValueDecl: | ||
| 5405 | case NodeTypeTestDecl: | 5500 | case NodeTypeTestDecl: |
| 5406 | zig_unreachable(); | 5501 | zig_unreachable(); |
| 5407 | case NodeTypeBlock: | 5502 | case NodeTypeBlock: |
| ... | @@ -5482,6 +5577,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop | ... | @@ -5482,6 +5577,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 5482 | return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval); | 5577 | return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval); |
| 5483 | case NodeTypeFnProto: | 5578 | case NodeTypeFnProto: |
| 5484 | return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval); | 5579 | return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval); |
| 5580 | case NodeTypeErrorSetDecl: | ||
| 5581 | return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval); | ||
| 5485 | } | 5582 | } |
| 5486 | zig_unreachable(); | 5583 | zig_unreachable(); |
| 5487 | } | 5584 | } |
| ... | @@ -6301,25 +6398,32 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, | ... | @@ -6301,25 +6398,32 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, |
| 6301 | return ImplicitCastMatchResultYes; | 6398 | return ImplicitCastMatchResultYes; |
| 6302 | } | 6399 | } |
| 6303 | 6400 | ||
| 6304 | // implicit T to %T | 6401 | // implicit T to U!T |
| 6305 | if (expected_type->id == TypeTableEntryIdErrorUnion && | 6402 | if (expected_type->id == TypeTableEntryIdErrorUnion && |
| 6306 | ir_types_match_with_implicit_cast(ira, expected_type->data.error.child_type, actual_type, value)) | 6403 | ir_types_match_with_implicit_cast(ira, expected_type->data.error_union.payload_type, actual_type, value)) |
| 6307 | { | 6404 | { |
| 6308 | return ImplicitCastMatchResultYes; | 6405 | return ImplicitCastMatchResultYes; |
| 6309 | } | 6406 | } |
| 6310 | 6407 | ||
| 6311 | // implicit conversion from pure error to error union type | 6408 | // implicit conversion from error set to error union type |
| 6312 | if (expected_type->id == TypeTableEntryIdErrorUnion && | 6409 | if (expected_type->id == TypeTableEntryIdErrorUnion && |
| 6313 | actual_type->id == TypeTableEntryIdPureError) | 6410 | actual_type->id == TypeTableEntryIdErrorSet) |
| 6411 | { | ||
| 6412 | return ImplicitCastMatchResultYes; | ||
| 6413 | } | ||
| 6414 | |||
| 6415 | // implicit conversion from error set to another error set | ||
| 6416 | if (expected_type->id == TypeTableEntryIdErrorSet && | ||
| 6417 | actual_type->id == TypeTableEntryIdErrorSet) | ||
| 6314 | { | 6418 | { |
| 6315 | return ImplicitCastMatchResultYes; | 6419 | return ImplicitCastMatchResultYes; |
| 6316 | } | 6420 | } |
| 6317 | 6421 | ||
| 6318 | // implicit conversion from T to %?T | 6422 | // implicit conversion from T to U!?T |
| 6319 | if (expected_type->id == TypeTableEntryIdErrorUnion && | 6423 | if (expected_type->id == TypeTableEntryIdErrorUnion && |
| 6320 | expected_type->data.error.child_type->id == TypeTableEntryIdMaybe && | 6424 | expected_type->data.error_union.payload_type->id == TypeTableEntryIdMaybe && |
| 6321 | ir_types_match_with_implicit_cast(ira, | 6425 | ir_types_match_with_implicit_cast(ira, |
| 6322 | expected_type->data.error.child_type->data.maybe.child_type, | 6426 | expected_type->data.error_union.payload_type->data.maybe.child_type, |
| 6323 | actual_type, value)) | 6427 | actual_type, value)) |
| 6324 | { | 6428 | { |
| 6325 | return ImplicitCastMatchResultYes; | 6429 | return ImplicitCastMatchResultYes; |
| ... | @@ -6503,7 +6607,19 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod | ... | @@ -6503,7 +6607,19 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6503 | if (type_is_invalid(prev_inst->value.type)) { | 6607 | if (type_is_invalid(prev_inst->value.type)) { |
| 6504 | return ira->codegen->builtin_types.entry_invalid; | 6608 | return ira->codegen->builtin_types.entry_invalid; |
| 6505 | } | 6609 | } |
| 6506 | bool any_are_pure_error = (prev_inst->value.type->id == TypeTableEntryIdPureError); | 6610 | ErrorTableEntry **errors = nullptr; |
| 6611 | TypeTableEntry *err_set_type = nullptr; | ||
| 6612 | if (prev_inst->value.type == ira->codegen->builtin_types.entry_global_error_set) { | ||
| 6613 | err_set_type = ira->codegen->builtin_types.entry_global_error_set; | ||
| 6614 | } else if (prev_inst->value.type->id == TypeTableEntryIdErrorSet) { | ||
| 6615 | err_set_type = prev_inst->value.type; | ||
| 6616 | errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length); | ||
| 6617 | for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) { | ||
| 6618 | ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i]; | ||
| 6619 | errors[error_entry->value] = error_entry; | ||
| 6620 | } | ||
| 6621 | } | ||
| 6622 | |||
| 6507 | bool any_are_null = (prev_inst->value.type->id == TypeTableEntryIdNullLit); | 6623 | bool any_are_null = (prev_inst->value.type->id == TypeTableEntryIdNullLit); |
| 6508 | bool convert_to_const_slice = false; | 6624 | bool convert_to_const_slice = false; |
| 6509 | for (size_t i = 1; i < instruction_count; i += 1) { | 6625 | for (size_t i = 1; i < instruction_count; i += 1) { |
| ... | @@ -6524,27 +6640,133 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod | ... | @@ -6524,27 +6640,133 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6524 | continue; | 6640 | continue; |
| 6525 | } | 6641 | } |
| 6526 | 6642 | ||
| 6527 | if (prev_type->id == TypeTableEntryIdPureError) { | 6643 | if (prev_type->id == TypeTableEntryIdNullLit) { |
| 6528 | prev_inst = cur_inst; | 6644 | prev_inst = cur_inst; |
| 6529 | continue; | 6645 | continue; |
| 6530 | } | 6646 | } |
| 6531 | 6647 | ||
| 6532 | if (prev_type->id == TypeTableEntryIdNullLit) { | 6648 | if (cur_type->id == TypeTableEntryIdNullLit) { |
| 6533 | prev_inst = cur_inst; | 6649 | any_are_null = true; |
| 6534 | continue; | 6650 | continue; |
| 6535 | } | 6651 | } |
| 6536 | 6652 | ||
| 6537 | if (cur_type->id == TypeTableEntryIdPureError) { | 6653 | if (prev_type->id == TypeTableEntryIdErrorSet) { |
| 6538 | if (prev_type->id == TypeTableEntryIdArray) { | 6654 | assert(err_set_type != nullptr); |
| 6539 | convert_to_const_slice = true; | 6655 | if (cur_type->id == TypeTableEntryIdErrorSet) { |
| 6656 | if (err_set_type == ira->codegen->builtin_types.entry_global_error_set) { | ||
| 6657 | continue; | ||
| 6658 | } | ||
| 6659 | if (cur_type == ira->codegen->builtin_types.entry_global_error_set) { | ||
| 6660 | err_set_type = ira->codegen->builtin_types.entry_global_error_set; | ||
| 6661 | prev_inst = cur_inst; | ||
| 6662 | continue; | ||
| 6663 | } | ||
| 6664 | // if err_set_type is a superset of cur_type, keep err_set_type. | ||
| 6665 | // if cur_type is a superset of err_set_type, switch err_set_type to cur_type | ||
| 6666 | // otherwise emit a compile error | ||
| 6667 | bool prev_is_superset = true; | ||
| 6668 | for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) { | ||
| 6669 | ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i]; | ||
| 6670 | ErrorTableEntry *error_entry = errors[contained_error_entry->value]; | ||
| 6671 | if (error_entry == nullptr) { | ||
| 6672 | prev_is_superset = false; | ||
| 6673 | break; | ||
| 6674 | } | ||
| 6675 | } | ||
| 6676 | if (prev_is_superset) { | ||
| 6677 | continue; | ||
| 6678 | } | ||
| 6679 | |||
| 6680 | // unset everything in errors | ||
| 6681 | for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) { | ||
| 6682 | ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i]; | ||
| 6683 | errors[error_entry->value] = nullptr; | ||
| 6684 | } | ||
| 6685 | for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) { | ||
| 6686 | ErrorTableEntry *error_entry = cur_type->data.error_set.errors[i]; | ||
| 6687 | errors[error_entry->value] = error_entry; | ||
| 6688 | } | ||
| 6689 | bool cur_is_superset = true; | ||
| 6690 | for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) { | ||
| 6691 | ErrorTableEntry *contained_error_entry = err_set_type->data.error_set.errors[i]; | ||
| 6692 | ErrorTableEntry *error_entry = errors[contained_error_entry->value]; | ||
| 6693 | if (error_entry == nullptr) { | ||
| 6694 | cur_is_superset = false; | ||
| 6695 | break; | ||
| 6696 | } | ||
| 6697 | } | ||
| 6698 | if (cur_is_superset) { | ||
| 6699 | err_set_type = cur_inst->value.type; | ||
| 6700 | prev_inst = cur_inst; | ||
| 6701 | continue; | ||
| 6702 | } | ||
| 6703 | } else if (cur_type->id == TypeTableEntryIdErrorUnion) { | ||
| 6704 | // err_set_type must be a subset of cur_type's error set | ||
| 6705 | // unset everything in errors | ||
| 6706 | for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) { | ||
| 6707 | ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i]; | ||
| 6708 | errors[error_entry->value] = nullptr; | ||
| 6709 | } | ||
| 6710 | TypeTableEntry *cur_err_set_type = cur_type->data.error_union.err_set_type; | ||
| 6711 | for (uint32_t i = 0; i < cur_err_set_type->data.error_set.err_count; i += 1) { | ||
| 6712 | ErrorTableEntry *error_entry = cur_err_set_type->data.error_set.errors[i]; | ||
| 6713 | errors[error_entry->value] = error_entry; | ||
| 6714 | } | ||
| 6715 | bool cur_is_superset = true; | ||
| 6716 | for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) { | ||
| 6717 | ErrorTableEntry *contained_error_entry = err_set_type->data.error_set.errors[i]; | ||
| 6718 | ErrorTableEntry *error_entry = errors[contained_error_entry->value]; | ||
| 6719 | if (error_entry == nullptr) { | ||
| 6720 | cur_is_superset = false; | ||
| 6721 | break; | ||
| 6722 | } | ||
| 6723 | } | ||
| 6724 | if (cur_is_superset) { | ||
| 6725 | err_set_type = cur_err_set_type; | ||
| 6726 | prev_inst = cur_inst; | ||
| 6727 | continue; | ||
| 6728 | } | ||
| 6729 | } else { | ||
| 6730 | prev_inst = cur_inst; | ||
| 6731 | continue; | ||
| 6540 | } | 6732 | } |
| 6541 | any_are_pure_error = true; | ||
| 6542 | continue; | ||
| 6543 | } | 6733 | } |
| 6544 | 6734 | ||
| 6545 | if (cur_type->id == TypeTableEntryIdNullLit) { | 6735 | if (cur_type->id == TypeTableEntryIdErrorSet) { |
| 6546 | any_are_null = true; | 6736 | if (prev_type->id == TypeTableEntryIdArray) { |
| 6547 | continue; | 6737 | convert_to_const_slice = true; |
| 6738 | } | ||
| 6739 | if (cur_type == ira->codegen->builtin_types.entry_global_error_set) { | ||
| 6740 | err_set_type = ira->codegen->builtin_types.entry_global_error_set; | ||
| 6741 | continue; | ||
| 6742 | } | ||
| 6743 | if (err_set_type == ira->codegen->builtin_types.entry_global_error_set) { | ||
| 6744 | continue; | ||
| 6745 | } | ||
| 6746 | if (err_set_type == nullptr) { | ||
| 6747 | err_set_type = cur_type; | ||
| 6748 | errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length); | ||
| 6749 | for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) { | ||
| 6750 | ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i]; | ||
| 6751 | errors[error_entry->value] = error_entry; | ||
| 6752 | } | ||
| 6753 | continue; | ||
| 6754 | } | ||
| 6755 | if (prev_type->id == TypeTableEntryIdErrorUnion) { | ||
| 6756 | // the cur type error set must be a subset | ||
| 6757 | bool prev_is_superset = true; | ||
| 6758 | for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) { | ||
| 6759 | ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i]; | ||
| 6760 | ErrorTableEntry *error_entry = errors[contained_error_entry->value]; | ||
| 6761 | if (error_entry == nullptr) { | ||
| 6762 | prev_is_superset = false; | ||
| 6763 | break; | ||
| 6764 | } | ||
| 6765 | } | ||
| 6766 | if (prev_is_superset) { | ||
| 6767 | continue; | ||
| 6768 | } | ||
| 6769 | } | ||
| 6548 | } | 6770 | } |
| 6549 | 6771 | ||
| 6550 | if (types_match_const_cast_only(prev_type, cur_type)) { | 6772 | if (types_match_const_cast_only(prev_type, cur_type)) { |
| ... | @@ -6574,20 +6796,20 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod | ... | @@ -6574,20 +6796,20 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6574 | } | 6796 | } |
| 6575 | 6797 | ||
| 6576 | if (prev_type->id == TypeTableEntryIdErrorUnion && | 6798 | if (prev_type->id == TypeTableEntryIdErrorUnion && |
| 6577 | types_match_const_cast_only(prev_type->data.error.child_type, cur_type)) | 6799 | types_match_const_cast_only(prev_type->data.error_union.payload_type, cur_type)) |
| 6578 | { | 6800 | { |
| 6579 | continue; | 6801 | continue; |
| 6580 | } | 6802 | } |
| 6581 | 6803 | ||
| 6582 | if (cur_type->id == TypeTableEntryIdErrorUnion && | 6804 | if (cur_type->id == TypeTableEntryIdErrorUnion && |
| 6583 | types_match_const_cast_only(cur_type->data.error.child_type, prev_type)) | 6805 | types_match_const_cast_only(cur_type->data.error_union.payload_type, prev_type)) |
| 6584 | { | 6806 | { |
| 6585 | prev_inst = cur_inst; | 6807 | prev_inst = cur_inst; |
| 6586 | continue; | 6808 | continue; |
| 6587 | } | 6809 | } |
| 6588 | 6810 | ||
| 6589 | if (prev_type->id == TypeTableEntryIdMaybe && | 6811 | if (prev_type->id == TypeTableEntryIdMaybe && |
| 6590 | types_match_const_cast_only(prev_type->data.maybe.child_type, cur_type)) | 6812 | types_match_const_cast_only(prev_type->data.maybe.child_type, cur_type)) |
| 6591 | { | 6813 | { |
| 6592 | continue; | 6814 | continue; |
| 6593 | } | 6815 | } |
| ... | @@ -6700,16 +6922,19 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod | ... | @@ -6700,16 +6922,19 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6700 | 6922 | ||
| 6701 | return ira->codegen->builtin_types.entry_invalid; | 6923 | return ira->codegen->builtin_types.entry_invalid; |
| 6702 | } | 6924 | } |
| 6925 | |||
| 6926 | free(errors); | ||
| 6927 | |||
| 6703 | if (convert_to_const_slice) { | 6928 | if (convert_to_const_slice) { |
| 6704 | assert(prev_inst->value.type->id == TypeTableEntryIdArray); | 6929 | assert(prev_inst->value.type->id == TypeTableEntryIdArray); |
| 6705 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, prev_inst->value.type->data.array.child_type, true); | 6930 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, prev_inst->value.type->data.array.child_type, true); |
| 6706 | TypeTableEntry *slice_type = get_slice_type(ira->codegen, ptr_type); | 6931 | TypeTableEntry *slice_type = get_slice_type(ira->codegen, ptr_type); |
| 6707 | if (any_are_pure_error) { | 6932 | if (err_set_type != nullptr) { |
| 6708 | return get_error_type(ira->codegen, slice_type); | 6933 | return get_error_union_type(ira->codegen, err_set_type, slice_type); |
| 6709 | } else { | 6934 | } else { |
| 6710 | return slice_type; | 6935 | return slice_type; |
| 6711 | } | 6936 | } |
| 6712 | } else if (any_are_pure_error && prev_inst->value.type->id != TypeTableEntryIdPureError) { | 6937 | } else if (err_set_type != nullptr && prev_inst->value.type->id != TypeTableEntryIdErrorSet) { |
| 6713 | if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt || | 6938 | if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt || |
| 6714 | prev_inst->value.type->id == TypeTableEntryIdNumLitFloat) | 6939 | prev_inst->value.type->id == TypeTableEntryIdNumLitFloat) |
| 6715 | { | 6940 | { |
| ... | @@ -6723,7 +6948,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod | ... | @@ -6723,7 +6948,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6723 | } else if (prev_inst->value.type->id == TypeTableEntryIdErrorUnion) { | 6948 | } else if (prev_inst->value.type->id == TypeTableEntryIdErrorUnion) { |
| 6724 | return prev_inst->value.type; | 6949 | return prev_inst->value.type; |
| 6725 | } else { | 6950 | } else { |
| 6726 | return get_error_type(ira->codegen, prev_inst->value.type); | 6951 | return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type); |
| 6727 | } | 6952 | } |
| 6728 | } else if (any_are_null && prev_inst->value.type->id != TypeTableEntryIdNullLit) { | 6953 | } else if (any_are_null && prev_inst->value.type->id != TypeTableEntryIdNullLit) { |
| 6729 | if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt || | 6954 | if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt || |
| ... | @@ -7199,7 +7424,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction | ... | @@ -7199,7 +7424,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction |
| 7199 | assert(wanted_type->id == TypeTableEntryIdErrorUnion); | 7424 | assert(wanted_type->id == TypeTableEntryIdErrorUnion); |
| 7200 | 7425 | ||
| 7201 | if (instr_is_comptime(value)) { | 7426 | if (instr_is_comptime(value)) { |
| 7202 | TypeTableEntry *payload_type = wanted_type->data.error.child_type; | 7427 | TypeTableEntry *payload_type = wanted_type->data.error_union.payload_type; |
| 7203 | IrInstruction *casted_payload = ir_implicit_cast(ira, value, payload_type); | 7428 | IrInstruction *casted_payload = ir_implicit_cast(ira, value, payload_type); |
| 7204 | if (type_is_invalid(casted_payload->value.type)) | 7429 | if (type_is_invalid(casted_payload->value.type)) |
| 7205 | return ira->codegen->invalid_instruction; | 7430 | return ira->codegen->invalid_instruction; |
| ... | @@ -7224,8 +7449,43 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction | ... | @@ -7224,8 +7449,43 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction |
| 7224 | return result; | 7449 | return result; |
| 7225 | } | 7450 | } |
| 7226 | 7451 | ||
| 7227 | static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) { | 7452 | static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, |
| 7228 | assert(wanted_type->id == TypeTableEntryIdErrorUnion); | 7453 | TypeTableEntry *wanted_type) |
| 7454 | { | ||
| 7455 | TypeTableEntry *contained_set = value->value.type; | ||
| 7456 | TypeTableEntry *container_set = wanted_type; | ||
| 7457 | |||
| 7458 | assert(contained_set->id == TypeTableEntryIdErrorSet); | ||
| 7459 | assert(container_set->id == TypeTableEntryIdErrorSet); | ||
| 7460 | |||
| 7461 | if (container_set->data.error_set.infer_fn == nullptr && | ||
| 7462 | container_set != ira->codegen->builtin_types.entry_global_error_set) | ||
| 7463 | { | ||
| 7464 | ErrorTableEntry **errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length); | ||
| 7465 | for (uint32_t i = 0; i < container_set->data.error_set.err_count; i += 1) { | ||
| 7466 | ErrorTableEntry *error_entry = container_set->data.error_set.errors[i]; | ||
| 7467 | errors[error_entry->value] = error_entry; | ||
| 7468 | } | ||
| 7469 | ErrorMsg *err_msg = nullptr; | ||
| 7470 | for (uint32_t i = 0; i < contained_set->data.error_set.err_count; i += 1) { | ||
| 7471 | ErrorTableEntry *contained_error_entry = contained_set->data.error_set.errors[i]; | ||
| 7472 | ErrorTableEntry *error_entry = errors[contained_error_entry->value]; | ||
| 7473 | if (error_entry == nullptr) { | ||
| 7474 | if (err_msg == nullptr) { | ||
| 7475 | err_msg = ir_add_error(ira, source_instr, | ||
| 7476 | buf_sprintf("invalid cast of error set '%s' to error set '%s'", | ||
| 7477 | buf_ptr(&contained_set->name), buf_ptr(&container_set->name))); | ||
| 7478 | } | ||
| 7479 | add_error_note(ira->codegen, err_msg, contained_error_entry->decl_node, | ||
| 7480 | buf_sprintf("'%s.%s' not present in '%s'", buf_ptr(&contained_set->name), | ||
| 7481 | buf_ptr(&contained_error_entry->name), buf_ptr(&container_set->name))); | ||
| 7482 | } | ||
| 7483 | } | ||
| 7484 | free(errors); | ||
| 7485 | if (err_msg != nullptr) { | ||
| 7486 | return ira->codegen->invalid_instruction; | ||
| 7487 | } | ||
| 7488 | } | ||
| 7229 | 7489 | ||
| 7230 | if (instr_is_comptime(value)) { | 7490 | if (instr_is_comptime(value)) { |
| 7231 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); | 7491 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); |
| ... | @@ -7236,7 +7496,30 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so | ... | @@ -7236,7 +7496,30 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so |
| 7236 | source_instr->scope, source_instr->source_node); | 7496 | source_instr->scope, source_instr->source_node); |
| 7237 | const_instruction->base.value.type = wanted_type; | 7497 | const_instruction->base.value.type = wanted_type; |
| 7238 | const_instruction->base.value.special = ConstValSpecialStatic; | 7498 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 7239 | const_instruction->base.value.data.x_err_union.err = val->data.x_pure_err; | 7499 | const_instruction->base.value.data.x_err_set = val->data.x_err_set; |
| 7500 | return &const_instruction->base; | ||
| 7501 | } | ||
| 7502 | |||
| 7503 | IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type, value, CastOpNoop); | ||
| 7504 | result->value.type = wanted_type; | ||
| 7505 | return result; | ||
| 7506 | } | ||
| 7507 | |||
| 7508 | static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) { | ||
| 7509 | assert(wanted_type->id == TypeTableEntryIdErrorUnion); | ||
| 7510 | |||
| 7511 | IrInstruction *casted_value = ir_implicit_cast(ira, value, wanted_type->data.error_union.err_set_type); | ||
| 7512 | |||
| 7513 | if (instr_is_comptime(casted_value)) { | ||
| 7514 | ConstExprValue *val = ir_resolve_const(ira, casted_value, UndefBad); | ||
| 7515 | if (!val) | ||
| 7516 | return ira->codegen->invalid_instruction; | ||
| 7517 | |||
| 7518 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, | ||
| 7519 | source_instr->scope, source_instr->source_node); | ||
| 7520 | const_instruction->base.value.type = wanted_type; | ||
| 7521 | const_instruction->base.value.special = ConstValSpecialStatic; | ||
| 7522 | const_instruction->base.value.data.x_err_union.err = val->data.x_err_set; | ||
| 7240 | const_instruction->base.value.data.x_err_union.payload = nullptr; | 7523 | const_instruction->base.value.data.x_err_union.payload = nullptr; |
| 7241 | return &const_instruction->base; | 7524 | return &const_instruction->base; |
| 7242 | } | 7525 | } |
| ... | @@ -7616,9 +7899,12 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction | ... | @@ -7616,9 +7899,12 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction |
| 7616 | return result; | 7899 | return result; |
| 7617 | } | 7900 | } |
| 7618 | 7901 | ||
| 7619 | static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target) { | 7902 | static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, |
| 7903 | TypeTableEntry *wanted_type) | ||
| 7904 | { | ||
| 7620 | assert(target->value.type->id == TypeTableEntryIdInt); | 7905 | assert(target->value.type->id == TypeTableEntryIdInt); |
| 7621 | assert(!target->value.type->data.integral.is_signed); | 7906 | assert(!target->value.type->data.integral.is_signed); |
| 7907 | assert(wanted_type->id == TypeTableEntryIdErrorSet); | ||
| 7622 | 7908 | ||
| 7623 | if (instr_is_comptime(target)) { | 7909 | if (instr_is_comptime(target)) { |
| 7624 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); | 7910 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); |
| ... | @@ -7626,10 +7912,10 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc | ... | @@ -7626,10 +7912,10 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc |
| 7626 | return ira->codegen->invalid_instruction; | 7912 | return ira->codegen->invalid_instruction; |
| 7627 | 7913 | ||
| 7628 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | 7914 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, |
| 7629 | source_instr->source_node, ira->codegen->builtin_types.entry_pure_error); | 7915 | source_instr->source_node, wanted_type); |
| 7630 | 7916 | ||
| 7631 | BigInt err_count; | 7917 | BigInt err_count; |
| 7632 | bigint_init_unsigned(&err_count, ira->codegen->error_decls.length); | 7918 | bigint_init_unsigned(&err_count, ira->codegen->errors_by_index.length); |
| 7633 | if (bigint_cmp_zero(&val->data.x_bigint) == CmpEQ || bigint_cmp(&val->data.x_bigint, &err_count) != CmpLT) { | 7919 | if (bigint_cmp_zero(&val->data.x_bigint) == CmpEQ || bigint_cmp(&val->data.x_bigint, &err_count) != CmpLT) { |
| 7634 | Buf *val_buf = buf_alloc(); | 7920 | Buf *val_buf = buf_alloc(); |
| 7635 | bigint_append_buf(val_buf, &val->data.x_bigint, 10); | 7921 | bigint_append_buf(val_buf, &val->data.x_bigint, 10); |
| ... | @@ -7639,13 +7925,12 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc | ... | @@ -7639,13 +7925,12 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc |
| 7639 | } | 7925 | } |
| 7640 | 7926 | ||
| 7641 | size_t index = bigint_as_unsigned(&val->data.x_bigint); | 7927 | size_t index = bigint_as_unsigned(&val->data.x_bigint); |
| 7642 | AstNode *error_decl_node = ira->codegen->error_decls.at(index); | 7928 | result->value.data.x_err_set = ira->codegen->errors_by_index.at(index); |
| 7643 | result->value.data.x_pure_err = error_decl_node->data.error_value_decl.err; | ||
| 7644 | return result; | 7929 | return result; |
| 7645 | } | 7930 | } |
| 7646 | 7931 | ||
| 7647 | IrInstruction *result = ir_build_int_to_err(&ira->new_irb, source_instr->scope, source_instr->source_node, target); | 7932 | IrInstruction *result = ir_build_int_to_err(&ira->new_irb, source_instr->scope, source_instr->source_node, target); |
| 7648 | result->value.type = ira->codegen->builtin_types.entry_pure_error; | 7933 | result->value.type = wanted_type; |
| 7649 | return result; | 7934 | return result; |
| 7650 | } | 7935 | } |
| 7651 | 7936 | ||
| ... | @@ -7667,8 +7952,8 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc | ... | @@ -7667,8 +7952,8 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc |
| 7667 | ErrorTableEntry *err; | 7952 | ErrorTableEntry *err; |
| 7668 | if (err_type->id == TypeTableEntryIdErrorUnion) { | 7953 | if (err_type->id == TypeTableEntryIdErrorUnion) { |
| 7669 | err = val->data.x_err_union.err; | 7954 | err = val->data.x_err_union.err; |
| 7670 | } else if (err_type->id == TypeTableEntryIdPureError) { | 7955 | } else if (err_type->id == TypeTableEntryIdErrorSet) { |
| 7671 | err = val->data.x_pure_err; | 7956 | err = val->data.x_err_set; |
| 7672 | } else { | 7957 | } else { |
| 7673 | zig_unreachable(); | 7958 | zig_unreachable(); |
| 7674 | } | 7959 | } |
| ... | @@ -7689,7 +7974,7 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc | ... | @@ -7689,7 +7974,7 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc |
| 7689 | } | 7974 | } |
| 7690 | 7975 | ||
| 7691 | BigInt bn; | 7976 | BigInt bn; |
| 7692 | bigint_init_unsigned(&bn, ira->codegen->error_decls.length); | 7977 | bigint_init_unsigned(&bn, ira->codegen->errors_by_index.length); |
| 7693 | if (!bigint_fits_in_bits(&bn, wanted_type->data.integral.bit_count, wanted_type->data.integral.is_signed)) { | 7978 | if (!bigint_fits_in_bits(&bn, wanted_type->data.integral.bit_count, wanted_type->data.integral.is_signed)) { |
| 7694 | ir_add_error_node(ira, source_instr->source_node, | 7979 | ir_add_error_node(ira, source_instr->source_node, |
| 7695 | buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name))); | 7980 | buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name))); |
| ... | @@ -7734,6 +8019,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -7734,6 +8019,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 7734 | return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type); | 8019 | return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type); |
| 7735 | } | 8020 | } |
| 7736 | 8021 | ||
| 8022 | // explicit error set cast | ||
| 8023 | if (wanted_type->id == TypeTableEntryIdErrorSet && | ||
| 8024 | actual_type->id == TypeTableEntryIdErrorSet) | ||
| 8025 | { | ||
| 8026 | return ir_analyze_err_set_cast(ira, source_instr, value, wanted_type); | ||
| 8027 | } | ||
| 8028 | |||
| 7737 | // explicit cast from int to float | 8029 | // explicit cast from int to float |
| 7738 | if (wanted_type->id == TypeTableEntryIdFloat && | 8030 | if (wanted_type->id == TypeTableEntryIdFloat && |
| 7739 | actual_type->id == TypeTableEntryIdInt) | 8031 | actual_type->id == TypeTableEntryIdInt) |
| ... | @@ -7894,12 +8186,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -7894,12 +8186,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 7894 | 8186 | ||
| 7895 | // explicit cast from child type of error type to error type | 8187 | // explicit cast from child type of error type to error type |
| 7896 | if (wanted_type->id == TypeTableEntryIdErrorUnion) { | 8188 | if (wanted_type->id == TypeTableEntryIdErrorUnion) { |
| 7897 | if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) { | 8189 | if (types_match_const_cast_only(wanted_type->data.error_union.payload_type, actual_type)) { |
| 7898 | return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); | 8190 | return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); |
| 7899 | } else if (actual_type->id == TypeTableEntryIdNumLitInt || | 8191 | } else if (actual_type->id == TypeTableEntryIdNumLitInt || |
| 7900 | actual_type->id == TypeTableEntryIdNumLitFloat) | 8192 | actual_type->id == TypeTableEntryIdNumLitFloat) |
| 7901 | { | 8193 | { |
| 7902 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error.child_type, true)) { | 8194 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) { |
| 7903 | return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); | 8195 | return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type); |
| 7904 | } else { | 8196 | } else { |
| 7905 | return ira->codegen->invalid_instruction; | 8197 | return ira->codegen->invalid_instruction; |
| ... | @@ -7909,16 +8201,16 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -7909,16 +8201,16 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 7909 | 8201 | ||
| 7910 | // explicit cast from [N]T to %[]const T | 8202 | // explicit cast from [N]T to %[]const T |
| 7911 | if (wanted_type->id == TypeTableEntryIdErrorUnion && | 8203 | if (wanted_type->id == TypeTableEntryIdErrorUnion && |
| 7912 | is_slice(wanted_type->data.error.child_type) && | 8204 | is_slice(wanted_type->data.error_union.payload_type) && |
| 7913 | actual_type->id == TypeTableEntryIdArray) | 8205 | actual_type->id == TypeTableEntryIdArray) |
| 7914 | { | 8206 | { |
| 7915 | TypeTableEntry *ptr_type = | 8207 | TypeTableEntry *ptr_type = |
| 7916 | wanted_type->data.error.child_type->data.structure.fields[slice_ptr_index].type_entry; | 8208 | wanted_type->data.error_union.payload_type->data.structure.fields[slice_ptr_index].type_entry; |
| 7917 | assert(ptr_type->id == TypeTableEntryIdPointer); | 8209 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 7918 | if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) && | 8210 | if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) && |
| 7919 | types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type)) | 8211 | types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type)) |
| 7920 | { | 8212 | { |
| 7921 | IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error.child_type, value); | 8213 | IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value); |
| 7922 | if (type_is_invalid(cast1->value.type)) | 8214 | if (type_is_invalid(cast1->value.type)) |
| 7923 | return ira->codegen->invalid_instruction; | 8215 | return ira->codegen->invalid_instruction; |
| 7924 | 8216 | ||
| ... | @@ -7930,25 +8222,25 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -7930,25 +8222,25 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 7930 | } | 8222 | } |
| 7931 | } | 8223 | } |
| 7932 | 8224 | ||
| 7933 | // explicit cast from pure error to error union type | 8225 | // explicit cast from error set to error union type |
| 7934 | if (wanted_type->id == TypeTableEntryIdErrorUnion && | 8226 | if (wanted_type->id == TypeTableEntryIdErrorUnion && |
| 7935 | actual_type->id == TypeTableEntryIdPureError) | 8227 | actual_type->id == TypeTableEntryIdErrorSet) |
| 7936 | { | 8228 | { |
| 7937 | return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type); | 8229 | return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type); |
| 7938 | } | 8230 | } |
| 7939 | 8231 | ||
| 7940 | // explicit cast from T to %?T | 8232 | // explicit cast from T to %?T |
| 7941 | if (wanted_type->id == TypeTableEntryIdErrorUnion && | 8233 | if (wanted_type->id == TypeTableEntryIdErrorUnion && |
| 7942 | wanted_type->data.error.child_type->id == TypeTableEntryIdMaybe && | 8234 | wanted_type->data.error_union.payload_type->id == TypeTableEntryIdMaybe && |
| 7943 | actual_type->id != TypeTableEntryIdMaybe) | 8235 | actual_type->id != TypeTableEntryIdMaybe) |
| 7944 | { | 8236 | { |
| 7945 | TypeTableEntry *wanted_child_type = wanted_type->data.error.child_type->data.maybe.child_type; | 8237 | TypeTableEntry *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type; |
| 7946 | if (types_match_const_cast_only(wanted_child_type, actual_type) || | 8238 | if (types_match_const_cast_only(wanted_child_type, actual_type) || |
| 7947 | actual_type->id == TypeTableEntryIdNullLit || | 8239 | actual_type->id == TypeTableEntryIdNullLit || |
| 7948 | actual_type->id == TypeTableEntryIdNumLitInt || | 8240 | actual_type->id == TypeTableEntryIdNumLitInt || |
| 7949 | actual_type->id == TypeTableEntryIdNumLitFloat) | 8241 | actual_type->id == TypeTableEntryIdNumLitFloat) |
| 7950 | { | 8242 | { |
| 7951 | IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error.child_type, value); | 8243 | IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value); |
| 7952 | if (type_is_invalid(cast1->value.type)) | 8244 | if (type_is_invalid(cast1->value.type)) |
| 7953 | return ira->codegen->invalid_instruction; | 8245 | return ira->codegen->invalid_instruction; |
| 7954 | 8246 | ||
| ... | @@ -8017,21 +8309,19 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -8017,21 +8309,19 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 8017 | return ir_analyze_number_to_literal(ira, source_instr, value, wanted_type); | 8309 | return ir_analyze_number_to_literal(ira, source_instr, value, wanted_type); |
| 8018 | } | 8310 | } |
| 8019 | 8311 | ||
| 8020 | // explicit cast from %void to integer type which can fit it | 8312 | // explicit cast from T!void to integer type which can fit it |
| 8021 | bool actual_type_is_void_err = actual_type->id == TypeTableEntryIdErrorUnion && | 8313 | bool actual_type_is_void_err = actual_type->id == TypeTableEntryIdErrorUnion && |
| 8022 | !type_has_bits(actual_type->data.error.child_type); | 8314 | !type_has_bits(actual_type->data.error_union.payload_type); |
| 8023 | bool actual_type_is_pure_err = actual_type->id == TypeTableEntryIdPureError; | 8315 | bool actual_type_is_err_set = actual_type->id == TypeTableEntryIdErrorSet; |
| 8024 | if ((actual_type_is_void_err || actual_type_is_pure_err) && | 8316 | if ((actual_type_is_void_err || actual_type_is_err_set) && wanted_type->id == TypeTableEntryIdInt) { |
| 8025 | wanted_type->id == TypeTableEntryIdInt) | ||
| 8026 | { | ||
| 8027 | return ir_analyze_err_to_int(ira, source_instr, value, wanted_type); | 8317 | return ir_analyze_err_to_int(ira, source_instr, value, wanted_type); |
| 8028 | } | 8318 | } |
| 8029 | 8319 | ||
| 8030 | // explicit cast from integer to pure error | 8320 | // explicit cast from integer to error set |
| 8031 | if (wanted_type->id == TypeTableEntryIdPureError && actual_type->id == TypeTableEntryIdInt && | 8321 | if (wanted_type->id == TypeTableEntryIdErrorSet && actual_type->id == TypeTableEntryIdInt && |
| 8032 | !actual_type->data.integral.is_signed) | 8322 | !actual_type->data.integral.is_signed) |
| 8033 | { | 8323 | { |
| 8034 | return ir_analyze_int_to_err(ira, source_instr, value); | 8324 | return ir_analyze_int_to_err(ira, source_instr, value, wanted_type); |
| 8035 | } | 8325 | } |
| 8036 | 8326 | ||
| 8037 | // explicit cast from integer to enum type with no payload | 8327 | // explicit cast from integer to enum type with no payload |
| ... | @@ -8524,7 +8814,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -8524,7 +8814,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 8524 | case TypeTableEntryIdMetaType: | 8814 | case TypeTableEntryIdMetaType: |
| 8525 | case TypeTableEntryIdVoid: | 8815 | case TypeTableEntryIdVoid: |
| 8526 | case TypeTableEntryIdPointer: | 8816 | case TypeTableEntryIdPointer: |
| 8527 | case TypeTableEntryIdPureError: | 8817 | case TypeTableEntryIdErrorSet: |
| 8528 | case TypeTableEntryIdFn: | 8818 | case TypeTableEntryIdFn: |
| 8529 | case TypeTableEntryIdOpaque: | 8819 | case TypeTableEntryIdOpaque: |
| 8530 | case TypeTableEntryIdNamespace: | 8820 | case TypeTableEntryIdNamespace: |
| ... | @@ -9312,7 +9602,7 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) { | ... | @@ -9312,7 +9602,7 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) { |
| 9312 | case TypeTableEntryIdInt: | 9602 | case TypeTableEntryIdInt: |
| 9313 | case TypeTableEntryIdFloat: | 9603 | case TypeTableEntryIdFloat: |
| 9314 | case TypeTableEntryIdVoid: | 9604 | case TypeTableEntryIdVoid: |
| 9315 | case TypeTableEntryIdPureError: | 9605 | case TypeTableEntryIdErrorSet: |
| 9316 | case TypeTableEntryIdFn: | 9606 | case TypeTableEntryIdFn: |
| 9317 | return VarClassRequiredAny; | 9607 | return VarClassRequiredAny; |
| 9318 | case TypeTableEntryIdNumLitFloat: | 9608 | case TypeTableEntryIdNumLitFloat: |
| ... | @@ -9338,7 +9628,7 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) { | ... | @@ -9338,7 +9628,7 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) { |
| 9338 | case TypeTableEntryIdMaybe: | 9628 | case TypeTableEntryIdMaybe: |
| 9339 | return get_var_class_required(type_entry->data.maybe.child_type); | 9629 | return get_var_class_required(type_entry->data.maybe.child_type); |
| 9340 | case TypeTableEntryIdErrorUnion: | 9630 | case TypeTableEntryIdErrorUnion: |
| 9341 | return get_var_class_required(type_entry->data.error.child_type); | 9631 | return get_var_class_required(type_entry->data.error_union.payload_type); |
| 9342 | 9632 | ||
| 9343 | case TypeTableEntryIdStruct: | 9633 | case TypeTableEntryIdStruct: |
| 9344 | case TypeTableEntryIdEnum: | 9634 | case TypeTableEntryIdEnum: |
| ... | @@ -9573,7 +9863,7 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi | ... | @@ -9573,7 +9863,7 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi |
| 9573 | case TypeTableEntryIdNullLit: | 9863 | case TypeTableEntryIdNullLit: |
| 9574 | case TypeTableEntryIdMaybe: | 9864 | case TypeTableEntryIdMaybe: |
| 9575 | case TypeTableEntryIdErrorUnion: | 9865 | case TypeTableEntryIdErrorUnion: |
| 9576 | case TypeTableEntryIdPureError: | 9866 | case TypeTableEntryIdErrorSet: |
| 9577 | case TypeTableEntryIdNamespace: | 9867 | case TypeTableEntryIdNamespace: |
| 9578 | case TypeTableEntryIdBlock: | 9868 | case TypeTableEntryIdBlock: |
| 9579 | case TypeTableEntryIdBoundFn: | 9869 | case TypeTableEntryIdBoundFn: |
| ... | @@ -9596,7 +9886,7 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi | ... | @@ -9596,7 +9886,7 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi |
| 9596 | case TypeTableEntryIdNullLit: | 9886 | case TypeTableEntryIdNullLit: |
| 9597 | case TypeTableEntryIdMaybe: | 9887 | case TypeTableEntryIdMaybe: |
| 9598 | case TypeTableEntryIdErrorUnion: | 9888 | case TypeTableEntryIdErrorUnion: |
| 9599 | case TypeTableEntryIdPureError: | 9889 | case TypeTableEntryIdErrorSet: |
| 9600 | zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name)); | 9890 | zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name)); |
| 9601 | case TypeTableEntryIdNamespace: | 9891 | case TypeTableEntryIdNamespace: |
| 9602 | case TypeTableEntryIdBlock: | 9892 | case TypeTableEntryIdBlock: |
| ... | @@ -9630,6 +9920,24 @@ static TypeTableEntry *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, | ... | @@ -9630,6 +9920,24 @@ static TypeTableEntry *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, |
| 9630 | return nullable_type; | 9920 | return nullable_type; |
| 9631 | } | 9921 | } |
| 9632 | 9922 | ||
| 9923 | static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira, | ||
| 9924 | IrInstructionErrorUnion *instruction) | ||
| 9925 | { | ||
| 9926 | TypeTableEntry *err_set_type = ir_resolve_type(ira, instruction->err_set->other); | ||
| 9927 | if (type_is_invalid(err_set_type)) | ||
| 9928 | return ira->codegen->builtin_types.entry_invalid; | ||
| 9929 | |||
| 9930 | TypeTableEntry *payload_type = ir_resolve_type(ira, instruction->payload->other); | ||
| 9931 | if (type_is_invalid(payload_type)) | ||
| 9932 | return ira->codegen->builtin_types.entry_invalid; | ||
| 9933 | |||
| 9934 | TypeTableEntry *result_type = get_error_union_type(ira->codegen, err_set_type, payload_type); | ||
| 9935 | |||
| 9936 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | ||
| 9937 | out_val->data.x_type = result_type; | ||
| 9938 | return ira->codegen->builtin_types.entry_type; | ||
| 9939 | } | ||
| 9940 | |||
| 9633 | static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node, | 9941 | static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node, |
| 9634 | IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i) | 9942 | IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i) |
| 9635 | { | 9943 | { |
| ... | @@ -10114,7 +10422,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -10114,7 +10422,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 10114 | TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type; | 10422 | TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type; |
| 10115 | ir_add_alloca(ira, new_call_instruction, return_type); | 10423 | ir_add_alloca(ira, new_call_instruction, return_type); |
| 10116 | 10424 | ||
| 10117 | if (return_type->id == TypeTableEntryIdPureError || return_type->id == TypeTableEntryIdErrorUnion) { | 10425 | if (return_type->id == TypeTableEntryIdErrorSet || return_type->id == TypeTableEntryIdErrorUnion) { |
| 10118 | parent_fn_entry->calls_errorable_function = true; | 10426 | parent_fn_entry->calls_errorable_function = true; |
| 10119 | } | 10427 | } |
| 10120 | 10428 | ||
| ... | @@ -10124,7 +10432,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -10124,7 +10432,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 10124 | FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec); | 10432 | FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 10125 | assert(fn_type_id->return_type != nullptr); | 10433 | assert(fn_type_id->return_type != nullptr); |
| 10126 | assert(parent_fn_entry != nullptr); | 10434 | assert(parent_fn_entry != nullptr); |
| 10127 | if (fn_type_id->return_type->id == TypeTableEntryIdPureError || fn_type_id->return_type->id == TypeTableEntryIdErrorUnion) { | 10435 | if (fn_type_id->return_type->id == TypeTableEntryIdErrorSet || fn_type_id->return_type->id == TypeTableEntryIdErrorUnion) { |
| 10128 | parent_fn_entry->calls_errorable_function = true; | 10436 | parent_fn_entry->calls_errorable_function = true; |
| 10129 | } | 10437 | } |
| 10130 | 10438 | ||
| ... | @@ -10243,58 +10551,6 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction | ... | @@ -10243,58 +10551,6 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction |
| 10243 | } | 10551 | } |
| 10244 | } | 10552 | } |
| 10245 | 10553 | ||
| 10246 | static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { | ||
| 10247 | assert(un_op_instruction->op_id == IrUnOpError); | ||
| 10248 | IrInstruction *value = un_op_instruction->value->other; | ||
| 10249 | |||
| 10250 | TypeTableEntry *meta_type = ir_resolve_type(ira, value); | ||
| 10251 | if (type_is_invalid(meta_type)) | ||
| 10252 | return ira->codegen->builtin_types.entry_invalid; | ||
| 10253 | |||
| 10254 | |||
| 10255 | switch (meta_type->id) { | ||
| 10256 | case TypeTableEntryIdInvalid: // handled above | ||
| 10257 | zig_unreachable(); | ||
| 10258 | |||
| 10259 | case TypeTableEntryIdVoid: | ||
| 10260 | case TypeTableEntryIdBool: | ||
| 10261 | case TypeTableEntryIdInt: | ||
| 10262 | case TypeTableEntryIdFloat: | ||
| 10263 | case TypeTableEntryIdPointer: | ||
| 10264 | case TypeTableEntryIdArray: | ||
| 10265 | case TypeTableEntryIdStruct: | ||
| 10266 | case TypeTableEntryIdMaybe: | ||
| 10267 | case TypeTableEntryIdErrorUnion: | ||
| 10268 | case TypeTableEntryIdPureError: | ||
| 10269 | case TypeTableEntryIdEnum: | ||
| 10270 | case TypeTableEntryIdUnion: | ||
| 10271 | case TypeTableEntryIdFn: | ||
| 10272 | case TypeTableEntryIdBoundFn: | ||
| 10273 | { | ||
| 10274 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base); | ||
| 10275 | TypeTableEntry *result_type = get_error_type(ira->codegen, meta_type); | ||
| 10276 | out_val->data.x_type = result_type; | ||
| 10277 | return ira->codegen->builtin_types.entry_type; | ||
| 10278 | } | ||
| 10279 | case TypeTableEntryIdMetaType: | ||
| 10280 | case TypeTableEntryIdNumLitFloat: | ||
| 10281 | case TypeTableEntryIdNumLitInt: | ||
| 10282 | case TypeTableEntryIdUndefLit: | ||
| 10283 | case TypeTableEntryIdNullLit: | ||
| 10284 | case TypeTableEntryIdNamespace: | ||
| 10285 | case TypeTableEntryIdBlock: | ||
| 10286 | case TypeTableEntryIdUnreachable: | ||
| 10287 | case TypeTableEntryIdVar: | ||
| 10288 | case TypeTableEntryIdArgTuple: | ||
| 10289 | case TypeTableEntryIdOpaque: | ||
| 10290 | ir_add_error_node(ira, un_op_instruction->base.source_node, | ||
| 10291 | buf_sprintf("unable to wrap type '%s' in error type", buf_ptr(&meta_type->name))); | ||
| 10292 | return ira->codegen->builtin_types.entry_invalid; | ||
| 10293 | } | ||
| 10294 | zig_unreachable(); | ||
| 10295 | } | ||
| 10296 | |||
| 10297 | |||
| 10298 | static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { | 10554 | static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| 10299 | IrInstruction *value = un_op_instruction->value->other; | 10555 | IrInstruction *value = un_op_instruction->value->other; |
| 10300 | 10556 | ||
| ... | @@ -10350,7 +10606,7 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op | ... | @@ -10350,7 +10606,7 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op |
| 10350 | case TypeTableEntryIdNullLit: | 10606 | case TypeTableEntryIdNullLit: |
| 10351 | case TypeTableEntryIdMaybe: | 10607 | case TypeTableEntryIdMaybe: |
| 10352 | case TypeTableEntryIdErrorUnion: | 10608 | case TypeTableEntryIdErrorUnion: |
| 10353 | case TypeTableEntryIdPureError: | 10609 | case TypeTableEntryIdErrorSet: |
| 10354 | case TypeTableEntryIdEnum: | 10610 | case TypeTableEntryIdEnum: |
| 10355 | case TypeTableEntryIdUnion: | 10611 | case TypeTableEntryIdUnion: |
| 10356 | case TypeTableEntryIdFn: | 10612 | case TypeTableEntryIdFn: |
| ... | @@ -10460,8 +10716,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio | ... | @@ -10460,8 +10716,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio |
| 10460 | return ir_analyze_dereference(ira, un_op_instruction); | 10716 | return ir_analyze_dereference(ira, un_op_instruction); |
| 10461 | case IrUnOpMaybe: | 10717 | case IrUnOpMaybe: |
| 10462 | return ir_analyze_maybe(ira, un_op_instruction); | 10718 | return ir_analyze_maybe(ira, un_op_instruction); |
| 10463 | case IrUnOpError: | ||
| 10464 | return ir_analyze_unary_prefix_op_err(ira, un_op_instruction); | ||
| 10465 | } | 10719 | } |
| 10466 | zig_unreachable(); | 10720 | zig_unreachable(); |
| 10467 | } | 10721 | } |
| ... | @@ -11083,6 +11337,17 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source | ... | @@ -11083,6 +11337,17 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source |
| 11083 | zig_unreachable(); | 11337 | zig_unreachable(); |
| 11084 | } | 11338 | } |
| 11085 | 11339 | ||
| 11340 | static ErrorTableEntry *find_err_table_entry(TypeTableEntry *err_set_type, Buf *field_name) { | ||
| 11341 | assert(err_set_type->id == TypeTableEntryIdErrorSet); | ||
| 11342 | for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) { | ||
| 11343 | ErrorTableEntry *err_table_entry = err_set_type->data.error_set.errors[i]; | ||
| 11344 | if (buf_eql_buf(&err_table_entry->name, field_name)) { | ||
| 11345 | return err_table_entry; | ||
| 11346 | } | ||
| 11347 | } | ||
| 11348 | return nullptr; | ||
| 11349 | } | ||
| 11350 | |||
| 11086 | static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFieldPtr *field_ptr_instruction) { | 11351 | static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFieldPtr *field_ptr_instruction) { |
| 11087 | IrInstruction *container_ptr = field_ptr_instruction->container_ptr->other; | 11352 | IrInstruction *container_ptr = field_ptr_instruction->container_ptr->other; |
| 11088 | if (type_is_invalid(container_ptr->value.type)) | 11353 | if (type_is_invalid(container_ptr->value.type)) |
| ... | @@ -11224,23 +11489,49 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -11224,23 +11489,49 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 11224 | buf_sprintf("container '%s' has no member called '%s'", | 11489 | buf_sprintf("container '%s' has no member called '%s'", |
| 11225 | buf_ptr(&child_type->name), buf_ptr(field_name))); | 11490 | buf_ptr(&child_type->name), buf_ptr(field_name))); |
| 11226 | return ira->codegen->builtin_types.entry_invalid; | 11491 | return ira->codegen->builtin_types.entry_invalid; |
| 11227 | } else if (child_type->id == TypeTableEntryIdPureError) { | 11492 | } else if (child_type->id == TypeTableEntryIdErrorSet) { |
| 11228 | auto err_table_entry = ira->codegen->error_table.maybe_get(field_name); | 11493 | ErrorTableEntry *err_entry; |
| 11229 | if (err_table_entry) { | 11494 | TypeTableEntry *err_set_type; |
| 11230 | ConstExprValue *const_val = create_const_vals(1); | 11495 | if (child_type == ira->codegen->builtin_types.entry_global_error_set) { |
| 11231 | const_val->special = ConstValSpecialStatic; | 11496 | auto existing_entry = ira->codegen->error_table.maybe_get(field_name); |
| 11232 | const_val->type = child_type; | 11497 | if (existing_entry) { |
| 11233 | const_val->data.x_pure_err = err_table_entry->value; | 11498 | err_entry = existing_entry->value; |
| 11234 | 11499 | } else { | |
| 11235 | bool ptr_is_const = true; | 11500 | err_entry = allocate<ErrorTableEntry>(1); |
| 11236 | bool ptr_is_volatile = false; | 11501 | err_entry->decl_node = field_ptr_instruction->base.source_node; |
| 11237 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, const_val, | 11502 | buf_init_from_buf(&err_entry->name, field_name); |
| 11238 | child_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | 11503 | size_t error_value_count = ira->codegen->errors_by_index.length; |
| 11504 | assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)ira->codegen->err_tag_type->data.integral.bit_count)); | ||
| 11505 | err_entry->value = error_value_count; | ||
| 11506 | ira->codegen->errors_by_index.append(err_entry); | ||
| 11507 | ira->codegen->err_enumerators.append(ZigLLVMCreateDebugEnumerator(ira->codegen->dbuilder, | ||
| 11508 | buf_ptr(field_name), error_value_count)); | ||
| 11509 | ira->codegen->error_table.put(field_name, err_entry); | ||
| 11510 | } | ||
| 11511 | if (err_entry->set_with_only_this_in_it == nullptr) { | ||
| 11512 | err_entry->set_with_only_this_in_it = make_err_set_with_one_item(ira->codegen, | ||
| 11513 | field_ptr_instruction->base.scope, field_ptr_instruction->base.source_node, | ||
| 11514 | err_entry); | ||
| 11515 | } | ||
| 11516 | err_set_type = err_entry->set_with_only_this_in_it; | ||
| 11517 | } else { | ||
| 11518 | ErrorTableEntry *err_entry = find_err_table_entry(child_type, field_name); | ||
| 11519 | if (err_entry == nullptr) { | ||
| 11520 | ir_add_error(ira, &field_ptr_instruction->base, | ||
| 11521 | buf_sprintf("no error named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&child_type->name))); | ||
| 11522 | return ira->codegen->builtin_types.entry_invalid; | ||
| 11523 | } | ||
| 11524 | err_set_type = child_type; | ||
| 11239 | } | 11525 | } |
| 11526 | ConstExprValue *const_val = create_const_vals(1); | ||
| 11527 | const_val->special = ConstValSpecialStatic; | ||
| 11528 | const_val->type = err_set_type; | ||
| 11529 | const_val->data.x_err_set = err_entry; | ||
| 11240 | 11530 | ||
| 11241 | ir_add_error(ira, &field_ptr_instruction->base, | 11531 | bool ptr_is_const = true; |
| 11242 | buf_sprintf("use of undeclared error value '%s'", buf_ptr(field_name))); | 11532 | bool ptr_is_volatile = false; |
| 11243 | return ira->codegen->builtin_types.entry_invalid; | 11533 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, const_val, |
| 11534 | err_set_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | ||
| 11244 | } else if (child_type->id == TypeTableEntryIdInt) { | 11535 | } else if (child_type->id == TypeTableEntryIdInt) { |
| 11245 | if (buf_eql_str(field_name, "bit_count")) { | 11536 | if (buf_eql_str(field_name, "bit_count")) { |
| 11246 | bool ptr_is_const = true; | 11537 | bool ptr_is_const = true; |
| ... | @@ -11323,11 +11614,18 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -11323,11 +11614,18 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 11323 | return ira->codegen->builtin_types.entry_invalid; | 11614 | return ira->codegen->builtin_types.entry_invalid; |
| 11324 | } | 11615 | } |
| 11325 | } else if (child_type->id == TypeTableEntryIdErrorUnion) { | 11616 | } else if (child_type->id == TypeTableEntryIdErrorUnion) { |
| 11326 | if (buf_eql_str(field_name, "Child")) { | 11617 | if (buf_eql_str(field_name, "Payload")) { |
| 11618 | bool ptr_is_const = true; | ||
| 11619 | bool ptr_is_volatile = false; | ||
| 11620 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | ||
| 11621 | create_const_type(ira->codegen, child_type->data.error_union.payload_type), | ||
| 11622 | ira->codegen->builtin_types.entry_type, | ||
| 11623 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | ||
| 11624 | } else if (buf_eql_str(field_name, "ErrorSet")) { | ||
| 11327 | bool ptr_is_const = true; | 11625 | bool ptr_is_const = true; |
| 11328 | bool ptr_is_volatile = false; | 11626 | bool ptr_is_volatile = false; |
| 11329 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | 11627 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 11330 | create_const_type(ira->codegen, child_type->data.error.child_type), | 11628 | create_const_type(ira->codegen, child_type->data.error_union.err_set_type), |
| 11331 | ira->codegen->builtin_types.entry_type, | 11629 | ira->codegen->builtin_types.entry_type, |
| 11332 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); | 11630 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 11333 | } else { | 11631 | } else { |
| ... | @@ -11514,7 +11812,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi | ... | @@ -11514,7 +11812,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi |
| 11514 | case TypeTableEntryIdStruct: | 11812 | case TypeTableEntryIdStruct: |
| 11515 | case TypeTableEntryIdMaybe: | 11813 | case TypeTableEntryIdMaybe: |
| 11516 | case TypeTableEntryIdErrorUnion: | 11814 | case TypeTableEntryIdErrorUnion: |
| 11517 | case TypeTableEntryIdPureError: | 11815 | case TypeTableEntryIdErrorSet: |
| 11518 | case TypeTableEntryIdEnum: | 11816 | case TypeTableEntryIdEnum: |
| 11519 | case TypeTableEntryIdUnion: | 11817 | case TypeTableEntryIdUnion: |
| 11520 | case TypeTableEntryIdFn: | 11818 | case TypeTableEntryIdFn: |
| ... | @@ -11781,7 +12079,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, | ... | @@ -11781,7 +12079,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 11781 | case TypeTableEntryIdNumLitInt: | 12079 | case TypeTableEntryIdNumLitInt: |
| 11782 | case TypeTableEntryIdMaybe: | 12080 | case TypeTableEntryIdMaybe: |
| 11783 | case TypeTableEntryIdErrorUnion: | 12081 | case TypeTableEntryIdErrorUnion: |
| 11784 | case TypeTableEntryIdPureError: | 12082 | case TypeTableEntryIdErrorSet: |
| 11785 | case TypeTableEntryIdEnum: | 12083 | case TypeTableEntryIdEnum: |
| 11786 | case TypeTableEntryIdUnion: | 12084 | case TypeTableEntryIdUnion: |
| 11787 | case TypeTableEntryIdFn: | 12085 | case TypeTableEntryIdFn: |
| ... | @@ -11889,7 +12187,7 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira, | ... | @@ -11889,7 +12187,7 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira, |
| 11889 | case TypeTableEntryIdNumLitInt: | 12187 | case TypeTableEntryIdNumLitInt: |
| 11890 | case TypeTableEntryIdMaybe: | 12188 | case TypeTableEntryIdMaybe: |
| 11891 | case TypeTableEntryIdErrorUnion: | 12189 | case TypeTableEntryIdErrorUnion: |
| 11892 | case TypeTableEntryIdPureError: | 12190 | case TypeTableEntryIdErrorSet: |
| 11893 | case TypeTableEntryIdEnum: | 12191 | case TypeTableEntryIdEnum: |
| 11894 | case TypeTableEntryIdUnion: | 12192 | case TypeTableEntryIdUnion: |
| 11895 | case TypeTableEntryIdFn: | 12193 | case TypeTableEntryIdFn: |
| ... | @@ -11942,7 +12240,7 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, | ... | @@ -11942,7 +12240,7 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 11942 | case TypeTableEntryIdStruct: | 12240 | case TypeTableEntryIdStruct: |
| 11943 | case TypeTableEntryIdMaybe: | 12241 | case TypeTableEntryIdMaybe: |
| 11944 | case TypeTableEntryIdErrorUnion: | 12242 | case TypeTableEntryIdErrorUnion: |
| 11945 | case TypeTableEntryIdPureError: | 12243 | case TypeTableEntryIdErrorSet: |
| 11946 | case TypeTableEntryIdEnum: | 12244 | case TypeTableEntryIdEnum: |
| 11947 | case TypeTableEntryIdUnion: | 12245 | case TypeTableEntryIdUnion: |
| 11948 | case TypeTableEntryIdFn: | 12246 | case TypeTableEntryIdFn: |
| ... | @@ -12277,7 +12575,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -12277,7 +12575,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 12277 | case TypeTableEntryIdPointer: | 12575 | case TypeTableEntryIdPointer: |
| 12278 | case TypeTableEntryIdFn: | 12576 | case TypeTableEntryIdFn: |
| 12279 | case TypeTableEntryIdNamespace: | 12577 | case TypeTableEntryIdNamespace: |
| 12280 | case TypeTableEntryIdPureError: | 12578 | case TypeTableEntryIdErrorSet: |
| 12281 | if (pointee_val) { | 12579 | if (pointee_val) { |
| 12282 | ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base); | 12580 | ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base); |
| 12283 | copy_const_val(out_val, pointee_val, true); | 12581 | copy_const_val(out_val, pointee_val, true); |
| ... | @@ -12347,8 +12645,6 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -12347,8 +12645,6 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 12347 | return target_type; | 12645 | return target_type; |
| 12348 | } | 12646 | } |
| 12349 | case TypeTableEntryIdErrorUnion: | 12647 | case TypeTableEntryIdErrorUnion: |
| 12350 | // see https://github.com/andrewrk/zig/issues/632 | ||
| 12351 | zig_panic("TODO switch on error union"); | ||
| 12352 | case TypeTableEntryIdUnreachable: | 12648 | case TypeTableEntryIdUnreachable: |
| 12353 | case TypeTableEntryIdArray: | 12649 | case TypeTableEntryIdArray: |
| 12354 | case TypeTableEntryIdStruct: | 12650 | case TypeTableEntryIdStruct: |
| ... | @@ -12873,7 +13169,7 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -12873,7 +13169,7 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_ |
| 12873 | case TypeTableEntryIdNullLit: | 13169 | case TypeTableEntryIdNullLit: |
| 12874 | case TypeTableEntryIdMaybe: | 13170 | case TypeTableEntryIdMaybe: |
| 12875 | case TypeTableEntryIdErrorUnion: | 13171 | case TypeTableEntryIdErrorUnion: |
| 12876 | case TypeTableEntryIdPureError: | 13172 | case TypeTableEntryIdErrorSet: |
| 12877 | case TypeTableEntryIdUnion: | 13173 | case TypeTableEntryIdUnion: |
| 12878 | case TypeTableEntryIdFn: | 13174 | case TypeTableEntryIdFn: |
| 12879 | case TypeTableEntryIdNamespace: | 13175 | case TypeTableEntryIdNamespace: |
| ... | @@ -12961,7 +13257,7 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc | ... | @@ -12961,7 +13257,7 @@ static TypeTableEntry *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruc |
| 12961 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); | 13257 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); |
| 12962 | TypeTableEntry *str_type = get_slice_type(ira->codegen, u8_ptr_type); | 13258 | TypeTableEntry *str_type = get_slice_type(ira->codegen, u8_ptr_type); |
| 12963 | if (casted_value->value.special == ConstValSpecialStatic) { | 13259 | if (casted_value->value.special == ConstValSpecialStatic) { |
| 12964 | ErrorTableEntry *err = casted_value->value.data.x_pure_err; | 13260 | ErrorTableEntry *err = casted_value->value.data.x_err_set; |
| 12965 | if (!err->cached_error_name_val) { | 13261 | if (!err->cached_error_name_val) { |
| 12966 | ConstExprValue *array_val = create_const_str_lit(ira->codegen, &err->name); | 13262 | ConstExprValue *array_val = create_const_str_lit(ira->codegen, &err->name); |
| 12967 | err->cached_error_name_val = create_const_slice(ira->codegen, array_val, 0, buf_len(&err->name), true); | 13263 | err->cached_error_name_val = create_const_slice(ira->codegen, array_val, 0, buf_len(&err->name), true); |
| ... | @@ -14106,7 +14402,7 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc | ... | @@ -14106,7 +14402,7 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc |
| 14106 | case TypeTableEntryIdStruct: | 14402 | case TypeTableEntryIdStruct: |
| 14107 | case TypeTableEntryIdMaybe: | 14403 | case TypeTableEntryIdMaybe: |
| 14108 | case TypeTableEntryIdErrorUnion: | 14404 | case TypeTableEntryIdErrorUnion: |
| 14109 | case TypeTableEntryIdPureError: | 14405 | case TypeTableEntryIdErrorSet: |
| 14110 | case TypeTableEntryIdEnum: | 14406 | case TypeTableEntryIdEnum: |
| 14111 | case TypeTableEntryIdUnion: | 14407 | case TypeTableEntryIdUnion: |
| 14112 | case TypeTableEntryIdFn: | 14408 | case TypeTableEntryIdFn: |
| ... | @@ -14239,7 +14535,7 @@ static TypeTableEntry *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruc | ... | @@ -14239,7 +14535,7 @@ static TypeTableEntry *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruc |
| 14239 | 14535 | ||
| 14240 | ir_build_test_err_from(&ira->new_irb, &instruction->base, value); | 14536 | ir_build_test_err_from(&ira->new_irb, &instruction->base, value); |
| 14241 | return ira->codegen->builtin_types.entry_bool; | 14537 | return ira->codegen->builtin_types.entry_bool; |
| 14242 | } else if (type_entry->id == TypeTableEntryIdPureError) { | 14538 | } else if (type_entry->id == TypeTableEntryIdErrorSet) { |
| 14243 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 14539 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 14244 | out_val->data.x_bool = true; | 14540 | out_val->data.x_bool = true; |
| 14245 | return ira->codegen->builtin_types.entry_bool; | 14541 | return ira->codegen->builtin_types.entry_bool; |
| ... | @@ -14275,13 +14571,13 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, | ... | @@ -14275,13 +14571,13 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, |
| 14275 | assert(err); | 14571 | assert(err); |
| 14276 | 14572 | ||
| 14277 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 14573 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 14278 | out_val->data.x_pure_err = err; | 14574 | out_val->data.x_err_set = err; |
| 14279 | return ira->codegen->builtin_types.entry_pure_error; | 14575 | return type_entry->data.error_union.err_set_type; |
| 14280 | } | 14576 | } |
| 14281 | } | 14577 | } |
| 14282 | 14578 | ||
| 14283 | ir_build_unwrap_err_code_from(&ira->new_irb, &instruction->base, value); | 14579 | ir_build_unwrap_err_code_from(&ira->new_irb, &instruction->base, value); |
| 14284 | return ira->codegen->builtin_types.entry_pure_error; | 14580 | return type_entry->data.error_union.err_set_type; |
| 14285 | } else { | 14581 | } else { |
| 14286 | ir_add_error(ira, value, | 14582 | ir_add_error(ira, value, |
| 14287 | buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name))); | 14583 | buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name))); |
| ... | @@ -14305,10 +14601,10 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, | ... | @@ -14305,10 +14601,10 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, |
| 14305 | if (type_is_invalid(type_entry)) { | 14601 | if (type_is_invalid(type_entry)) { |
| 14306 | return ira->codegen->builtin_types.entry_invalid; | 14602 | return ira->codegen->builtin_types.entry_invalid; |
| 14307 | } else if (type_entry->id == TypeTableEntryIdErrorUnion) { | 14603 | } else if (type_entry->id == TypeTableEntryIdErrorUnion) { |
| 14308 | TypeTableEntry *child_type = type_entry->data.error.child_type; | 14604 | TypeTableEntry *payload_type = type_entry->data.error_union.payload_type; |
| 14309 | TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, child_type, | 14605 | TypeTableEntry *result_type = get_pointer_to_type_extra(ira->codegen, payload_type, |
| 14310 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | 14606 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, |
| 14311 | get_abi_alignment(ira->codegen, child_type), 0, 0); | 14607 | get_abi_alignment(ira->codegen, payload_type), 0, 0); |
| 14312 | if (instr_is_comptime(value)) { | 14608 | if (instr_is_comptime(value)) { |
| 14313 | ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); | 14609 | ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); |
| 14314 | if (!ptr_val) | 14610 | if (!ptr_val) |
| ... | @@ -14343,6 +14639,12 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc | ... | @@ -14343,6 +14639,12 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc |
| 14343 | AstNode *proto_node = instruction->base.source_node; | 14639 | AstNode *proto_node = instruction->base.source_node; |
| 14344 | assert(proto_node->type == NodeTypeFnProto); | 14640 | assert(proto_node->type == NodeTypeFnProto); |
| 14345 | 14641 | ||
| 14642 | if (proto_node->data.fn_proto.auto_err_set) { | ||
| 14643 | ir_add_error(ira, &instruction->base, | ||
| 14644 | buf_sprintf("inferring error set of return type valid only for function definitions")); | ||
| 14645 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14646 | } | ||
| 14647 | |||
| 14346 | FnTypeId fn_type_id = {0}; | 14648 | FnTypeId fn_type_id = {0}; |
| 14347 | init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length); | 14649 | init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length); |
| 14348 | 14650 | ||
| ... | @@ -14468,6 +14770,71 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira | ... | @@ -14468,6 +14770,71 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira |
| 14468 | } | 14770 | } |
| 14469 | } | 14771 | } |
| 14470 | } | 14772 | } |
| 14773 | } else if (switch_type->id == TypeTableEntryIdErrorSet) { | ||
| 14774 | FnTableEntry *infer_fn = switch_type->data.error_set.infer_fn; | ||
| 14775 | if (infer_fn != nullptr) { | ||
| 14776 | if (infer_fn->anal_state == FnAnalStateInvalid) { | ||
| 14777 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14778 | } else if (infer_fn->anal_state == FnAnalStateReady) { | ||
| 14779 | analyze_fn_body(ira->codegen, infer_fn); | ||
| 14780 | if (switch_type->data.error_set.infer_fn != nullptr) { | ||
| 14781 | assert(ira->codegen->errors.length != 0); | ||
| 14782 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14783 | } | ||
| 14784 | } else { | ||
| 14785 | ir_add_error(ira, &instruction->base, | ||
| 14786 | buf_sprintf("cannot switch on inferred error set '%s': function '%s' not fully analyzed yet", | ||
| 14787 | buf_ptr(&switch_type->name), buf_ptr(&switch_type->data.error_set.infer_fn->symbol_name))); | ||
| 14788 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14789 | } | ||
| 14790 | } | ||
| 14791 | |||
| 14792 | AstNode **field_prev_uses = allocate<AstNode *>(ira->codegen->errors_by_index.length); | ||
| 14793 | |||
| 14794 | for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { | ||
| 14795 | IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i]; | ||
| 14796 | |||
| 14797 | IrInstruction *start_value = range->start->other; | ||
| 14798 | if (type_is_invalid(start_value->value.type)) | ||
| 14799 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14800 | |||
| 14801 | IrInstruction *end_value = range->end->other; | ||
| 14802 | if (type_is_invalid(end_value->value.type)) | ||
| 14803 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14804 | |||
| 14805 | assert(start_value->value.type->id == TypeTableEntryIdErrorSet); | ||
| 14806 | uint32_t start_index = start_value->value.data.x_err_set->value; | ||
| 14807 | |||
| 14808 | assert(end_value->value.type->id == TypeTableEntryIdErrorSet); | ||
| 14809 | uint32_t end_index = end_value->value.data.x_err_set->value; | ||
| 14810 | |||
| 14811 | if (start_index != end_index) { | ||
| 14812 | ir_add_error(ira, end_value, buf_sprintf("ranges not allowed when switching on errors")); | ||
| 14813 | return ira->codegen->builtin_types.entry_invalid; | ||
| 14814 | } | ||
| 14815 | |||
| 14816 | AstNode *prev_node = field_prev_uses[start_index]; | ||
| 14817 | if (prev_node != nullptr) { | ||
| 14818 | Buf *err_name = &ira->codegen->errors_by_index.at(start_index)->name; | ||
| 14819 | ErrorMsg *msg = ir_add_error(ira, start_value, | ||
| 14820 | buf_sprintf("duplicate switch value: '%s.%s'", buf_ptr(&switch_type->name), buf_ptr(err_name))); | ||
| 14821 | add_error_note(ira->codegen, msg, prev_node, buf_sprintf("other value is here")); | ||
| 14822 | } | ||
| 14823 | field_prev_uses[start_index] = start_value->source_node; | ||
| 14824 | } | ||
| 14825 | if (!instruction->have_else_prong) { | ||
| 14826 | for (uint32_t i = 0; i < switch_type->data.error_set.err_count; i += 1) { | ||
| 14827 | ErrorTableEntry *err_entry = switch_type->data.error_set.errors[i]; | ||
| 14828 | |||
| 14829 | AstNode *prev_node = field_prev_uses[err_entry->value]; | ||
| 14830 | if (prev_node == nullptr) { | ||
| 14831 | ir_add_error(ira, &instruction->base, | ||
| 14832 | buf_sprintf("error.%s not handled in switch", buf_ptr(&err_entry->name))); | ||
| 14833 | } | ||
| 14834 | } | ||
| 14835 | } | ||
| 14836 | |||
| 14837 | free(field_prev_uses); | ||
| 14471 | } else if (switch_type->id == TypeTableEntryIdInt) { | 14838 | } else if (switch_type->id == TypeTableEntryIdInt) { |
| 14472 | RangeSet rs = {0}; | 14839 | RangeSet rs = {0}; |
| 14473 | for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { | 14840 | for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { |
| ... | @@ -14760,7 +15127,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -14760,7 +15127,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 14760 | zig_panic("TODO buf_write_value_bytes maybe type"); | 15127 | zig_panic("TODO buf_write_value_bytes maybe type"); |
| 14761 | case TypeTableEntryIdErrorUnion: | 15128 | case TypeTableEntryIdErrorUnion: |
| 14762 | zig_panic("TODO buf_write_value_bytes error union"); | 15129 | zig_panic("TODO buf_write_value_bytes error union"); |
| 14763 | case TypeTableEntryIdPureError: | 15130 | case TypeTableEntryIdErrorSet: |
| 14764 | zig_panic("TODO buf_write_value_bytes pure error type"); | 15131 | zig_panic("TODO buf_write_value_bytes pure error type"); |
| 14765 | case TypeTableEntryIdEnum: | 15132 | case TypeTableEntryIdEnum: |
| 14766 | zig_panic("TODO buf_write_value_bytes enum type"); | 15133 | zig_panic("TODO buf_write_value_bytes enum type"); |
| ... | @@ -14818,7 +15185,7 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -14818,7 +15185,7 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 14818 | zig_panic("TODO buf_read_value_bytes maybe type"); | 15185 | zig_panic("TODO buf_read_value_bytes maybe type"); |
| 14819 | case TypeTableEntryIdErrorUnion: | 15186 | case TypeTableEntryIdErrorUnion: |
| 14820 | zig_panic("TODO buf_read_value_bytes error union"); | 15187 | zig_panic("TODO buf_read_value_bytes error union"); |
| 14821 | case TypeTableEntryIdPureError: | 15188 | case TypeTableEntryIdErrorSet: |
| 14822 | zig_panic("TODO buf_read_value_bytes pure error type"); | 15189 | zig_panic("TODO buf_read_value_bytes pure error type"); |
| 14823 | case TypeTableEntryIdEnum: | 15190 | case TypeTableEntryIdEnum: |
| 14824 | zig_panic("TODO buf_read_value_bytes enum type"); | 15191 | zig_panic("TODO buf_read_value_bytes enum type"); |
| ... | @@ -15429,6 +15796,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -15429,6 +15796,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 15429 | return ir_analyze_instruction_export(ira, (IrInstructionExport *)instruction); | 15796 | return ir_analyze_instruction_export(ira, (IrInstructionExport *)instruction); |
| 15430 | case IrInstructionIdErrorReturnTrace: | 15797 | case IrInstructionIdErrorReturnTrace: |
| 15431 | return ir_analyze_instruction_error_return_trace(ira, (IrInstructionErrorReturnTrace *)instruction); | 15798 | return ir_analyze_instruction_error_return_trace(ira, (IrInstructionErrorReturnTrace *)instruction); |
| 15799 | case IrInstructionIdErrorUnion: | ||
| 15800 | return ir_analyze_instruction_error_union(ira, (IrInstructionErrorUnion *)instruction); | ||
| 15432 | } | 15801 | } |
| 15433 | zig_unreachable(); | 15802 | zig_unreachable(); |
| 15434 | } | 15803 | } |
| ... | @@ -15614,6 +15983,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -15614,6 +15983,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 15614 | case IrInstructionIdArgType: | 15983 | case IrInstructionIdArgType: |
| 15615 | case IrInstructionIdTagType: | 15984 | case IrInstructionIdTagType: |
| 15616 | case IrInstructionIdErrorReturnTrace: | 15985 | case IrInstructionIdErrorReturnTrace: |
| 15986 | case IrInstructionIdErrorUnion: | ||
| 15617 | return false; | 15987 | return false; |
| 15618 | case IrInstructionIdAsm: | 15988 | case IrInstructionIdAsm: |
| 15619 | { | 15989 | { |
src/ir_print.cpp+8-2| ... | @@ -148,8 +148,6 @@ static const char *ir_un_op_id_str(IrUnOp op_id) { | ... | @@ -148,8 +148,6 @@ static const char *ir_un_op_id_str(IrUnOp op_id) { |
| 148 | return "*"; | 148 | return "*"; |
| 149 | case IrUnOpMaybe: | 149 | case IrUnOpMaybe: |
| 150 | return "?"; | 150 | return "?"; |
| 151 | case IrUnOpError: | ||
| 152 | return "%"; | ||
| 153 | } | 151 | } |
| 154 | zig_unreachable(); | 152 | zig_unreachable(); |
| 155 | } | 153 | } |
| ... | @@ -1004,6 +1002,11 @@ static void ir_print_error_return_trace(IrPrint *irp, IrInstructionErrorReturnTr | ... | @@ -1004,6 +1002,11 @@ static void ir_print_error_return_trace(IrPrint *irp, IrInstructionErrorReturnTr |
| 1004 | fprintf(irp->f, "@errorReturnTrace()"); | 1002 | fprintf(irp->f, "@errorReturnTrace()"); |
| 1005 | } | 1003 | } |
| 1006 | 1004 | ||
| 1005 | static void ir_print_error_union(IrPrint *irp, IrInstructionErrorUnion *instruction) { | ||
| 1006 | ir_print_other_instruction(irp, instruction->err_set); | ||
| 1007 | fprintf(irp->f, "!"); | ||
| 1008 | ir_print_other_instruction(irp, instruction->payload); | ||
| 1009 | } | ||
| 1007 | 1010 | ||
| 1008 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | 1011 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1009 | ir_print_prefix(irp, instruction); | 1012 | ir_print_prefix(irp, instruction); |
| ... | @@ -1322,6 +1325,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1322,6 +1325,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1322 | case IrInstructionIdErrorReturnTrace: | 1325 | case IrInstructionIdErrorReturnTrace: |
| 1323 | ir_print_error_return_trace(irp, (IrInstructionErrorReturnTrace *)instruction); | 1326 | ir_print_error_return_trace(irp, (IrInstructionErrorReturnTrace *)instruction); |
| 1324 | break; | 1327 | break; |
| 1328 | case IrInstructionIdErrorUnion: | ||
| 1329 | ir_print_error_union(irp, (IrInstructionErrorUnion *)instruction); | ||
| 1330 | break; | ||
| 1325 | } | 1331 | } |
| 1326 | fprintf(irp->f, "\n"); | 1332 | fprintf(irp->f, "\n"); |
| 1327 | } | 1333 | } |
src/parser.cpp+50-37| ... | @@ -221,6 +221,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bo | ... | @@ -221,6 +221,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bo |
| 221 | static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory); | 221 | static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory); |
| 222 | static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory); | 222 | static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory); |
| 223 | static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index); | 223 | static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index); |
| 224 | static AstNode *ast_parse_symbol(ParseContext *pc, size_t *token_index); | ||
| 224 | 225 | ||
| 225 | static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) { | 226 | static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) { |
| 226 | if (token->id == token_id) { | 227 | if (token->id == token_id) { |
| ... | @@ -651,8 +652,9 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b | ... | @@ -651,8 +652,9 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b |
| 651 | } | 652 | } |
| 652 | 653 | ||
| 653 | /* | 654 | /* |
| 654 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." Symbol) | ContainerDecl | ("continue" option(":" Symbol)) | 655 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl |
| 655 | KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" | 656 | KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" |
| 657 | ErrorSetDecl = "error" "{" list(Symbol, ",") "}" | ||
| 656 | */ | 658 | */ |
| 657 | static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 659 | static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 658 | Token *token = &pc->tokens->at(*token_index); | 660 | Token *token = &pc->tokens->at(*token_index); |
| ... | @@ -716,9 +718,31 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo | ... | @@ -716,9 +718,31 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo |
| 716 | *token_index += 1; | 718 | *token_index += 1; |
| 717 | return node; | 719 | return node; |
| 718 | } else if (token->id == TokenIdKeywordError) { | 720 | } else if (token->id == TokenIdKeywordError) { |
| 719 | AstNode *node = ast_create_node(pc, NodeTypeErrorType, token); | 721 | Token *next_token = &pc->tokens->at(*token_index + 1); |
| 720 | *token_index += 1; | 722 | if (next_token->id == TokenIdLBrace) { |
| 721 | return node; | 723 | AstNode *node = ast_create_node(pc, NodeTypeErrorSetDecl, token); |
| 724 | *token_index += 2; | ||
| 725 | for (;;) { | ||
| 726 | Token *item_tok = &pc->tokens->at(*token_index); | ||
| 727 | if (item_tok->id == TokenIdRBrace) { | ||
| 728 | *token_index += 1; | ||
| 729 | return node; | ||
| 730 | } else if (item_tok->id == TokenIdSymbol) { | ||
| 731 | AstNode *symbol_node = ast_parse_symbol(pc, token_index); | ||
| 732 | node->data.err_set_decl.decls.append(symbol_node); | ||
| 733 | Token *opt_comma_tok = &pc->tokens->at(*token_index); | ||
| 734 | if (opt_comma_tok->id == TokenIdComma) { | ||
| 735 | *token_index += 1; | ||
| 736 | } | ||
| 737 | } else { | ||
| 738 | ast_invalid_token_error(pc, item_tok); | ||
| 739 | } | ||
| 740 | } | ||
| 741 | } else { | ||
| 742 | AstNode *node = ast_create_node(pc, NodeTypeErrorType, token); | ||
| 743 | *token_index += 1; | ||
| 744 | return node; | ||
| 745 | } | ||
| 722 | } else if (token->id == TokenIdAtSign) { | 746 | } else if (token->id == TokenIdAtSign) { |
| 723 | *token_index += 1; | 747 | *token_index += 1; |
| 724 | Token *name_tok = &pc->tokens->at(*token_index); | 748 | Token *name_tok = &pc->tokens->at(*token_index); |
| ... | @@ -950,7 +974,6 @@ static PrefixOp tok_to_prefix_op(Token *token) { | ... | @@ -950,7 +974,6 @@ static PrefixOp tok_to_prefix_op(Token *token) { |
| 950 | case TokenIdTilde: return PrefixOpBinNot; | 974 | case TokenIdTilde: return PrefixOpBinNot; |
| 951 | case TokenIdStar: return PrefixOpDereference; | 975 | case TokenIdStar: return PrefixOpDereference; |
| 952 | case TokenIdMaybe: return PrefixOpMaybe; | 976 | case TokenIdMaybe: return PrefixOpMaybe; |
| 953 | case TokenIdPercent: return PrefixOpError; | ||
| 954 | case TokenIdDoubleQuestion: return PrefixOpUnwrapMaybe; | 977 | case TokenIdDoubleQuestion: return PrefixOpUnwrapMaybe; |
| 955 | case TokenIdStarStar: return PrefixOpDereference; | 978 | case TokenIdStarStar: return PrefixOpDereference; |
| 956 | default: return PrefixOpInvalid; | 979 | default: return PrefixOpInvalid; |
| ... | @@ -998,7 +1021,7 @@ static AstNode *ast_parse_addr_of(ParseContext *pc, size_t *token_index) { | ... | @@ -998,7 +1021,7 @@ static AstNode *ast_parse_addr_of(ParseContext *pc, size_t *token_index) { |
| 998 | 1021 | ||
| 999 | /* | 1022 | /* |
| 1000 | PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression | 1023 | PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression |
| 1001 | PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%" | "try" | 1024 | PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" |
| 1002 | */ | 1025 | */ |
| 1003 | static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 1026 | static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 1004 | Token *token = &pc->tokens->at(*token_index); | 1027 | Token *token = &pc->tokens->at(*token_index); |
| ... | @@ -1043,12 +1066,13 @@ static BinOpType tok_to_mult_op(Token *token) { | ... | @@ -1043,12 +1066,13 @@ static BinOpType tok_to_mult_op(Token *token) { |
| 1043 | case TokenIdStarStar: return BinOpTypeArrayMult; | 1066 | case TokenIdStarStar: return BinOpTypeArrayMult; |
| 1044 | case TokenIdSlash: return BinOpTypeDiv; | 1067 | case TokenIdSlash: return BinOpTypeDiv; |
| 1045 | case TokenIdPercent: return BinOpTypeMod; | 1068 | case TokenIdPercent: return BinOpTypeMod; |
| 1069 | case TokenIdBang: return BinOpTypeErrorUnion; | ||
| 1046 | default: return BinOpTypeInvalid; | 1070 | default: return BinOpTypeInvalid; |
| 1047 | } | 1071 | } |
| 1048 | } | 1072 | } |
| 1049 | 1073 | ||
| 1050 | /* | 1074 | /* |
| 1051 | MultiplyOperator = "*" | "/" | "%" | "**" | "*%" | 1075 | MultiplyOperator = "!" | "*" | "/" | "%" | "**" | "*%" |
| 1052 | */ | 1076 | */ |
| 1053 | static BinOpType ast_parse_mult_op(ParseContext *pc, size_t *token_index, bool mandatory) { | 1077 | static BinOpType ast_parse_mult_op(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 1054 | Token *token = &pc->tokens->at(*token_index); | 1078 | Token *token = &pc->tokens->at(*token_index); |
| ... | @@ -2240,7 +2264,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand | ... | @@ -2240,7 +2264,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand |
| 2240 | } | 2264 | } |
| 2241 | 2265 | ||
| 2242 | /* | 2266 | /* |
| 2243 | FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") TypeExpr | 2267 | FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr |
| 2244 | */ | 2268 | */ |
| 2245 | static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { | 2269 | static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { |
| 2246 | Token *first_token = &pc->tokens->at(*token_index); | 2270 | Token *first_token = &pc->tokens->at(*token_index); |
| ... | @@ -2315,6 +2339,21 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m | ... | @@ -2315,6 +2339,21 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2315 | ast_eat_token(pc, token_index, TokenIdRParen); | 2339 | ast_eat_token(pc, token_index, TokenIdRParen); |
| 2316 | next_token = &pc->tokens->at(*token_index); | 2340 | next_token = &pc->tokens->at(*token_index); |
| 2317 | } | 2341 | } |
| 2342 | if (next_token->id == TokenIdKeywordError) { | ||
| 2343 | Token *maybe_lbrace_tok = &pc->tokens->at(*token_index + 1); | ||
| 2344 | if (maybe_lbrace_tok->id == TokenIdLBrace) { | ||
| 2345 | *token_index += 1; | ||
| 2346 | node->data.fn_proto.return_type = ast_create_node(pc, NodeTypeErrorType, next_token); | ||
| 2347 | return node; | ||
| 2348 | } | ||
| 2349 | |||
| 2350 | return node; | ||
| 2351 | } | ||
| 2352 | if (next_token->id == TokenIdBang) { | ||
| 2353 | *token_index += 1; | ||
| 2354 | node->data.fn_proto.auto_err_set = true; | ||
| 2355 | next_token = &pc->tokens->at(*token_index); | ||
| 2356 | } | ||
| 2318 | node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, true); | 2357 | node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, true); |
| 2319 | 2358 | ||
| 2320 | return node; | 2359 | return node; |
| ... | @@ -2559,26 +2598,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, | ... | @@ -2559,26 +2598,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, |
| 2559 | return node; | 2598 | return node; |
| 2560 | } | 2599 | } |
| 2561 | 2600 | ||
| 2562 | /* | ||
| 2563 | ErrorValueDecl : "error" "Symbol" ";" | ||
| 2564 | */ | ||
| 2565 | static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index) { | ||
| 2566 | Token *first_token = &pc->tokens->at(*token_index); | ||
| 2567 | |||
| 2568 | if (first_token->id != TokenIdKeywordError) { | ||
| 2569 | return nullptr; | ||
| 2570 | } | ||
| 2571 | *token_index += 1; | ||
| 2572 | |||
| 2573 | Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol); | ||
| 2574 | ast_eat_token(pc, token_index, TokenIdSemicolon); | ||
| 2575 | |||
| 2576 | AstNode *node = ast_create_node(pc, NodeTypeErrorValueDecl, first_token); | ||
| 2577 | node->data.error_value_decl.name = token_buf(name_tok); | ||
| 2578 | |||
| 2579 | return node; | ||
| 2580 | } | ||
| 2581 | |||
| 2582 | /* | 2601 | /* |
| 2583 | TestDecl = "test" String Block | 2602 | TestDecl = "test" String Block |
| 2584 | */ | 2603 | */ |
| ... | @@ -2611,12 +2630,6 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig | ... | @@ -2611,12 +2630,6 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig |
| 2611 | continue; | 2630 | continue; |
| 2612 | } | 2631 | } |
| 2613 | 2632 | ||
| 2614 | AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index); | ||
| 2615 | if (error_value_node) { | ||
| 2616 | top_level_decls->append(error_value_node); | ||
| 2617 | continue; | ||
| 2618 | } | ||
| 2619 | |||
| 2620 | AstNode *test_decl_node = ast_parse_test_decl_node(pc, token_index); | 2633 | AstNode *test_decl_node = ast_parse_test_decl_node(pc, token_index); |
| 2621 | if (test_decl_node) { | 2634 | if (test_decl_node) { |
| 2622 | top_level_decls->append(test_decl_node); | 2635 | top_level_decls->append(test_decl_node); |
| ... | @@ -2744,9 +2757,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont | ... | @@ -2744,9 +2757,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2744 | visit_field(&node->data.variable_declaration.align_expr, visit, context); | 2757 | visit_field(&node->data.variable_declaration.align_expr, visit, context); |
| 2745 | visit_field(&node->data.variable_declaration.section_expr, visit, context); | 2758 | visit_field(&node->data.variable_declaration.section_expr, visit, context); |
| 2746 | break; | 2759 | break; |
| 2747 | case NodeTypeErrorValueDecl: | ||
| 2748 | // none | ||
| 2749 | break; | ||
| 2750 | case NodeTypeTestDecl: | 2760 | case NodeTypeTestDecl: |
| 2751 | visit_field(&node->data.test_decl.body, visit, context); | 2761 | visit_field(&node->data.test_decl.body, visit, context); |
| 2752 | break; | 2762 | break; |
| ... | @@ -2899,5 +2909,8 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont | ... | @@ -2899,5 +2909,8 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2899 | visit_field(&node->data.addr_of_expr.align_expr, visit, context); | 2909 | visit_field(&node->data.addr_of_expr.align_expr, visit, context); |
| 2900 | visit_field(&node->data.addr_of_expr.op_expr, visit, context); | 2910 | visit_field(&node->data.addr_of_expr.op_expr, visit, context); |
| 2901 | break; | 2911 | break; |
| 2912 | case NodeTypeErrorSetDecl: | ||
| 2913 | visit_node_list(&node->data.err_set_decl.decls, visit, context); | ||
| 2914 | break; | ||
| 2902 | } | 2915 | } |
| 2903 | } | 2916 | } |
src/zig_llvm.cpp+4| ... | @@ -437,6 +437,10 @@ unsigned ZigLLVMTag_DW_structure_type(void) { | ... | @@ -437,6 +437,10 @@ unsigned ZigLLVMTag_DW_structure_type(void) { |
| 437 | return dwarf::DW_TAG_structure_type; | 437 | return dwarf::DW_TAG_structure_type; |
| 438 | } | 438 | } |
| 439 | 439 | ||
| 440 | unsigned ZigLLVMTag_DW_enumeration_type(void) { | ||
| 441 | return dwarf::DW_TAG_enumeration_type; | ||
| 442 | } | ||
| 443 | |||
| 440 | unsigned ZigLLVMTag_DW_union_type(void) { | 444 | unsigned ZigLLVMTag_DW_union_type(void) { |
| 441 | return dwarf::DW_TAG_union_type; | 445 | return dwarf::DW_TAG_union_type; |
| 442 | } | 446 | } |
src/zig_llvm.h+1| ... | @@ -133,6 +133,7 @@ ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_signed_char(void); | ... | @@ -133,6 +133,7 @@ ZIG_EXTERN_C unsigned ZigLLVMEncoding_DW_ATE_signed_char(void); |
| 133 | ZIG_EXTERN_C unsigned ZigLLVMLang_DW_LANG_C99(void); | 133 | ZIG_EXTERN_C unsigned ZigLLVMLang_DW_LANG_C99(void); |
| 134 | ZIG_EXTERN_C unsigned ZigLLVMTag_DW_variable(void); | 134 | ZIG_EXTERN_C unsigned ZigLLVMTag_DW_variable(void); |
| 135 | ZIG_EXTERN_C unsigned ZigLLVMTag_DW_structure_type(void); | 135 | ZIG_EXTERN_C unsigned ZigLLVMTag_DW_structure_type(void); |
| 136 | ZIG_EXTERN_C unsigned ZigLLVMTag_DW_enumeration_type(void); | ||
| 136 | ZIG_EXTERN_C unsigned ZigLLVMTag_DW_union_type(void); | 137 | ZIG_EXTERN_C unsigned ZigLLVMTag_DW_union_type(void); |
| 137 | 138 | ||
| 138 | ZIG_EXTERN_C struct ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved); | 139 | ZIG_EXTERN_C struct ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved); |
std/debug/index.zig+34-46| ... | @@ -10,15 +10,6 @@ const builtin = @import("builtin"); | ... | @@ -10,15 +10,6 @@ const builtin = @import("builtin"); |
| 10 | 10 | ||
| 11 | pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator; | 11 | pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator; |
| 12 | 12 | ||
| 13 | error MissingDebugInfo; | ||
| 14 | error InvalidDebugInfo; | ||
| 15 | error UnsupportedDebugInfo; | ||
| 16 | error UnknownObjectFormat; | ||
| 17 | error TodoSupportCoffDebugInfo; | ||
| 18 | error TodoSupportMachoDebugInfo; | ||
| 19 | error TodoSupportCOFFDebugInfo; | ||
| 20 | |||
| 21 | |||
| 22 | /// Tries to write to stderr, unbuffered, and ignores any error returned. | 13 | /// Tries to write to stderr, unbuffered, and ignores any error returned. |
| 23 | /// Does not append a newline. | 14 | /// Does not append a newline. |
| 24 | /// TODO atomic/multithread support | 15 | /// TODO atomic/multithread support |
| ... | @@ -29,7 +20,7 @@ pub fn warn(comptime fmt: []const u8, args: ...) void { | ... | @@ -29,7 +20,7 @@ pub fn warn(comptime fmt: []const u8, args: ...) void { |
| 29 | const stderr = getStderrStream() catch return; | 20 | const stderr = getStderrStream() catch return; |
| 30 | stderr.print(fmt, args) catch return; | 21 | stderr.print(fmt, args) catch return; |
| 31 | } | 22 | } |
| 32 | fn getStderrStream() %&io.OutStream { | 23 | fn getStderrStream() !&io.OutStream { |
| 33 | if (stderr_stream) |st| { | 24 | if (stderr_stream) |st| { |
| 34 | return st; | 25 | return st; |
| 35 | } else { | 26 | } else { |
| ... | @@ -42,7 +33,7 @@ fn getStderrStream() %&io.OutStream { | ... | @@ -42,7 +33,7 @@ fn getStderrStream() %&io.OutStream { |
| 42 | } | 33 | } |
| 43 | 34 | ||
| 44 | var self_debug_info: ?&ElfStackTrace = null; | 35 | var self_debug_info: ?&ElfStackTrace = null; |
| 45 | pub fn getSelfDebugInfo() %&ElfStackTrace { | 36 | pub fn getSelfDebugInfo() !&ElfStackTrace { |
| 46 | if (self_debug_info) |info| { | 37 | if (self_debug_info) |info| { |
| 47 | return info; | 38 | return info; |
| 48 | } else { | 39 | } else { |
| ... | @@ -149,11 +140,8 @@ const WHITE = "\x1b[37;1m"; | ... | @@ -149,11 +140,8 @@ const WHITE = "\x1b[37;1m"; |
| 149 | const DIM = "\x1b[2m"; | 140 | const DIM = "\x1b[2m"; |
| 150 | const RESET = "\x1b[0m"; | 141 | const RESET = "\x1b[0m"; |
| 151 | 142 | ||
| 152 | error PathNotFound; | ||
| 153 | error InvalidDebugInfo; | ||
| 154 | |||
| 155 | pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.OutStream, allocator: &mem.Allocator, | 143 | pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.OutStream, allocator: &mem.Allocator, |
| 156 | debug_info: &ElfStackTrace, tty_color: bool) %void | 144 | debug_info: &ElfStackTrace, tty_color: bool) !void |
| 157 | { | 145 | { |
| 158 | var frame_index: usize = undefined; | 146 | var frame_index: usize = undefined; |
| 159 | var frames_left: usize = undefined; | 147 | var frames_left: usize = undefined; |
| ... | @@ -175,7 +163,7 @@ pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.O | ... | @@ -175,7 +163,7 @@ pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.O |
| 175 | } | 163 | } |
| 176 | 164 | ||
| 177 | pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, | 165 | pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, |
| 178 | debug_info: &ElfStackTrace, tty_color: bool, ignore_frame_count: usize) %void | 166 | debug_info: &ElfStackTrace, tty_color: bool, ignore_frame_count: usize) !void |
| 179 | { | 167 | { |
| 180 | var ignored_count: usize = 0; | 168 | var ignored_count: usize = 0; |
| 181 | 169 | ||
| ... | @@ -191,7 +179,7 @@ pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocat | ... | @@ -191,7 +179,7 @@ pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocat |
| 191 | } | 179 | } |
| 192 | } | 180 | } |
| 193 | 181 | ||
| 194 | fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, address: usize) %void { | 182 | fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, address: usize) !void { |
| 195 | if (builtin.os == builtin.Os.windows) { | 183 | if (builtin.os == builtin.Os.windows) { |
| 196 | return error.UnsupportedDebugInfo; | 184 | return error.UnsupportedDebugInfo; |
| 197 | } | 185 | } |
| ... | @@ -232,7 +220,7 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, a | ... | @@ -232,7 +220,7 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, a |
| 232 | } | 220 | } |
| 233 | } | 221 | } |
| 234 | 222 | ||
| 235 | pub fn openSelfDebugInfo(allocator: &mem.Allocator) %&ElfStackTrace { | 223 | pub fn openSelfDebugInfo(allocator: &mem.Allocator) !&ElfStackTrace { |
| 236 | switch (builtin.object_format) { | 224 | switch (builtin.object_format) { |
| 237 | builtin.ObjectFormat.elf => { | 225 | builtin.ObjectFormat.elf => { |
| 238 | const st = try allocator.create(ElfStackTrace); | 226 | const st = try allocator.create(ElfStackTrace); |
| ... | @@ -276,7 +264,7 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) %&ElfStackTrace { | ... | @@ -276,7 +264,7 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) %&ElfStackTrace { |
| 276 | } | 264 | } |
| 277 | } | 265 | } |
| 278 | 266 | ||
| 279 | fn printLineFromFile(allocator: &mem.Allocator, out_stream: &io.OutStream, line_info: &const LineInfo) %void { | 267 | fn printLineFromFile(allocator: &mem.Allocator, out_stream: &io.OutStream, line_info: &const LineInfo) !void { |
| 280 | var f = try io.File.openRead(line_info.file_name, allocator); | 268 | var f = try io.File.openRead(line_info.file_name, allocator); |
| 281 | defer f.close(); | 269 | defer f.close(); |
| 282 | // TODO fstat and make sure that the file has the correct size | 270 | // TODO fstat and make sure that the file has the correct size |
| ... | @@ -324,7 +312,7 @@ pub const ElfStackTrace = struct { | ... | @@ -324,7 +312,7 @@ pub const ElfStackTrace = struct { |
| 324 | return self.abbrev_table_list.allocator; | 312 | return self.abbrev_table_list.allocator; |
| 325 | } | 313 | } |
| 326 | 314 | ||
| 327 | pub fn readString(self: &ElfStackTrace) %[]u8 { | 315 | pub fn readString(self: &ElfStackTrace) ![]u8 { |
| 328 | var in_file_stream = io.FileInStream.init(&self.self_exe_file); | 316 | var in_file_stream = io.FileInStream.init(&self.self_exe_file); |
| 329 | const in_stream = &in_file_stream.stream; | 317 | const in_stream = &in_file_stream.stream; |
| 330 | return readStringRaw(self.allocator(), in_stream); | 318 | return readStringRaw(self.allocator(), in_stream); |
| ... | @@ -387,7 +375,7 @@ const Constant = struct { | ... | @@ -387,7 +375,7 @@ const Constant = struct { |
| 387 | payload: []u8, | 375 | payload: []u8, |
| 388 | signed: bool, | 376 | signed: bool, |
| 389 | 377 | ||
| 390 | fn asUnsignedLe(self: &const Constant) %u64 { | 378 | fn asUnsignedLe(self: &const Constant) !u64 { |
| 391 | if (self.payload.len > @sizeOf(u64)) | 379 | if (self.payload.len > @sizeOf(u64)) |
| 392 | return error.InvalidDebugInfo; | 380 | return error.InvalidDebugInfo; |
| 393 | if (self.signed) | 381 | if (self.signed) |
| ... | @@ -414,7 +402,7 @@ const Die = struct { | ... | @@ -414,7 +402,7 @@ const Die = struct { |
| 414 | return null; | 402 | return null; |
| 415 | } | 403 | } |
| 416 | 404 | ||
| 417 | fn getAttrAddr(self: &const Die, id: u64) %u64 { | 405 | fn getAttrAddr(self: &const Die, id: u64) !u64 { |
| 418 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; | 406 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 419 | return switch (*form_value) { | 407 | return switch (*form_value) { |
| 420 | FormValue.Address => |value| value, | 408 | FormValue.Address => |value| value, |
| ... | @@ -422,7 +410,7 @@ const Die = struct { | ... | @@ -422,7 +410,7 @@ const Die = struct { |
| 422 | }; | 410 | }; |
| 423 | } | 411 | } |
| 424 | 412 | ||
| 425 | fn getAttrSecOffset(self: &const Die, id: u64) %u64 { | 413 | fn getAttrSecOffset(self: &const Die, id: u64) !u64 { |
| 426 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; | 414 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 427 | return switch (*form_value) { | 415 | return switch (*form_value) { |
| 428 | FormValue.Const => |value| value.asUnsignedLe(), | 416 | FormValue.Const => |value| value.asUnsignedLe(), |
| ... | @@ -431,7 +419,7 @@ const Die = struct { | ... | @@ -431,7 +419,7 @@ const Die = struct { |
| 431 | }; | 419 | }; |
| 432 | } | 420 | } |
| 433 | 421 | ||
| 434 | fn getAttrUnsignedLe(self: &const Die, id: u64) %u64 { | 422 | fn getAttrUnsignedLe(self: &const Die, id: u64) !u64 { |
| 435 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; | 423 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 436 | return switch (*form_value) { | 424 | return switch (*form_value) { |
| 437 | FormValue.Const => |value| value.asUnsignedLe(), | 425 | FormValue.Const => |value| value.asUnsignedLe(), |
| ... | @@ -439,7 +427,7 @@ const Die = struct { | ... | @@ -439,7 +427,7 @@ const Die = struct { |
| 439 | }; | 427 | }; |
| 440 | } | 428 | } |
| 441 | 429 | ||
| 442 | fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) %[]u8 { | 430 | fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) ![]u8 { |
| 443 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; | 431 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 444 | return switch (*form_value) { | 432 | return switch (*form_value) { |
| 445 | FormValue.String => |value| value, | 433 | FormValue.String => |value| value, |
| ... | @@ -512,7 +500,7 @@ const LineNumberProgram = struct { | ... | @@ -512,7 +500,7 @@ const LineNumberProgram = struct { |
| 512 | }; | 500 | }; |
| 513 | } | 501 | } |
| 514 | 502 | ||
| 515 | pub fn checkLineMatch(self: &LineNumberProgram) %?LineInfo { | 503 | pub fn checkLineMatch(self: &LineNumberProgram) !?LineInfo { |
| 516 | if (self.target_address >= self.prev_address and self.target_address < self.address) { | 504 | if (self.target_address >= self.prev_address and self.target_address < self.address) { |
| 517 | const file_entry = if (self.prev_file == 0) { | 505 | const file_entry = if (self.prev_file == 0) { |
| 518 | return error.MissingDebugInfo; | 506 | return error.MissingDebugInfo; |
| ... | @@ -544,7 +532,7 @@ const LineNumberProgram = struct { | ... | @@ -544,7 +532,7 @@ const LineNumberProgram = struct { |
| 544 | } | 532 | } |
| 545 | }; | 533 | }; |
| 546 | 534 | ||
| 547 | fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) %[]u8 { | 535 | fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) ![]u8 { |
| 548 | var buf = ArrayList(u8).init(allocator); | 536 | var buf = ArrayList(u8).init(allocator); |
| 549 | while (true) { | 537 | while (true) { |
| 550 | const byte = try in_stream.readByte(); | 538 | const byte = try in_stream.readByte(); |
| ... | @@ -555,58 +543,58 @@ fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) %[]u8 { | ... | @@ -555,58 +543,58 @@ fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) %[]u8 { |
| 555 | return buf.toSlice(); | 543 | return buf.toSlice(); |
| 556 | } | 544 | } |
| 557 | 545 | ||
| 558 | fn getString(st: &ElfStackTrace, offset: u64) %[]u8 { | 546 | fn getString(st: &ElfStackTrace, offset: u64) ![]u8 { |
| 559 | const pos = st.debug_str.offset + offset; | 547 | const pos = st.debug_str.offset + offset; |
| 560 | try st.self_exe_file.seekTo(pos); | 548 | try st.self_exe_file.seekTo(pos); |
| 561 | return st.readString(); | 549 | return st.readString(); |
| 562 | } | 550 | } |
| 563 | 551 | ||
| 564 | fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %[]u8 { | 552 | fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) ![]u8 { |
| 565 | const buf = try global_allocator.alloc(u8, size); | 553 | const buf = try global_allocator.alloc(u8, size); |
| 566 | errdefer global_allocator.free(buf); | 554 | errdefer global_allocator.free(buf); |
| 567 | if ((try in_stream.read(buf)) < size) return error.EndOfFile; | 555 | if ((try in_stream.read(buf)) < size) return error.EndOfFile; |
| 568 | return buf; | 556 | return buf; |
| 569 | } | 557 | } |
| 570 | 558 | ||
| 571 | fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %FormValue { | 559 | fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) !FormValue { |
| 572 | const buf = try readAllocBytes(allocator, in_stream, size); | 560 | const buf = try readAllocBytes(allocator, in_stream, size); |
| 573 | return FormValue { .Block = buf }; | 561 | return FormValue { .Block = buf }; |
| 574 | } | 562 | } |
| 575 | 563 | ||
| 576 | fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %FormValue { | 564 | fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) !FormValue { |
| 577 | const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size); | 565 | const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size); |
| 578 | return parseFormValueBlockLen(allocator, in_stream, block_len); | 566 | return parseFormValueBlockLen(allocator, in_stream, block_len); |
| 579 | } | 567 | } |
| 580 | 568 | ||
| 581 | fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) %FormValue { | 569 | fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) !FormValue { |
| 582 | return FormValue { .Const = Constant { | 570 | return FormValue { .Const = Constant { |
| 583 | .signed = signed, | 571 | .signed = signed, |
| 584 | .payload = try readAllocBytes(allocator, in_stream, size), | 572 | .payload = try readAllocBytes(allocator, in_stream, size), |
| 585 | }}; | 573 | }}; |
| 586 | } | 574 | } |
| 587 | 575 | ||
| 588 | fn parseFormValueDwarfOffsetSize(in_stream: &io.InStream, is_64: bool) %u64 { | 576 | fn parseFormValueDwarfOffsetSize(in_stream: &io.InStream, is_64: bool) !u64 { |
| 589 | return if (is_64) try in_stream.readIntLe(u64) | 577 | return if (is_64) try in_stream.readIntLe(u64) |
| 590 | else u64(try in_stream.readIntLe(u32)) ; | 578 | else u64(try in_stream.readIntLe(u32)) ; |
| 591 | } | 579 | } |
| 592 | 580 | ||
| 593 | fn parseFormValueTargetAddrSize(in_stream: &io.InStream) %u64 { | 581 | fn parseFormValueTargetAddrSize(in_stream: &io.InStream) !u64 { |
| 594 | return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) | 582 | return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) |
| 595 | else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) | 583 | else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) |
| 596 | else unreachable; | 584 | else unreachable; |
| 597 | } | 585 | } |
| 598 | 586 | ||
| 599 | fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %FormValue { | 587 | fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) !FormValue { |
| 600 | const buf = try readAllocBytes(allocator, in_stream, size); | 588 | const buf = try readAllocBytes(allocator, in_stream, size); |
| 601 | return FormValue { .Ref = buf }; | 589 | return FormValue { .Ref = buf }; |
| 602 | } | 590 | } |
| 603 | 591 | ||
| 604 | fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) %FormValue { | 592 | fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) !FormValue { |
| 605 | const block_len = try in_stream.readIntLe(T); | 593 | const block_len = try in_stream.readIntLe(T); |
| 606 | return parseFormValueRefLen(allocator, in_stream, block_len); | 594 | return parseFormValueRefLen(allocator, in_stream, block_len); |
| 607 | } | 595 | } |
| 608 | 596 | ||
| 609 | fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) %FormValue { | 597 | fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) !FormValue { |
| 610 | return switch (form_id) { | 598 | return switch (form_id) { |
| 611 | DW.FORM_addr => FormValue { .Address = try parseFormValueTargetAddrSize(in_stream) }, | 599 | DW.FORM_addr => FormValue { .Address = try parseFormValueTargetAddrSize(in_stream) }, |
| 612 | DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), | 600 | DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), |
| ... | @@ -656,7 +644,7 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u | ... | @@ -656,7 +644,7 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u |
| 656 | }; | 644 | }; |
| 657 | } | 645 | } |
| 658 | 646 | ||
| 659 | fn parseAbbrevTable(st: &ElfStackTrace) %AbbrevTable { | 647 | fn parseAbbrevTable(st: &ElfStackTrace) !AbbrevTable { |
| 660 | const in_file = &st.self_exe_file; | 648 | const in_file = &st.self_exe_file; |
| 661 | var in_file_stream = io.FileInStream.init(in_file); | 649 | var in_file_stream = io.FileInStream.init(in_file); |
| 662 | const in_stream = &in_file_stream.stream; | 650 | const in_stream = &in_file_stream.stream; |
| ... | @@ -688,7 +676,7 @@ fn parseAbbrevTable(st: &ElfStackTrace) %AbbrevTable { | ... | @@ -688,7 +676,7 @@ fn parseAbbrevTable(st: &ElfStackTrace) %AbbrevTable { |
| 688 | 676 | ||
| 689 | /// Gets an already existing AbbrevTable given the abbrev_offset, or if not found, | 677 | /// Gets an already existing AbbrevTable given the abbrev_offset, or if not found, |
| 690 | /// seeks in the stream and parses it. | 678 | /// seeks in the stream and parses it. |
| 691 | fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) %&const AbbrevTable { | 679 | fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) !&const AbbrevTable { |
| 692 | for (st.abbrev_table_list.toSlice()) |*header| { | 680 | for (st.abbrev_table_list.toSlice()) |*header| { |
| 693 | if (header.offset == abbrev_offset) { | 681 | if (header.offset == abbrev_offset) { |
| 694 | return &header.table; | 682 | return &header.table; |
| ... | @@ -710,7 +698,7 @@ fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) ?&con | ... | @@ -710,7 +698,7 @@ fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) ?&con |
| 710 | return null; | 698 | return null; |
| 711 | } | 699 | } |
| 712 | 700 | ||
| 713 | fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) %Die { | 701 | fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) !Die { |
| 714 | const in_file = &st.self_exe_file; | 702 | const in_file = &st.self_exe_file; |
| 715 | var in_file_stream = io.FileInStream.init(in_file); | 703 | var in_file_stream = io.FileInStream.init(in_file); |
| 716 | const in_stream = &in_file_stream.stream; | 704 | const in_stream = &in_file_stream.stream; |
| ... | @@ -732,7 +720,7 @@ fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) % | ... | @@ -732,7 +720,7 @@ fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) % |
| 732 | return result; | 720 | return result; |
| 733 | } | 721 | } |
| 734 | 722 | ||
| 735 | fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, target_address: usize) %LineInfo { | 723 | fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, target_address: usize) !LineInfo { |
| 736 | const compile_unit_cwd = try compile_unit.die.getAttrString(st, DW.AT_comp_dir); | 724 | const compile_unit_cwd = try compile_unit.die.getAttrString(st, DW.AT_comp_dir); |
| 737 | 725 | ||
| 738 | const in_file = &st.self_exe_file; | 726 | const in_file = &st.self_exe_file; |
| ... | @@ -910,7 +898,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe | ... | @@ -910,7 +898,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe |
| 910 | return error.MissingDebugInfo; | 898 | return error.MissingDebugInfo; |
| 911 | } | 899 | } |
| 912 | 900 | ||
| 913 | fn scanAllCompileUnits(st: &ElfStackTrace) %void { | 901 | fn scanAllCompileUnits(st: &ElfStackTrace) !void { |
| 914 | const debug_info_end = st.debug_info.offset + st.debug_info.size; | 902 | const debug_info_end = st.debug_info.offset + st.debug_info.size; |
| 915 | var this_unit_offset = st.debug_info.offset; | 903 | var this_unit_offset = st.debug_info.offset; |
| 916 | var cu_index: usize = 0; | 904 | var cu_index: usize = 0; |
| ... | @@ -986,7 +974,7 @@ fn scanAllCompileUnits(st: &ElfStackTrace) %void { | ... | @@ -986,7 +974,7 @@ fn scanAllCompileUnits(st: &ElfStackTrace) %void { |
| 986 | } | 974 | } |
| 987 | } | 975 | } |
| 988 | 976 | ||
| 989 | fn findCompileUnit(st: &ElfStackTrace, target_address: u64) %&const CompileUnit { | 977 | fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit { |
| 990 | var in_file_stream = io.FileInStream.init(&st.self_exe_file); | 978 | var in_file_stream = io.FileInStream.init(&st.self_exe_file); |
| 991 | const in_stream = &in_file_stream.stream; | 979 | const in_stream = &in_file_stream.stream; |
| 992 | for (st.compile_unit_list.toSlice()) |*compile_unit| { | 980 | for (st.compile_unit_list.toSlice()) |*compile_unit| { |
| ... | @@ -1022,7 +1010,7 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) %&const CompileUnit | ... | @@ -1022,7 +1010,7 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) %&const CompileUnit |
| 1022 | return error.MissingDebugInfo; | 1010 | return error.MissingDebugInfo; |
| 1023 | } | 1011 | } |
| 1024 | 1012 | ||
| 1025 | fn readInitialLength(in_stream: &io.InStream, is_64: &bool) %u64 { | 1013 | fn readInitialLength(in_stream: &io.InStream, is_64: &bool) !u64 { |
| 1026 | const first_32_bits = try in_stream.readIntLe(u32); | 1014 | const first_32_bits = try in_stream.readIntLe(u32); |
| 1027 | *is_64 = (first_32_bits == 0xffffffff); | 1015 | *is_64 = (first_32_bits == 0xffffffff); |
| 1028 | if (*is_64) { | 1016 | if (*is_64) { |
| ... | @@ -1033,7 +1021,7 @@ fn readInitialLength(in_stream: &io.InStream, is_64: &bool) %u64 { | ... | @@ -1033,7 +1021,7 @@ fn readInitialLength(in_stream: &io.InStream, is_64: &bool) %u64 { |
| 1033 | } | 1021 | } |
| 1034 | } | 1022 | } |
| 1035 | 1023 | ||
| 1036 | fn readULeb128(in_stream: &io.InStream) %u64 { | 1024 | fn readULeb128(in_stream: &io.InStream) !u64 { |
| 1037 | var result: u64 = 0; | 1025 | var result: u64 = 0; |
| 1038 | var shift: usize = 0; | 1026 | var shift: usize = 0; |
| 1039 | 1027 | ||
| ... | @@ -1054,7 +1042,7 @@ fn readULeb128(in_stream: &io.InStream) %u64 { | ... | @@ -1054,7 +1042,7 @@ fn readULeb128(in_stream: &io.InStream) %u64 { |
| 1054 | } | 1042 | } |
| 1055 | } | 1043 | } |
| 1056 | 1044 | ||
| 1057 | fn readILeb128(in_stream: &io.InStream) %i64 { | 1045 | fn readILeb128(in_stream: &io.InStream) !i64 { |
| 1058 | var result: i64 = 0; | 1046 | var result: i64 = 0; |
| 1059 | var shift: usize = 0; | 1047 | var shift: usize = 0; |
| 1060 | 1048 |
std/os/index.zig+43-77| ... | @@ -57,25 +57,10 @@ const ArrayList = std.ArrayList; | ... | @@ -57,25 +57,10 @@ const ArrayList = std.ArrayList; |
| 57 | const Buffer = std.Buffer; | 57 | const Buffer = std.Buffer; |
| 58 | const math = std.math; | 58 | const math = std.math; |
| 59 | 59 | ||
| 60 | error SystemResources; | ||
| 61 | error AccessDenied; | ||
| 62 | error InvalidExe; | ||
| 63 | error FileSystem; | ||
| 64 | error IsDir; | ||
| 65 | error FileNotFound; | ||
| 66 | error FileBusy; | ||
| 67 | error PathAlreadyExists; | ||
| 68 | error SymLinkLoop; | ||
| 69 | error ReadOnlyFileSystem; | ||
| 70 | error LinkQuotaExceeded; | ||
| 71 | error RenameAcrossMountPoints; | ||
| 72 | error DirNotEmpty; | ||
| 73 | error WouldBlock; | ||
| 74 | |||
| 75 | /// Fills `buf` with random bytes. If linking against libc, this calls the | 60 | /// Fills `buf` with random bytes. If linking against libc, this calls the |
| 76 | /// appropriate OS-specific library call. Otherwise it uses the zig standard | 61 | /// appropriate OS-specific library call. Otherwise it uses the zig standard |
| 77 | /// library implementation. | 62 | /// library implementation. |
| 78 | pub fn getRandomBytes(buf: []u8) %void { | 63 | pub fn getRandomBytes(buf: []u8) !void { |
| 79 | switch (builtin.os) { | 64 | switch (builtin.os) { |
| 80 | Os.linux => while (true) { | 65 | Os.linux => while (true) { |
| 81 | // TODO check libc version and potentially call c.getrandom. | 66 | // TODO check libc version and potentially call c.getrandom. |
| ... | @@ -182,7 +167,7 @@ pub fn close(handle: FileHandle) void { | ... | @@ -182,7 +167,7 @@ pub fn close(handle: FileHandle) void { |
| 182 | } | 167 | } |
| 183 | 168 | ||
| 184 | /// Calls POSIX read, and keeps trying if it gets interrupted. | 169 | /// Calls POSIX read, and keeps trying if it gets interrupted. |
| 185 | pub fn posixRead(fd: i32, buf: []u8) %void { | 170 | pub fn posixRead(fd: i32, buf: []u8) !void { |
| 186 | var index: usize = 0; | 171 | var index: usize = 0; |
| 187 | while (index < buf.len) { | 172 | while (index < buf.len) { |
| 188 | const amt_written = posix.read(fd, &buf[index], buf.len - index); | 173 | const amt_written = posix.read(fd, &buf[index], buf.len - index); |
| ... | @@ -203,17 +188,8 @@ pub fn posixRead(fd: i32, buf: []u8) %void { | ... | @@ -203,17 +188,8 @@ pub fn posixRead(fd: i32, buf: []u8) %void { |
| 203 | } | 188 | } |
| 204 | } | 189 | } |
| 205 | 190 | ||
| 206 | error WouldBlock; | ||
| 207 | error FileClosed; | ||
| 208 | error DestinationAddressRequired; | ||
| 209 | error DiskQuota; | ||
| 210 | error FileTooBig; | ||
| 211 | error InputOutput; | ||
| 212 | error NoSpaceLeft; | ||
| 213 | error BrokenPipe; | ||
| 214 | |||
| 215 | /// Calls POSIX write, and keeps trying if it gets interrupted. | 191 | /// Calls POSIX write, and keeps trying if it gets interrupted. |
| 216 | pub fn posixWrite(fd: i32, bytes: []const u8) %void { | 192 | pub fn posixWrite(fd: i32, bytes: []const u8) !void { |
| 217 | while (true) { | 193 | while (true) { |
| 218 | const write_ret = posix.write(fd, bytes.ptr, bytes.len); | 194 | const write_ret = posix.write(fd, bytes.ptr, bytes.len); |
| 219 | const write_err = posix.getErrno(write_ret); | 195 | const write_err = posix.getErrno(write_ret); |
| ... | @@ -243,7 +219,7 @@ pub fn posixWrite(fd: i32, bytes: []const u8) %void { | ... | @@ -243,7 +219,7 @@ pub fn posixWrite(fd: i32, bytes: []const u8) %void { |
| 243 | /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. | 219 | /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. |
| 244 | /// Calls POSIX open, keeps trying if it gets interrupted, and translates | 220 | /// Calls POSIX open, keeps trying if it gets interrupted, and translates |
| 245 | /// the return value into zig errors. | 221 | /// the return value into zig errors. |
| 246 | pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Allocator) %i32 { | 222 | pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Allocator) !i32 { |
| 247 | var stack_buf: [max_noalloc_path_len]u8 = undefined; | 223 | var stack_buf: [max_noalloc_path_len]u8 = undefined; |
| 248 | var path0: []u8 = undefined; | 224 | var path0: []u8 = undefined; |
| 249 | var need_free = false; | 225 | var need_free = false; |
| ... | @@ -292,7 +268,7 @@ pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Al | ... | @@ -292,7 +268,7 @@ pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Al |
| 292 | } | 268 | } |
| 293 | } | 269 | } |
| 294 | 270 | ||
| 295 | pub fn posixDup2(old_fd: i32, new_fd: i32) %void { | 271 | pub fn posixDup2(old_fd: i32, new_fd: i32) !void { |
| 296 | while (true) { | 272 | while (true) { |
| 297 | const err = posix.getErrno(posix.dup2(old_fd, new_fd)); | 273 | const err = posix.getErrno(posix.dup2(old_fd, new_fd)); |
| 298 | if (err > 0) { | 274 | if (err > 0) { |
| ... | @@ -307,7 +283,7 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) %void { | ... | @@ -307,7 +283,7 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) %void { |
| 307 | } | 283 | } |
| 308 | } | 284 | } |
| 309 | 285 | ||
| 310 | pub fn createNullDelimitedEnvMap(allocator: &Allocator, env_map: &const BufMap) %[]?&u8 { | 286 | pub fn createNullDelimitedEnvMap(allocator: &Allocator, env_map: &const BufMap) ![]?&u8 { |
| 311 | const envp_count = env_map.count(); | 287 | const envp_count = env_map.count(); |
| 312 | const envp_buf = try allocator.alloc(?&u8, envp_count + 1); | 288 | const envp_buf = try allocator.alloc(?&u8, envp_count + 1); |
| 313 | mem.set(?&u8, envp_buf, null); | 289 | mem.set(?&u8, envp_buf, null); |
| ... | @@ -344,7 +320,7 @@ pub fn freeNullDelimitedEnvMap(allocator: &Allocator, envp_buf: []?&u8) void { | ... | @@ -344,7 +320,7 @@ pub fn freeNullDelimitedEnvMap(allocator: &Allocator, envp_buf: []?&u8) void { |
| 344 | /// `argv[0]` is the executable path. | 320 | /// `argv[0]` is the executable path. |
| 345 | /// This function also uses the PATH environment variable to get the full path to the executable. | 321 | /// This function also uses the PATH environment variable to get the full path to the executable. |
| 346 | pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap, | 322 | pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap, |
| 347 | allocator: &Allocator) %void | 323 | allocator: &Allocator) !void |
| 348 | { | 324 | { |
| 349 | const argv_buf = try allocator.alloc(?&u8, argv.len + 1); | 325 | const argv_buf = try allocator.alloc(?&u8, argv.len + 1); |
| 350 | mem.set(?&u8, argv_buf, null); | 326 | mem.set(?&u8, argv_buf, null); |
| ... | @@ -419,7 +395,7 @@ fn posixExecveErrnoToErr(err: usize) error { | ... | @@ -419,7 +395,7 @@ fn posixExecveErrnoToErr(err: usize) error { |
| 419 | pub var posix_environ_raw: []&u8 = undefined; | 395 | pub var posix_environ_raw: []&u8 = undefined; |
| 420 | 396 | ||
| 421 | /// Caller must free result when done. | 397 | /// Caller must free result when done. |
| 422 | pub fn getEnvMap(allocator: &Allocator) %BufMap { | 398 | pub fn getEnvMap(allocator: &Allocator) !BufMap { |
| 423 | var result = BufMap.init(allocator); | 399 | var result = BufMap.init(allocator); |
| 424 | errdefer result.deinit(); | 400 | errdefer result.deinit(); |
| 425 | 401 | ||
| ... | @@ -480,10 +456,8 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 { | ... | @@ -480,10 +456,8 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 { |
| 480 | return null; | 456 | return null; |
| 481 | } | 457 | } |
| 482 | 458 | ||
| 483 | error EnvironmentVariableNotFound; | ||
| 484 | |||
| 485 | /// Caller must free returned memory. | 459 | /// Caller must free returned memory. |
| 486 | pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) %[]u8 { | 460 | pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) ![]u8 { |
| 487 | if (is_windows) { | 461 | if (is_windows) { |
| 488 | const key_with_null = try cstr.addNullByte(allocator, key); | 462 | const key_with_null = try cstr.addNullByte(allocator, key); |
| 489 | defer allocator.free(key_with_null); | 463 | defer allocator.free(key_with_null); |
| ... | @@ -517,7 +491,7 @@ pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) %[]u8 { | ... | @@ -517,7 +491,7 @@ pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) %[]u8 { |
| 517 | } | 491 | } |
| 518 | 492 | ||
| 519 | /// Caller must free the returned memory. | 493 | /// Caller must free the returned memory. |
| 520 | pub fn getCwd(allocator: &Allocator) %[]u8 { | 494 | pub fn getCwd(allocator: &Allocator) ![]u8 { |
| 521 | switch (builtin.os) { | 495 | switch (builtin.os) { |
| 522 | Os.windows => { | 496 | Os.windows => { |
| 523 | var buf = try allocator.alloc(u8, 256); | 497 | var buf = try allocator.alloc(u8, 256); |
| ... | @@ -564,7 +538,7 @@ test "os.getCwd" { | ... | @@ -564,7 +538,7 @@ test "os.getCwd" { |
| 564 | _ = getCwd(debug.global_allocator); | 538 | _ = getCwd(debug.global_allocator); |
| 565 | } | 539 | } |
| 566 | 540 | ||
| 567 | pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) %void { | 541 | pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) !void { |
| 568 | if (is_windows) { | 542 | if (is_windows) { |
| 569 | return symLinkWindows(allocator, existing_path, new_path); | 543 | return symLinkWindows(allocator, existing_path, new_path); |
| 570 | } else { | 544 | } else { |
| ... | @@ -572,7 +546,7 @@ pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []con | ... | @@ -572,7 +546,7 @@ pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []con |
| 572 | } | 546 | } |
| 573 | } | 547 | } |
| 574 | 548 | ||
| 575 | pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) %void { | 549 | pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) !void { |
| 576 | const existing_with_null = try cstr.addNullByte(allocator, existing_path); | 550 | const existing_with_null = try cstr.addNullByte(allocator, existing_path); |
| 577 | defer allocator.free(existing_with_null); | 551 | defer allocator.free(existing_with_null); |
| 578 | const new_with_null = try cstr.addNullByte(allocator, new_path); | 552 | const new_with_null = try cstr.addNullByte(allocator, new_path); |
| ... | @@ -586,7 +560,7 @@ pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path | ... | @@ -586,7 +560,7 @@ pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path |
| 586 | } | 560 | } |
| 587 | } | 561 | } |
| 588 | 562 | ||
| 589 | pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) %void { | 563 | pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) !void { |
| 590 | const full_buf = try allocator.alloc(u8, existing_path.len + new_path.len + 2); | 564 | const full_buf = try allocator.alloc(u8, existing_path.len + new_path.len + 2); |
| 591 | defer allocator.free(full_buf); | 565 | defer allocator.free(full_buf); |
| 592 | 566 | ||
| ... | @@ -623,7 +597,7 @@ const b64_fs_encoder = base64.Base64Encoder.init( | ... | @@ -623,7 +597,7 @@ const b64_fs_encoder = base64.Base64Encoder.init( |
| 623 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", | 597 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", |
| 624 | base64.standard_pad_char); | 598 | base64.standard_pad_char); |
| 625 | 599 | ||
| 626 | pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) %void { | 600 | pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) !void { |
| 627 | if (symLink(allocator, existing_path, new_path)) { | 601 | if (symLink(allocator, existing_path, new_path)) { |
| 628 | return; | 602 | return; |
| 629 | } else |err| { | 603 | } else |err| { |
| ... | @@ -652,7 +626,7 @@ pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: | ... | @@ -652,7 +626,7 @@ pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: |
| 652 | 626 | ||
| 653 | } | 627 | } |
| 654 | 628 | ||
| 655 | pub fn deleteFile(allocator: &Allocator, file_path: []const u8) %void { | 629 | pub fn deleteFile(allocator: &Allocator, file_path: []const u8) !void { |
| 656 | if (builtin.os == Os.windows) { | 630 | if (builtin.os == Os.windows) { |
| 657 | return deleteFileWindows(allocator, file_path); | 631 | return deleteFileWindows(allocator, file_path); |
| 658 | } else { | 632 | } else { |
| ... | @@ -660,10 +634,7 @@ pub fn deleteFile(allocator: &Allocator, file_path: []const u8) %void { | ... | @@ -660,10 +634,7 @@ pub fn deleteFile(allocator: &Allocator, file_path: []const u8) %void { |
| 660 | } | 634 | } |
| 661 | } | 635 | } |
| 662 | 636 | ||
| 663 | error FileNotFound; | 637 | pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) !void { |
| 664 | error AccessDenied; | ||
| 665 | |||
| 666 | pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) %void { | ||
| 667 | const buf = try allocator.alloc(u8, file_path.len + 1); | 638 | const buf = try allocator.alloc(u8, file_path.len + 1); |
| 668 | defer allocator.free(buf); | 639 | defer allocator.free(buf); |
| 669 | 640 | ||
| ... | @@ -681,7 +652,7 @@ pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) %void { | ... | @@ -681,7 +652,7 @@ pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) %void { |
| 681 | } | 652 | } |
| 682 | } | 653 | } |
| 683 | 654 | ||
| 684 | pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) %void { | 655 | pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) !void { |
| 685 | const buf = try allocator.alloc(u8, file_path.len + 1); | 656 | const buf = try allocator.alloc(u8, file_path.len + 1); |
| 686 | defer allocator.free(buf); | 657 | defer allocator.free(buf); |
| 687 | 658 | ||
| ... | @@ -708,13 +679,13 @@ pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) %void { | ... | @@ -708,13 +679,13 @@ pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) %void { |
| 708 | } | 679 | } |
| 709 | 680 | ||
| 710 | /// Calls ::copyFileMode with 0o666 for the mode. | 681 | /// Calls ::copyFileMode with 0o666 for the mode. |
| 711 | pub fn copyFile(allocator: &Allocator, source_path: []const u8, dest_path: []const u8) %void { | 682 | pub fn copyFile(allocator: &Allocator, source_path: []const u8, dest_path: []const u8) !void { |
| 712 | return copyFileMode(allocator, source_path, dest_path, 0o666); | 683 | return copyFileMode(allocator, source_path, dest_path, 0o666); |
| 713 | } | 684 | } |
| 714 | 685 | ||
| 715 | // TODO instead of accepting a mode argument, use the mode from fstat'ing the source path once open | 686 | // TODO instead of accepting a mode argument, use the mode from fstat'ing the source path once open |
| 716 | /// Guaranteed to be atomic. | 687 | /// Guaranteed to be atomic. |
| 717 | pub fn copyFileMode(allocator: &Allocator, source_path: []const u8, dest_path: []const u8, mode: usize) %void { | 688 | pub fn copyFileMode(allocator: &Allocator, source_path: []const u8, dest_path: []const u8, mode: usize) !void { |
| 718 | var rand_buf: [12]u8 = undefined; | 689 | var rand_buf: [12]u8 = undefined; |
| 719 | const tmp_path = try allocator.alloc(u8, dest_path.len + base64.Base64Encoder.calcSize(rand_buf.len)); | 690 | const tmp_path = try allocator.alloc(u8, dest_path.len + base64.Base64Encoder.calcSize(rand_buf.len)); |
| 720 | defer allocator.free(tmp_path); | 691 | defer allocator.free(tmp_path); |
| ... | @@ -738,7 +709,7 @@ pub fn copyFileMode(allocator: &Allocator, source_path: []const u8, dest_path: [ | ... | @@ -738,7 +709,7 @@ pub fn copyFileMode(allocator: &Allocator, source_path: []const u8, dest_path: [ |
| 738 | } | 709 | } |
| 739 | } | 710 | } |
| 740 | 711 | ||
| 741 | pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) %void { | 712 | pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) !void { |
| 742 | const full_buf = try allocator.alloc(u8, old_path.len + new_path.len + 2); | 713 | const full_buf = try allocator.alloc(u8, old_path.len + new_path.len + 2); |
| 743 | defer allocator.free(full_buf); | 714 | defer allocator.free(full_buf); |
| 744 | 715 | ||
| ... | @@ -783,7 +754,7 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) | ... | @@ -783,7 +754,7 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) |
| 783 | } | 754 | } |
| 784 | } | 755 | } |
| 785 | 756 | ||
| 786 | pub fn makeDir(allocator: &Allocator, dir_path: []const u8) %void { | 757 | pub fn makeDir(allocator: &Allocator, dir_path: []const u8) !void { |
| 787 | if (is_windows) { | 758 | if (is_windows) { |
| 788 | return makeDirWindows(allocator, dir_path); | 759 | return makeDirWindows(allocator, dir_path); |
| 789 | } else { | 760 | } else { |
| ... | @@ -791,7 +762,7 @@ pub fn makeDir(allocator: &Allocator, dir_path: []const u8) %void { | ... | @@ -791,7 +762,7 @@ pub fn makeDir(allocator: &Allocator, dir_path: []const u8) %void { |
| 791 | } | 762 | } |
| 792 | } | 763 | } |
| 793 | 764 | ||
| 794 | pub fn makeDirWindows(allocator: &Allocator, dir_path: []const u8) %void { | 765 | pub fn makeDirWindows(allocator: &Allocator, dir_path: []const u8) !void { |
| 795 | const path_buf = try cstr.addNullByte(allocator, dir_path); | 766 | const path_buf = try cstr.addNullByte(allocator, dir_path); |
| 796 | defer allocator.free(path_buf); | 767 | defer allocator.free(path_buf); |
| 797 | 768 | ||
| ... | @@ -805,7 +776,7 @@ pub fn makeDirWindows(allocator: &Allocator, dir_path: []const u8) %void { | ... | @@ -805,7 +776,7 @@ pub fn makeDirWindows(allocator: &Allocator, dir_path: []const u8) %void { |
| 805 | } | 776 | } |
| 806 | } | 777 | } |
| 807 | 778 | ||
| 808 | pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) %void { | 779 | pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) !void { |
| 809 | const path_buf = try cstr.addNullByte(allocator, dir_path); | 780 | const path_buf = try cstr.addNullByte(allocator, dir_path); |
| 810 | defer allocator.free(path_buf); | 781 | defer allocator.free(path_buf); |
| 811 | 782 | ||
| ... | @@ -831,7 +802,7 @@ pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) %void { | ... | @@ -831,7 +802,7 @@ pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) %void { |
| 831 | 802 | ||
| 832 | /// Calls makeDir recursively to make an entire path. Returns success if the path | 803 | /// Calls makeDir recursively to make an entire path. Returns success if the path |
| 833 | /// already exists and is a directory. | 804 | /// already exists and is a directory. |
| 834 | pub fn makePath(allocator: &Allocator, full_path: []const u8) %void { | 805 | pub fn makePath(allocator: &Allocator, full_path: []const u8) !void { |
| 835 | const resolved_path = try path.resolve(allocator, full_path); | 806 | const resolved_path = try path.resolve(allocator, full_path); |
| 836 | defer allocator.free(resolved_path); | 807 | defer allocator.free(resolved_path); |
| 837 | 808 | ||
| ... | @@ -869,7 +840,7 @@ pub fn makePath(allocator: &Allocator, full_path: []const u8) %void { | ... | @@ -869,7 +840,7 @@ pub fn makePath(allocator: &Allocator, full_path: []const u8) %void { |
| 869 | 840 | ||
| 870 | /// Returns ::error.DirNotEmpty if the directory is not empty. | 841 | /// Returns ::error.DirNotEmpty if the directory is not empty. |
| 871 | /// To delete a directory recursively, see ::deleteTree | 842 | /// To delete a directory recursively, see ::deleteTree |
| 872 | pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) %void { | 843 | pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) !void { |
| 873 | const path_buf = try allocator.alloc(u8, dir_path.len + 1); | 844 | const path_buf = try allocator.alloc(u8, dir_path.len + 1); |
| 874 | defer allocator.free(path_buf); | 845 | defer allocator.free(path_buf); |
| 875 | 846 | ||
| ... | @@ -898,7 +869,7 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) %void { | ... | @@ -898,7 +869,7 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) %void { |
| 898 | /// removes it. If it cannot be removed because it is a non-empty directory, | 869 | /// removes it. If it cannot be removed because it is a non-empty directory, |
| 899 | /// this function recursively removes its entries and then tries again. | 870 | /// this function recursively removes its entries and then tries again. |
| 900 | // TODO non-recursive implementation | 871 | // TODO non-recursive implementation |
| 901 | pub fn deleteTree(allocator: &Allocator, full_path: []const u8) %void { | 872 | pub fn deleteTree(allocator: &Allocator, full_path: []const u8) !void { |
| 902 | start_over: while (true) { | 873 | start_over: while (true) { |
| 903 | // First, try deleting the item as a file. This way we don't follow sym links. | 874 | // First, try deleting the item as a file. This way we don't follow sym links. |
| 904 | if (deleteFile(allocator, full_path)) { | 875 | if (deleteFile(allocator, full_path)) { |
| ... | @@ -967,7 +938,7 @@ pub const Dir = struct { | ... | @@ -967,7 +938,7 @@ pub const Dir = struct { |
| 967 | }; | 938 | }; |
| 968 | }; | 939 | }; |
| 969 | 940 | ||
| 970 | pub fn open(allocator: &Allocator, dir_path: []const u8) %Dir { | 941 | pub fn open(allocator: &Allocator, dir_path: []const u8) !Dir { |
| 971 | const fd = try posixOpen(dir_path, posix.O_RDONLY|posix.O_DIRECTORY|posix.O_CLOEXEC, 0, allocator); | 942 | const fd = try posixOpen(dir_path, posix.O_RDONLY|posix.O_DIRECTORY|posix.O_CLOEXEC, 0, allocator); |
| 972 | return Dir { | 943 | return Dir { |
| 973 | .allocator = allocator, | 944 | .allocator = allocator, |
| ... | @@ -985,7 +956,7 @@ pub const Dir = struct { | ... | @@ -985,7 +956,7 @@ pub const Dir = struct { |
| 985 | 956 | ||
| 986 | /// Memory such as file names referenced in this returned entry becomes invalid | 957 | /// Memory such as file names referenced in this returned entry becomes invalid |
| 987 | /// with subsequent calls to next, as well as when this ::Dir is deinitialized. | 958 | /// with subsequent calls to next, as well as when this ::Dir is deinitialized. |
| 988 | pub fn next(self: &Dir) %?Entry { | 959 | pub fn next(self: &Dir) !?Entry { |
| 989 | start_over: while (true) { | 960 | start_over: while (true) { |
| 990 | if (self.index >= self.end_index) { | 961 | if (self.index >= self.end_index) { |
| 991 | if (self.buf.len == 0) { | 962 | if (self.buf.len == 0) { |
| ... | @@ -1042,7 +1013,7 @@ pub const Dir = struct { | ... | @@ -1042,7 +1013,7 @@ pub const Dir = struct { |
| 1042 | } | 1013 | } |
| 1043 | }; | 1014 | }; |
| 1044 | 1015 | ||
| 1045 | pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) %void { | 1016 | pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) !void { |
| 1046 | const path_buf = try allocator.alloc(u8, dir_path.len + 1); | 1017 | const path_buf = try allocator.alloc(u8, dir_path.len + 1); |
| 1047 | defer allocator.free(path_buf); | 1018 | defer allocator.free(path_buf); |
| 1048 | 1019 | ||
| ... | @@ -1066,7 +1037,7 @@ pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) %void { | ... | @@ -1066,7 +1037,7 @@ pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) %void { |
| 1066 | } | 1037 | } |
| 1067 | 1038 | ||
| 1068 | /// Read value of a symbolic link. | 1039 | /// Read value of a symbolic link. |
| 1069 | pub fn readLink(allocator: &Allocator, pathname: []const u8) %[]u8 { | 1040 | pub fn readLink(allocator: &Allocator, pathname: []const u8) ![]u8 { |
| 1070 | const path_buf = try allocator.alloc(u8, pathname.len + 1); | 1041 | const path_buf = try allocator.alloc(u8, pathname.len + 1); |
| 1071 | defer allocator.free(path_buf); | 1042 | defer allocator.free(path_buf); |
| 1072 | 1043 | ||
| ... | @@ -1143,11 +1114,7 @@ test "os.sleep" { | ... | @@ -1143,11 +1114,7 @@ test "os.sleep" { |
| 1143 | sleep(0, 1); | 1114 | sleep(0, 1); |
| 1144 | } | 1115 | } |
| 1145 | 1116 | ||
| 1146 | error ResourceLimitReached; | 1117 | pub fn posix_setuid(uid: u32) !void { |
| 1147 | error InvalidUserId; | ||
| 1148 | error PermissionDenied; | ||
| 1149 | |||
| 1150 | pub fn posix_setuid(uid: u32) %void { | ||
| 1151 | const err = posix.getErrno(posix.setuid(uid)); | 1118 | const err = posix.getErrno(posix.setuid(uid)); |
| 1152 | if (err == 0) return; | 1119 | if (err == 0) return; |
| 1153 | return switch (err) { | 1120 | return switch (err) { |
| ... | @@ -1158,7 +1125,7 @@ pub fn posix_setuid(uid: u32) %void { | ... | @@ -1158,7 +1125,7 @@ pub fn posix_setuid(uid: u32) %void { |
| 1158 | }; | 1125 | }; |
| 1159 | } | 1126 | } |
| 1160 | 1127 | ||
| 1161 | pub fn posix_setreuid(ruid: u32, euid: u32) %void { | 1128 | pub fn posix_setreuid(ruid: u32, euid: u32) !void { |
| 1162 | const err = posix.getErrno(posix.setreuid(ruid, euid)); | 1129 | const err = posix.getErrno(posix.setreuid(ruid, euid)); |
| 1163 | if (err == 0) return; | 1130 | if (err == 0) return; |
| 1164 | return switch (err) { | 1131 | return switch (err) { |
| ... | @@ -1169,7 +1136,7 @@ pub fn posix_setreuid(ruid: u32, euid: u32) %void { | ... | @@ -1169,7 +1136,7 @@ pub fn posix_setreuid(ruid: u32, euid: u32) %void { |
| 1169 | }; | 1136 | }; |
| 1170 | } | 1137 | } |
| 1171 | 1138 | ||
| 1172 | pub fn posix_setgid(gid: u32) %void { | 1139 | pub fn posix_setgid(gid: u32) !void { |
| 1173 | const err = posix.getErrno(posix.setgid(gid)); | 1140 | const err = posix.getErrno(posix.setgid(gid)); |
| 1174 | if (err == 0) return; | 1141 | if (err == 0) return; |
| 1175 | return switch (err) { | 1142 | return switch (err) { |
| ... | @@ -1180,7 +1147,7 @@ pub fn posix_setgid(gid: u32) %void { | ... | @@ -1180,7 +1147,7 @@ pub fn posix_setgid(gid: u32) %void { |
| 1180 | }; | 1147 | }; |
| 1181 | } | 1148 | } |
| 1182 | 1149 | ||
| 1183 | pub fn posix_setregid(rgid: u32, egid: u32) %void { | 1150 | pub fn posix_setregid(rgid: u32, egid: u32) !void { |
| 1184 | const err = posix.getErrno(posix.setregid(rgid, egid)); | 1151 | const err = posix.getErrno(posix.setregid(rgid, egid)); |
| 1185 | if (err == 0) return; | 1152 | if (err == 0) return; |
| 1186 | return switch (err) { | 1153 | return switch (err) { |
| ... | @@ -1191,8 +1158,7 @@ pub fn posix_setregid(rgid: u32, egid: u32) %void { | ... | @@ -1191,8 +1158,7 @@ pub fn posix_setregid(rgid: u32, egid: u32) %void { |
| 1191 | }; | 1158 | }; |
| 1192 | } | 1159 | } |
| 1193 | 1160 | ||
| 1194 | error NoStdHandles; | 1161 | pub fn windowsGetStdHandle(handle_id: windows.DWORD) !windows.HANDLE { |
| 1195 | pub fn windowsGetStdHandle(handle_id: windows.DWORD) %windows.HANDLE { | ||
| 1196 | if (windows.GetStdHandle(handle_id)) |handle| { | 1162 | if (windows.GetStdHandle(handle_id)) |handle| { |
| 1197 | if (handle == windows.INVALID_HANDLE_VALUE) { | 1163 | if (handle == windows.INVALID_HANDLE_VALUE) { |
| 1198 | const err = windows.GetLastError(); | 1164 | const err = windows.GetLastError(); |
| ... | @@ -1261,7 +1227,7 @@ pub const ArgIteratorWindows = struct { | ... | @@ -1261,7 +1227,7 @@ pub const ArgIteratorWindows = struct { |
| 1261 | } | 1227 | } |
| 1262 | 1228 | ||
| 1263 | /// You must free the returned memory when done. | 1229 | /// You must free the returned memory when done. |
| 1264 | pub fn next(self: &ArgIteratorWindows, allocator: &Allocator) ?%[]u8 { | 1230 | pub fn next(self: &ArgIteratorWindows, allocator: &Allocator) ?internalNext.errors![]u8 { |
| 1265 | // march forward over whitespace | 1231 | // march forward over whitespace |
| 1266 | while (true) : (self.index += 1) { | 1232 | while (true) : (self.index += 1) { |
| 1267 | const byte = self.cmd_line[self.index]; | 1233 | const byte = self.cmd_line[self.index]; |
| ... | @@ -1314,7 +1280,7 @@ pub const ArgIteratorWindows = struct { | ... | @@ -1314,7 +1280,7 @@ pub const ArgIteratorWindows = struct { |
| 1314 | } | 1280 | } |
| 1315 | } | 1281 | } |
| 1316 | 1282 | ||
| 1317 | fn internalNext(self: &ArgIteratorWindows, allocator: &Allocator) %[]u8 { | 1283 | fn internalNext(self: &ArgIteratorWindows, allocator: &Allocator) ![]u8 { |
| 1318 | var buf = try Buffer.initSize(allocator, 0); | 1284 | var buf = try Buffer.initSize(allocator, 0); |
| 1319 | defer buf.deinit(); | 1285 | defer buf.deinit(); |
| 1320 | 1286 | ||
| ... | @@ -1358,7 +1324,7 @@ pub const ArgIteratorWindows = struct { | ... | @@ -1358,7 +1324,7 @@ pub const ArgIteratorWindows = struct { |
| 1358 | } | 1324 | } |
| 1359 | } | 1325 | } |
| 1360 | 1326 | ||
| 1361 | fn emitBackslashes(self: &ArgIteratorWindows, buf: &Buffer, emit_count: usize) %void { | 1327 | fn emitBackslashes(self: &ArgIteratorWindows, buf: &Buffer, emit_count: usize) !void { |
| 1362 | var i: usize = 0; | 1328 | var i: usize = 0; |
| 1363 | while (i < emit_count) : (i += 1) { | 1329 | while (i < emit_count) : (i += 1) { |
| 1364 | try buf.appendByte('\\'); | 1330 | try buf.appendByte('\\'); |
| ... | @@ -1397,7 +1363,7 @@ pub const ArgIterator = struct { | ... | @@ -1397,7 +1363,7 @@ pub const ArgIterator = struct { |
| 1397 | } | 1363 | } |
| 1398 | 1364 | ||
| 1399 | /// You must free the returned memory when done. | 1365 | /// You must free the returned memory when done. |
| 1400 | pub fn next(self: &ArgIterator, allocator: &Allocator) ?%[]u8 { | 1366 | pub fn next(self: &ArgIterator, allocator: &Allocator) ?![]u8 { |
| 1401 | if (builtin.os == Os.windows) { | 1367 | if (builtin.os == Os.windows) { |
| 1402 | return self.inner.next(allocator); | 1368 | return self.inner.next(allocator); |
| 1403 | } else { | 1369 | } else { |
| ... | @@ -1422,7 +1388,7 @@ pub fn args() ArgIterator { | ... | @@ -1422,7 +1388,7 @@ pub fn args() ArgIterator { |
| 1422 | } | 1388 | } |
| 1423 | 1389 | ||
| 1424 | /// Caller must call freeArgs on result. | 1390 | /// Caller must call freeArgs on result. |
| 1425 | pub fn argsAlloc(allocator: &mem.Allocator) %[]const []u8 { | 1391 | pub fn argsAlloc(allocator: &mem.Allocator) ![]const []u8 { |
| 1426 | // TODO refactor to only make 1 allocation. | 1392 | // TODO refactor to only make 1 allocation. |
| 1427 | var it = args(); | 1393 | var it = args(); |
| 1428 | var contents = try Buffer.initSize(allocator, 0); | 1394 | var contents = try Buffer.initSize(allocator, 0); |
| ... | @@ -1529,7 +1495,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) error { | ... | @@ -1529,7 +1495,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) error { |
| 1529 | return error.Unexpected; | 1495 | return error.Unexpected; |
| 1530 | } | 1496 | } |
| 1531 | 1497 | ||
| 1532 | pub fn openSelfExe() %io.File { | 1498 | pub fn openSelfExe() !io.File { |
| 1533 | switch (builtin.os) { | 1499 | switch (builtin.os) { |
| 1534 | Os.linux => { | 1500 | Os.linux => { |
| 1535 | return io.File.openRead("/proc/self/exe", null); | 1501 | return io.File.openRead("/proc/self/exe", null); |
| ... | @@ -1547,7 +1513,7 @@ pub fn openSelfExe() %io.File { | ... | @@ -1547,7 +1513,7 @@ pub fn openSelfExe() %io.File { |
| 1547 | /// This function may return an error if the current executable | 1513 | /// This function may return an error if the current executable |
| 1548 | /// was deleted after spawning. | 1514 | /// was deleted after spawning. |
| 1549 | /// Caller owns returned memory. | 1515 | /// Caller owns returned memory. |
| 1550 | pub fn selfExePath(allocator: &mem.Allocator) %[]u8 { | 1516 | pub fn selfExePath(allocator: &mem.Allocator) ![]u8 { |
| 1551 | switch (builtin.os) { | 1517 | switch (builtin.os) { |
| 1552 | Os.linux => { | 1518 | Os.linux => { |
| 1553 | // If the currently executing binary has been deleted, | 1519 | // If the currently executing binary has been deleted, |
| ... | @@ -1590,7 +1556,7 @@ pub fn selfExePath(allocator: &mem.Allocator) %[]u8 { | ... | @@ -1590,7 +1556,7 @@ pub fn selfExePath(allocator: &mem.Allocator) %[]u8 { |
| 1590 | 1556 | ||
| 1591 | /// Get the directory path that contains the current executable. | 1557 | /// Get the directory path that contains the current executable. |
| 1592 | /// Caller owns returned memory. | 1558 | /// Caller owns returned memory. |
| 1593 | pub fn selfExeDirPath(allocator: &mem.Allocator) %[]u8 { | 1559 | pub fn selfExeDirPath(allocator: &mem.Allocator) ![]u8 { |
| 1594 | switch (builtin.os) { | 1560 | switch (builtin.os) { |
| 1595 | Os.linux => { | 1561 | Os.linux => { |
| 1596 | // If the currently executing binary has been deleted, | 1562 | // If the currently executing binary has been deleted, |
std/special/test_runner.zig+1-1| ... | @@ -4,7 +4,7 @@ const builtin = @import("builtin"); | ... | @@ -4,7 +4,7 @@ const builtin = @import("builtin"); |
| 4 | const test_fn_list = builtin.__zig_test_fn_slice; | 4 | const test_fn_list = builtin.__zig_test_fn_slice; |
| 5 | const warn = std.debug.warn; | 5 | const warn = std.debug.warn; |
| 6 | 6 | ||
| 7 | pub fn main() %void { | 7 | pub fn main() !void { |
| 8 | for (test_fn_list) |test_fn, i| { | 8 | for (test_fn_list) |test_fn, i| { |
| 9 | warn("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name); | 9 | warn("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name); |
| 10 | 10 |