| author | |
| committer | |
| log | b57cb04afc1898c3b21ef3486709f0c0aa285433 |
| tree | e234c061c28a95c35afbb35b80b89e3114ecdeb9 |
| parent | 73a306e2fa11c146b5f79a41953e0d19a82f17a5 |
| parent | 2e010c60ae006944ae20ab8b3445598471c9f1e8 |
22 files changed, 909 insertions(+), 352 deletions(-)
README.md+2-2| ... | @@ -125,13 +125,13 @@ libc. Create demo games using Zig. | ... | @@ -125,13 +125,13 @@ libc. Create demo games using Zig. |
| 125 | 125 | ||
| 126 | * cmake >= 2.8.5 | 126 | * cmake >= 2.8.5 |
| 127 | * gcc >= 5.0.0 or clang >= 3.6.0 | 127 | * gcc >= 5.0.0 or clang >= 3.6.0 |
| 128 | * LLVM, Clang, LLD libraries == 6.x, compiled with the same gcc or clang version above | 128 | * LLVM, Clang, LLD development libraries == 6.x, compiled with the same gcc or clang version above |
| 129 | 129 | ||
| 130 | ##### Windows | 130 | ##### Windows |
| 131 | 131 | ||
| 132 | * cmake >= 2.8.5 | 132 | * cmake >= 2.8.5 |
| 133 | * Microsoft Visual Studio 2015 | 133 | * Microsoft Visual Studio 2015 |
| 134 | * LLVM, Clang, LLD libraries == 6.x, compiled with the same MSVC version above | 134 | * LLVM, Clang, LLD development libraries == 6.x, compiled with the same MSVC version above |
| 135 | 135 | ||
| 136 | #### Instructions | 136 | #### Instructions |
| 137 | 137 |
doc/langref.html.in+3-3| ... | @@ -5733,19 +5733,19 @@ UseDecl = "use" Expression ";" | ... | @@ -5733,19 +5733,19 @@ UseDecl = "use" Expression ";" |
| 5733 | 5733 | ||
| 5734 | ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";" | 5734 | ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";" |
| 5735 | 5735 | ||
| 5736 | FnProto = option("nakedcc" | "stdcallcc" | "extern" | ("async" option("(" Expression ")"))) "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr | 5736 | FnProto = option("nakedcc" | "stdcallcc" | "extern" | ("async" option("(" Expression ")"))) "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") (TypeExpr | "var") |
| 5737 | 5737 | ||
| 5738 | FnDef = option("inline" | "export") FnProto Block | 5738 | FnDef = option("inline" | "export") FnProto Block |
| 5739 | 5739 | ||
| 5740 | ParamDeclList = "(" list(ParamDecl, ",") ")" | 5740 | ParamDeclList = "(" list(ParamDecl, ",") ")" |
| 5741 | 5741 | ||
| 5742 | ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "...") | 5742 | ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "var" | "...") |
| 5743 | 5743 | ||
| 5744 | Block = option(Symbol ":") "{" many(Statement) "}" | 5744 | Block = option(Symbol ":") "{" many(Statement) "}" |
| 5745 | 5745 | ||
| 5746 | Statement = LocalVarDecl ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";" | 5746 | Statement = LocalVarDecl ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";" |
| 5747 | 5747 | ||
| 5748 | TypeExpr = ErrorSetExpr | "var" | 5748 | TypeExpr = ErrorSetExpr |
| 5749 | 5749 | ||
| 5750 | ErrorSetExpr = (PrefixOpExpression "!" PrefixOpExpression) | PrefixOpExpression | 5750 | ErrorSetExpr = (PrefixOpExpression "!" PrefixOpExpression) | PrefixOpExpression |
| 5751 | 5751 |
src/all_types.hpp+5-6| ... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
| 16 | #include "bigint.hpp" | 16 | #include "bigint.hpp" |
| 17 | #include "bigfloat.hpp" | 17 | #include "bigfloat.hpp" |
| 18 | #include "target.hpp" | 18 | #include "target.hpp" |
| 19 | #include "tokenizer.hpp" | ||
| 19 | 20 | ||
| 20 | struct AstNode; | 21 | struct AstNode; |
| 21 | struct ImportTableEntry; | 22 | struct ImportTableEntry; |
| ... | @@ -399,7 +400,6 @@ enum NodeType { | ... | @@ -399,7 +400,6 @@ enum NodeType { |
| 399 | NodeTypeStructValueField, | 400 | NodeTypeStructValueField, |
| 400 | NodeTypeArrayType, | 401 | NodeTypeArrayType, |
| 401 | NodeTypeErrorType, | 402 | NodeTypeErrorType, |
| 402 | NodeTypeVarLiteral, | ||
| 403 | NodeTypeIfErrorExpr, | 403 | NodeTypeIfErrorExpr, |
| 404 | NodeTypeTestExpr, | 404 | NodeTypeTestExpr, |
| 405 | NodeTypeErrorSetDecl, | 405 | NodeTypeErrorSetDecl, |
| ... | @@ -427,6 +427,7 @@ struct AstNodeFnProto { | ... | @@ -427,6 +427,7 @@ struct AstNodeFnProto { |
| 427 | Buf *name; | 427 | Buf *name; |
| 428 | ZigList<AstNode *> params; | 428 | ZigList<AstNode *> params; |
| 429 | AstNode *return_type; | 429 | AstNode *return_type; |
| 430 | Token *return_var_token; | ||
| 430 | bool is_var_args; | 431 | bool is_var_args; |
| 431 | bool is_extern; | 432 | bool is_extern; |
| 432 | bool is_export; | 433 | bool is_export; |
| ... | @@ -456,6 +457,7 @@ struct AstNodeFnDecl { | ... | @@ -456,6 +457,7 @@ struct AstNodeFnDecl { |
| 456 | struct AstNodeParamDecl { | 457 | struct AstNodeParamDecl { |
| 457 | Buf *name; | 458 | Buf *name; |
| 458 | AstNode *type; | 459 | AstNode *type; |
| 460 | Token *var_token; | ||
| 459 | bool is_noalias; | 461 | bool is_noalias; |
| 460 | bool is_inline; | 462 | bool is_inline; |
| 461 | bool is_var_args; | 463 | bool is_var_args; |
| ... | @@ -866,9 +868,6 @@ struct AstNodeUnreachableExpr { | ... | @@ -866,9 +868,6 @@ struct AstNodeUnreachableExpr { |
| 866 | struct AstNodeErrorType { | 868 | struct AstNodeErrorType { |
| 867 | }; | 869 | }; |
| 868 | 870 | ||
| 869 | struct AstNodeVarLiteral { | ||
| 870 | }; | ||
| 871 | |||
| 872 | struct AstNodeAwaitExpr { | 871 | struct AstNodeAwaitExpr { |
| 873 | AstNode *expr; | 872 | AstNode *expr; |
| 874 | }; | 873 | }; |
| ... | @@ -933,7 +932,6 @@ struct AstNode { | ... | @@ -933,7 +932,6 @@ struct AstNode { |
| 933 | AstNodeUnreachableExpr unreachable_expr; | 932 | AstNodeUnreachableExpr unreachable_expr; |
| 934 | AstNodeArrayType array_type; | 933 | AstNodeArrayType array_type; |
| 935 | AstNodeErrorType error_type; | 934 | AstNodeErrorType error_type; |
| 936 | AstNodeVarLiteral var_literal; | ||
| 937 | AstNodeErrorSetDecl err_set_decl; | 935 | AstNodeErrorSetDecl err_set_decl; |
| 938 | AstNodeCancelExpr cancel_expr; | 936 | AstNodeCancelExpr cancel_expr; |
| 939 | AstNodeResumeExpr resume_expr; | 937 | AstNodeResumeExpr resume_expr; |
| ... | @@ -1098,6 +1096,8 @@ struct TypeTableEntryUnion { | ... | @@ -1098,6 +1096,8 @@ struct TypeTableEntryUnion { |
| 1098 | size_t gen_union_index; | 1096 | size_t gen_union_index; |
| 1099 | size_t gen_tag_index; | 1097 | size_t gen_tag_index; |
| 1100 | 1098 | ||
| 1099 | bool have_explicit_tag_type; | ||
| 1100 | |||
| 1101 | uint32_t union_size_bytes; | 1101 | uint32_t union_size_bytes; |
| 1102 | TypeTableEntry *most_aligned_union_member; | 1102 | TypeTableEntry *most_aligned_union_member; |
| 1103 | 1103 | ||
| ... | @@ -1134,7 +1134,6 @@ struct TypeTableEntryPromise { | ... | @@ -1134,7 +1134,6 @@ struct TypeTableEntryPromise { |
| 1134 | 1134 | ||
| 1135 | enum TypeTableEntryId { | 1135 | enum TypeTableEntryId { |
| 1136 | TypeTableEntryIdInvalid, | 1136 | TypeTableEntryIdInvalid, |
| 1137 | TypeTableEntryIdVar, | ||
| 1138 | TypeTableEntryIdMetaType, | 1137 | TypeTableEntryIdMetaType, |
| 1139 | TypeTableEntryIdVoid, | 1138 | TypeTableEntryIdVoid, |
| 1140 | TypeTableEntryIdBool, | 1139 | TypeTableEntryIdBool, |
src/analyze.cpp+53-39| ... | @@ -200,7 +200,6 @@ static uint8_t bits_needed_for_unsigned(uint64_t x) { | ... | @@ -200,7 +200,6 @@ static uint8_t bits_needed_for_unsigned(uint64_t x) { |
| 200 | bool type_is_complete(TypeTableEntry *type_entry) { | 200 | bool type_is_complete(TypeTableEntry *type_entry) { |
| 201 | switch (type_entry->id) { | 201 | switch (type_entry->id) { |
| 202 | case TypeTableEntryIdInvalid: | 202 | case TypeTableEntryIdInvalid: |
| 203 | case TypeTableEntryIdVar: | ||
| 204 | zig_unreachable(); | 203 | zig_unreachable(); |
| 205 | case TypeTableEntryIdStruct: | 204 | case TypeTableEntryIdStruct: |
| 206 | return type_entry->data.structure.complete; | 205 | return type_entry->data.structure.complete; |
| ... | @@ -239,7 +238,6 @@ bool type_is_complete(TypeTableEntry *type_entry) { | ... | @@ -239,7 +238,6 @@ bool type_is_complete(TypeTableEntry *type_entry) { |
| 239 | bool type_has_zero_bits_known(TypeTableEntry *type_entry) { | 238 | bool type_has_zero_bits_known(TypeTableEntry *type_entry) { |
| 240 | switch (type_entry->id) { | 239 | switch (type_entry->id) { |
| 241 | case TypeTableEntryIdInvalid: | 240 | case TypeTableEntryIdInvalid: |
| 242 | case TypeTableEntryIdVar: | ||
| 243 | zig_unreachable(); | 241 | zig_unreachable(); |
| 244 | case TypeTableEntryIdStruct: | 242 | case TypeTableEntryIdStruct: |
| 245 | return type_entry->data.structure.zero_bits_known; | 243 | return type_entry->data.structure.zero_bits_known; |
| ... | @@ -466,9 +464,8 @@ TypeTableEntry *get_promise_frame_type(CodeGen *g, TypeTableEntry *return_type) | ... | @@ -466,9 +464,8 @@ TypeTableEntry *get_promise_frame_type(CodeGen *g, TypeTableEntry *return_type) |
| 466 | TypeTableEntry *result_ptr_type = get_pointer_to_type(g, return_type, false); | 464 | TypeTableEntry *result_ptr_type = get_pointer_to_type(g, return_type, false); |
| 467 | const char *field_names[] = {AWAITER_HANDLE_FIELD_NAME, RESULT_FIELD_NAME, RESULT_PTR_FIELD_NAME}; | 465 | const char *field_names[] = {AWAITER_HANDLE_FIELD_NAME, RESULT_FIELD_NAME, RESULT_PTR_FIELD_NAME}; |
| 468 | TypeTableEntry *field_types[] = {awaiter_handle_type, return_type, result_ptr_type}; | 466 | TypeTableEntry *field_types[] = {awaiter_handle_type, return_type, result_ptr_type}; |
| 469 | size_t field_count = type_has_bits(result_ptr_type) ? 3 : 1; | ||
| 470 | Buf *name = buf_sprintf("AsyncFramePromise(%s)", buf_ptr(&return_type->name)); | 467 | Buf *name = buf_sprintf("AsyncFramePromise(%s)", buf_ptr(&return_type->name)); |
| 471 | TypeTableEntry *entry = get_struct_type(g, buf_ptr(name), field_names, field_types, field_count); | 468 | TypeTableEntry *entry = get_struct_type(g, buf_ptr(name), field_names, field_types, 3); |
| 472 | 469 | ||
| 473 | return_type->promise_frame_parent = entry; | 470 | return_type->promise_frame_parent = entry; |
| 474 | return entry; | 471 | return entry; |
| ... | @@ -1281,7 +1278,6 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** | ... | @@ -1281,7 +1278,6 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** |
| 1281 | static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { | 1278 | static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { |
| 1282 | switch (type_entry->id) { | 1279 | switch (type_entry->id) { |
| 1283 | case TypeTableEntryIdInvalid: | 1280 | case TypeTableEntryIdInvalid: |
| 1284 | case TypeTableEntryIdVar: | ||
| 1285 | zig_unreachable(); | 1281 | zig_unreachable(); |
| 1286 | case TypeTableEntryIdMetaType: | 1282 | case TypeTableEntryIdMetaType: |
| 1287 | case TypeTableEntryIdUnreachable: | 1283 | case TypeTableEntryIdUnreachable: |
| ... | @@ -1324,7 +1320,6 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { | ... | @@ -1324,7 +1320,6 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { |
| 1324 | static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) { | 1320 | static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) { |
| 1325 | switch (type_entry->id) { | 1321 | switch (type_entry->id) { |
| 1326 | case TypeTableEntryIdInvalid: | 1322 | case TypeTableEntryIdInvalid: |
| 1327 | case TypeTableEntryIdVar: | ||
| 1328 | zig_unreachable(); | 1323 | zig_unreachable(); |
| 1329 | case TypeTableEntryIdMetaType: | 1324 | case TypeTableEntryIdMetaType: |
| 1330 | case TypeTableEntryIdNumLitFloat: | 1325 | case TypeTableEntryIdNumLitFloat: |
| ... | @@ -1428,6 +1423,14 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c | ... | @@ -1428,6 +1423,14 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1428 | calling_convention_name(fn_type_id.cc))); | 1423 | calling_convention_name(fn_type_id.cc))); |
| 1429 | return g->builtin_types.entry_invalid; | 1424 | return g->builtin_types.entry_invalid; |
| 1430 | } | 1425 | } |
| 1426 | } else if (param_node->data.param_decl.var_token != nullptr) { | ||
| 1427 | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { | ||
| 1428 | add_node_error(g, param_node->data.param_decl.type, | ||
| 1429 | buf_sprintf("parameter of type 'var' not allowed in function with calling convention '%s'", | ||
| 1430 | calling_convention_name(fn_type_id.cc))); | ||
| 1431 | return g->builtin_types.entry_invalid; | ||
| 1432 | } | ||
| 1433 | return get_generic_fn_type(g, &fn_type_id); | ||
| 1431 | } | 1434 | } |
| 1432 | 1435 | ||
| 1433 | TypeTableEntry *type_entry = analyze_type_expr(g, child_scope, param_node->data.param_decl.type); | 1436 | TypeTableEntry *type_entry = analyze_type_expr(g, child_scope, param_node->data.param_decl.type); |
| ... | @@ -1463,14 +1466,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c | ... | @@ -1463,14 +1466,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1463 | add_node_error(g, param_node->data.param_decl.type, | 1466 | add_node_error(g, param_node->data.param_decl.type, |
| 1464 | buf_sprintf("parameter of type '%s' not allowed", buf_ptr(&type_entry->name))); | 1467 | buf_sprintf("parameter of type '%s' not allowed", buf_ptr(&type_entry->name))); |
| 1465 | return g->builtin_types.entry_invalid; | 1468 | return g->builtin_types.entry_invalid; |
| 1466 | case TypeTableEntryIdVar: | ||
| 1467 | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { | ||
| 1468 | add_node_error(g, param_node->data.param_decl.type, | ||
| 1469 | buf_sprintf("parameter of type 'var' not allowed in function with calling convention '%s'", | ||
| 1470 | calling_convention_name(fn_type_id.cc))); | ||
| 1471 | return g->builtin_types.entry_invalid; | ||
| 1472 | } | ||
| 1473 | return get_generic_fn_type(g, &fn_type_id); | ||
| 1474 | case TypeTableEntryIdNumLitFloat: | 1469 | case TypeTableEntryIdNumLitFloat: |
| 1475 | case TypeTableEntryIdNumLitInt: | 1470 | case TypeTableEntryIdNumLitInt: |
| 1476 | case TypeTableEntryIdNamespace: | 1471 | case TypeTableEntryIdNamespace: |
| ... | @@ -1514,6 +1509,19 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c | ... | @@ -1514,6 +1509,19 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1514 | } | 1509 | } |
| 1515 | } | 1510 | } |
| 1516 | 1511 | ||
| 1512 | if (fn_proto->return_var_token != nullptr) { | ||
| 1513 | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { | ||
| 1514 | add_node_error(g, fn_proto->return_type, | ||
| 1515 | buf_sprintf("return type 'var' not allowed in function with calling convention '%s'", | ||
| 1516 | calling_convention_name(fn_type_id.cc))); | ||
| 1517 | return g->builtin_types.entry_invalid; | ||
| 1518 | } | ||
| 1519 | add_node_error(g, proto_node, | ||
| 1520 | buf_sprintf("TODO implement inferred return types https://github.com/zig-lang/zig/issues/447")); | ||
| 1521 | return g->builtin_types.entry_invalid; | ||
| 1522 | //return get_generic_fn_type(g, &fn_type_id); | ||
| 1523 | } | ||
| 1524 | |||
| 1517 | TypeTableEntry *specified_return_type = analyze_type_expr(g, child_scope, fn_proto->return_type); | 1525 | TypeTableEntry *specified_return_type = analyze_type_expr(g, child_scope, fn_proto->return_type); |
| 1518 | if (type_is_invalid(specified_return_type)) { | 1526 | if (type_is_invalid(specified_return_type)) { |
| 1519 | fn_type_id.return_type = g->builtin_types.entry_invalid; | 1527 | fn_type_id.return_type = g->builtin_types.entry_invalid; |
| ... | @@ -1552,7 +1560,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c | ... | @@ -1552,7 +1560,6 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1552 | case TypeTableEntryIdNamespace: | 1560 | case TypeTableEntryIdNamespace: |
| 1553 | case TypeTableEntryIdBlock: | 1561 | case TypeTableEntryIdBlock: |
| 1554 | case TypeTableEntryIdBoundFn: | 1562 | case TypeTableEntryIdBoundFn: |
| 1555 | case TypeTableEntryIdVar: | ||
| 1556 | case TypeTableEntryIdMetaType: | 1563 | case TypeTableEntryIdMetaType: |
| 1557 | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { | 1564 | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { |
| 1558 | add_node_error(g, fn_proto->return_type, | 1565 | add_node_error(g, fn_proto->return_type, |
| ... | @@ -1707,7 +1714,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f | ... | @@ -1707,7 +1714,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f |
| 1707 | buf_init_from_str(&struct_type->name, type_name); | 1714 | buf_init_from_str(&struct_type->name, type_name); |
| 1708 | 1715 | ||
| 1709 | struct_type->data.structure.src_field_count = field_count; | 1716 | struct_type->data.structure.src_field_count = field_count; |
| 1710 | struct_type->data.structure.gen_field_count = field_count; | 1717 | struct_type->data.structure.gen_field_count = 0; |
| 1711 | struct_type->data.structure.zero_bits_known = true; | 1718 | struct_type->data.structure.zero_bits_known = true; |
| 1712 | struct_type->data.structure.complete = true; | 1719 | struct_type->data.structure.complete = true; |
| 1713 | struct_type->data.structure.fields = allocate<TypeStructField>(field_count); | 1720 | struct_type->data.structure.fields = allocate<TypeStructField>(field_count); |
| ... | @@ -1716,22 +1723,26 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f | ... | @@ -1716,22 +1723,26 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f |
| 1716 | ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(field_count); | 1723 | ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(field_count); |
| 1717 | LLVMTypeRef *element_types = allocate<LLVMTypeRef>(field_count); | 1724 | LLVMTypeRef *element_types = allocate<LLVMTypeRef>(field_count); |
| 1718 | for (size_t i = 0; i < field_count; i += 1) { | 1725 | for (size_t i = 0; i < field_count; i += 1) { |
| 1719 | element_types[i] = field_types[i]->type_ref; | 1726 | element_types[struct_type->data.structure.gen_field_count] = field_types[i]->type_ref; |
| 1720 | 1727 | ||
| 1721 | TypeStructField *field = &struct_type->data.structure.fields[i]; | 1728 | TypeStructField *field = &struct_type->data.structure.fields[i]; |
| 1722 | field->name = buf_create_from_str(field_names[i]); | 1729 | field->name = buf_create_from_str(field_names[i]); |
| 1723 | field->type_entry = field_types[i]; | 1730 | field->type_entry = field_types[i]; |
| 1724 | field->src_index = i; | 1731 | field->src_index = i; |
| 1725 | field->gen_index = i; | ||
| 1726 | 1732 | ||
| 1727 | assert(type_has_bits(field->type_entry)); | 1733 | if (type_has_bits(field->type_entry)) { |
| 1734 | field->gen_index = struct_type->data.structure.gen_field_count; | ||
| 1735 | struct_type->data.structure.gen_field_count += 1; | ||
| 1736 | } else { | ||
| 1737 | field->gen_index = SIZE_MAX; | ||
| 1738 | } | ||
| 1728 | 1739 | ||
| 1729 | auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field); | 1740 | auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field); |
| 1730 | assert(prev_entry == nullptr); | 1741 | assert(prev_entry == nullptr); |
| 1731 | } | 1742 | } |
| 1732 | 1743 | ||
| 1733 | struct_type->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), type_name); | 1744 | struct_type->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), type_name); |
| 1734 | LLVMStructSetBody(struct_type->type_ref, element_types, field_count, false); | 1745 | LLVMStructSetBody(struct_type->type_ref, element_types, struct_type->data.structure.gen_field_count, false); |
| 1735 | 1746 | ||
| 1736 | struct_type->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, | 1747 | struct_type->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, |
| 1737 | ZigLLVMTag_DW_structure_type(), type_name, | 1748 | ZigLLVMTag_DW_structure_type(), type_name, |
| ... | @@ -1739,11 +1750,14 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f | ... | @@ -1739,11 +1750,14 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f |
| 1739 | 1750 | ||
| 1740 | for (size_t i = 0; i < field_count; i += 1) { | 1751 | for (size_t i = 0; i < field_count; i += 1) { |
| 1741 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; | 1752 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; |
| 1753 | if (type_struct_field->gen_index == SIZE_MAX) { | ||
| 1754 | continue; | ||
| 1755 | } | ||
| 1742 | TypeTableEntry *field_type = type_struct_field->type_entry; | 1756 | TypeTableEntry *field_type = type_struct_field->type_entry; |
| 1743 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); | 1757 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); |
| 1744 | uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref); | 1758 | uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref); |
| 1745 | uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, i); | 1759 | uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, type_struct_field->gen_index); |
| 1746 | di_element_types[i] = ZigLLVMCreateDebugMemberType(g->dbuilder, | 1760 | di_element_types[type_struct_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 1747 | ZigLLVMTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name), | 1761 | ZigLLVMTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name), |
| 1748 | nullptr, 0, | 1762 | nullptr, 0, |
| 1749 | debug_size_in_bits, | 1763 | debug_size_in_bits, |
| ... | @@ -1751,7 +1765,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f | ... | @@ -1751,7 +1765,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f |
| 1751 | debug_offset_in_bits, | 1765 | debug_offset_in_bits, |
| 1752 | 0, field_type->di_type); | 1766 | 0, field_type->di_type); |
| 1753 | 1767 | ||
| 1754 | assert(di_element_types[i]); | 1768 | assert(di_element_types[type_struct_field->gen_index]); |
| 1755 | } | 1769 | } |
| 1756 | 1770 | ||
| 1757 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref); | 1771 | uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref); |
| ... | @@ -1762,7 +1776,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f | ... | @@ -1762,7 +1776,7 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f |
| 1762 | debug_size_in_bits, | 1776 | debug_size_in_bits, |
| 1763 | debug_align_in_bits, | 1777 | debug_align_in_bits, |
| 1764 | 0, | 1778 | 0, |
| 1765 | nullptr, di_element_types, field_count, 0, nullptr, ""); | 1779 | nullptr, di_element_types, struct_type->data.structure.gen_field_count, 0, nullptr, ""); |
| 1766 | 1780 | ||
| 1767 | ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type); | 1781 | ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type); |
| 1768 | struct_type->di_type = replacement_di_type; | 1782 | struct_type->di_type = replacement_di_type; |
| ... | @@ -2544,6 +2558,8 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2544,6 +2558,8 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2544 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {}; | 2558 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {}; |
| 2545 | 2559 | ||
| 2546 | AstNode *enum_type_node = decl_node->data.container_decl.init_arg_expr; | 2560 | AstNode *enum_type_node = decl_node->data.container_decl.init_arg_expr; |
| 2561 | union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum || | ||
| 2562 | enum_type_node != nullptr; | ||
| 2547 | bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto); | 2563 | bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto); |
| 2548 | bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr); | 2564 | bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr); |
| 2549 | TypeTableEntry *tag_type; | 2565 | TypeTableEntry *tag_type; |
| ... | @@ -3226,7 +3242,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { | ... | @@ -3226,7 +3242,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 3226 | case NodeTypeStructValueField: | 3242 | case NodeTypeStructValueField: |
| 3227 | case NodeTypeArrayType: | 3243 | case NodeTypeArrayType: |
| 3228 | case NodeTypeErrorType: | 3244 | case NodeTypeErrorType: |
| 3229 | case NodeTypeVarLiteral: | ||
| 3230 | case NodeTypeIfErrorExpr: | 3245 | case NodeTypeIfErrorExpr: |
| 3231 | case NodeTypeTestExpr: | 3246 | case NodeTypeTestExpr: |
| 3232 | case NodeTypeErrorSetDecl: | 3247 | case NodeTypeErrorSetDecl: |
| ... | @@ -3262,7 +3277,6 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt | ... | @@ -3262,7 +3277,6 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt |
| 3262 | case TypeTableEntryIdInvalid: | 3277 | case TypeTableEntryIdInvalid: |
| 3263 | return g->builtin_types.entry_invalid; | 3278 | return g->builtin_types.entry_invalid; |
| 3264 | case TypeTableEntryIdUnreachable: | 3279 | case TypeTableEntryIdUnreachable: |
| 3265 | case TypeTableEntryIdVar: | ||
| 3266 | case TypeTableEntryIdNumLitFloat: | 3280 | case TypeTableEntryIdNumLitFloat: |
| 3267 | case TypeTableEntryIdNumLitInt: | 3281 | case TypeTableEntryIdNumLitInt: |
| 3268 | case TypeTableEntryIdUndefLit: | 3282 | case TypeTableEntryIdUndefLit: |
| ... | @@ -3641,7 +3655,6 @@ TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *t | ... | @@ -3641,7 +3655,6 @@ TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *t |
| 3641 | static bool is_container(TypeTableEntry *type_entry) { | 3655 | static bool is_container(TypeTableEntry *type_entry) { |
| 3642 | switch (type_entry->id) { | 3656 | switch (type_entry->id) { |
| 3643 | case TypeTableEntryIdInvalid: | 3657 | case TypeTableEntryIdInvalid: |
| 3644 | case TypeTableEntryIdVar: | ||
| 3645 | zig_unreachable(); | 3658 | zig_unreachable(); |
| 3646 | case TypeTableEntryIdStruct: | 3659 | case TypeTableEntryIdStruct: |
| 3647 | case TypeTableEntryIdEnum: | 3660 | case TypeTableEntryIdEnum: |
| ... | @@ -3716,7 +3729,6 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) { | ... | @@ -3716,7 +3729,6 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) { |
| 3716 | case TypeTableEntryIdBlock: | 3729 | case TypeTableEntryIdBlock: |
| 3717 | case TypeTableEntryIdBoundFn: | 3730 | case TypeTableEntryIdBoundFn: |
| 3718 | case TypeTableEntryIdInvalid: | 3731 | case TypeTableEntryIdInvalid: |
| 3719 | case TypeTableEntryIdVar: | ||
| 3720 | case TypeTableEntryIdArgTuple: | 3732 | case TypeTableEntryIdArgTuple: |
| 3721 | case TypeTableEntryIdOpaque: | 3733 | case TypeTableEntryIdOpaque: |
| 3722 | case TypeTableEntryIdPromise: | 3734 | case TypeTableEntryIdPromise: |
| ... | @@ -3753,6 +3765,19 @@ uint32_t get_ptr_align(TypeTableEntry *type) { | ... | @@ -3753,6 +3765,19 @@ uint32_t get_ptr_align(TypeTableEntry *type) { |
| 3753 | } | 3765 | } |
| 3754 | } | 3766 | } |
| 3755 | 3767 | ||
| 3768 | bool get_ptr_const(TypeTableEntry *type) { | ||
| 3769 | TypeTableEntry *ptr_type = get_codegen_ptr_type(type); | ||
| 3770 | if (ptr_type->id == TypeTableEntryIdPointer) { | ||
| 3771 | return ptr_type->data.pointer.is_const; | ||
| 3772 | } else if (ptr_type->id == TypeTableEntryIdFn) { | ||
| 3773 | return true; | ||
| 3774 | } else if (ptr_type->id == TypeTableEntryIdPromise) { | ||
| 3775 | return true; | ||
| 3776 | } else { | ||
| 3777 | zig_unreachable(); | ||
| 3778 | } | ||
| 3779 | } | ||
| 3780 | |||
| 3756 | AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index) { | 3781 | AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index) { |
| 3757 | if (fn_entry->param_source_nodes) | 3782 | if (fn_entry->param_source_nodes) |
| 3758 | return fn_entry->param_source_nodes[index]; | 3783 | return fn_entry->param_source_nodes[index]; |
| ... | @@ -4203,7 +4228,6 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { | ... | @@ -4203,7 +4228,6 @@ bool handle_is_ptr(TypeTableEntry *type_entry) { |
| 4203 | case TypeTableEntryIdNamespace: | 4228 | case TypeTableEntryIdNamespace: |
| 4204 | case TypeTableEntryIdBlock: | 4229 | case TypeTableEntryIdBlock: |
| 4205 | case TypeTableEntryIdBoundFn: | 4230 | case TypeTableEntryIdBoundFn: |
| 4206 | case TypeTableEntryIdVar: | ||
| 4207 | case TypeTableEntryIdArgTuple: | 4231 | case TypeTableEntryIdArgTuple: |
| 4208 | case TypeTableEntryIdOpaque: | 4232 | case TypeTableEntryIdOpaque: |
| 4209 | zig_unreachable(); | 4233 | zig_unreachable(); |
| ... | @@ -4502,7 +4526,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { | ... | @@ -4502,7 +4526,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4502 | case TypeTableEntryIdBoundFn: | 4526 | case TypeTableEntryIdBoundFn: |
| 4503 | case TypeTableEntryIdInvalid: | 4527 | case TypeTableEntryIdInvalid: |
| 4504 | case TypeTableEntryIdUnreachable: | 4528 | case TypeTableEntryIdUnreachable: |
| 4505 | case TypeTableEntryIdVar: | ||
| 4506 | zig_unreachable(); | 4529 | zig_unreachable(); |
| 4507 | } | 4530 | } |
| 4508 | zig_unreachable(); | 4531 | zig_unreachable(); |
| ... | @@ -4600,7 +4623,6 @@ bool type_has_bits(TypeTableEntry *type_entry) { | ... | @@ -4600,7 +4623,6 @@ bool type_has_bits(TypeTableEntry *type_entry) { |
| 4600 | bool type_requires_comptime(TypeTableEntry *type_entry) { | 4623 | bool type_requires_comptime(TypeTableEntry *type_entry) { |
| 4601 | switch (type_entry->id) { | 4624 | switch (type_entry->id) { |
| 4602 | case TypeTableEntryIdInvalid: | 4625 | case TypeTableEntryIdInvalid: |
| 4603 | case TypeTableEntryIdVar: | ||
| 4604 | case TypeTableEntryIdOpaque: | 4626 | case TypeTableEntryIdOpaque: |
| 4605 | zig_unreachable(); | 4627 | zig_unreachable(); |
| 4606 | case TypeTableEntryIdNumLitFloat: | 4628 | case TypeTableEntryIdNumLitFloat: |
| ... | @@ -5096,7 +5118,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -5096,7 +5118,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 5096 | case TypeTableEntryIdBoundFn: | 5118 | case TypeTableEntryIdBoundFn: |
| 5097 | case TypeTableEntryIdInvalid: | 5119 | case TypeTableEntryIdInvalid: |
| 5098 | case TypeTableEntryIdUnreachable: | 5120 | case TypeTableEntryIdUnreachable: |
| 5099 | case TypeTableEntryIdVar: | ||
| 5100 | case TypeTableEntryIdPromise: | 5121 | case TypeTableEntryIdPromise: |
| 5101 | zig_unreachable(); | 5122 | zig_unreachable(); |
| 5102 | } | 5123 | } |
| ... | @@ -5176,9 +5197,6 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { | ... | @@ -5176,9 +5197,6 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5176 | case TypeTableEntryIdInvalid: | 5197 | case TypeTableEntryIdInvalid: |
| 5177 | buf_appendf(buf, "(invalid)"); | 5198 | buf_appendf(buf, "(invalid)"); |
| 5178 | return; | 5199 | return; |
| 5179 | case TypeTableEntryIdVar: | ||
| 5180 | buf_appendf(buf, "(var)"); | ||
| 5181 | return; | ||
| 5182 | case TypeTableEntryIdVoid: | 5200 | case TypeTableEntryIdVoid: |
| 5183 | buf_appendf(buf, "{}"); | 5201 | buf_appendf(buf, "{}"); |
| 5184 | return; | 5202 | return; |
| ... | @@ -5414,7 +5432,6 @@ TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) | ... | @@ -5414,7 +5432,6 @@ TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) |
| 5414 | uint32_t type_id_hash(TypeId x) { | 5432 | uint32_t type_id_hash(TypeId x) { |
| 5415 | switch (x.id) { | 5433 | switch (x.id) { |
| 5416 | case TypeTableEntryIdInvalid: | 5434 | case TypeTableEntryIdInvalid: |
| 5417 | case TypeTableEntryIdVar: | ||
| 5418 | case TypeTableEntryIdOpaque: | 5435 | case TypeTableEntryIdOpaque: |
| 5419 | case TypeTableEntryIdMetaType: | 5436 | case TypeTableEntryIdMetaType: |
| 5420 | case TypeTableEntryIdVoid: | 5437 | case TypeTableEntryIdVoid: |
| ... | @@ -5461,7 +5478,6 @@ bool type_id_eql(TypeId a, TypeId b) { | ... | @@ -5461,7 +5478,6 @@ bool type_id_eql(TypeId a, TypeId b) { |
| 5461 | return false; | 5478 | return false; |
| 5462 | switch (a.id) { | 5479 | switch (a.id) { |
| 5463 | case TypeTableEntryIdInvalid: | 5480 | case TypeTableEntryIdInvalid: |
| 5464 | case TypeTableEntryIdVar: | ||
| 5465 | case TypeTableEntryIdMetaType: | 5481 | case TypeTableEntryIdMetaType: |
| 5466 | case TypeTableEntryIdVoid: | 5482 | case TypeTableEntryIdVoid: |
| 5467 | case TypeTableEntryIdBool: | 5483 | case TypeTableEntryIdBool: |
| ... | @@ -5616,7 +5632,6 @@ size_t type_id_len() { | ... | @@ -5616,7 +5632,6 @@ size_t type_id_len() { |
| 5616 | size_t type_id_index(TypeTableEntryId id) { | 5632 | size_t type_id_index(TypeTableEntryId id) { |
| 5617 | switch (id) { | 5633 | switch (id) { |
| 5618 | case TypeTableEntryIdInvalid: | 5634 | case TypeTableEntryIdInvalid: |
| 5619 | case TypeTableEntryIdVar: | ||
| 5620 | zig_unreachable(); | 5635 | zig_unreachable(); |
| 5621 | case TypeTableEntryIdMetaType: | 5636 | case TypeTableEntryIdMetaType: |
| 5622 | return 0; | 5637 | return 0; |
| ... | @@ -5675,7 +5690,6 @@ size_t type_id_index(TypeTableEntryId id) { | ... | @@ -5675,7 +5690,6 @@ size_t type_id_index(TypeTableEntryId id) { |
| 5675 | const char *type_id_name(TypeTableEntryId id) { | 5690 | const char *type_id_name(TypeTableEntryId id) { |
| 5676 | switch (id) { | 5691 | switch (id) { |
| 5677 | case TypeTableEntryIdInvalid: | 5692 | case TypeTableEntryIdInvalid: |
| 5678 | case TypeTableEntryIdVar: | ||
| 5679 | zig_unreachable(); | 5693 | zig_unreachable(); |
| 5680 | case TypeTableEntryIdMetaType: | 5694 | case TypeTableEntryIdMetaType: |
| 5681 | return "Type"; | 5695 | return "Type"; |
src/analyze.hpp+1| ... | @@ -55,6 +55,7 @@ bool type_is_codegen_pointer(TypeTableEntry *type); | ... | @@ -55,6 +55,7 @@ bool type_is_codegen_pointer(TypeTableEntry *type); |
| 55 | 55 | ||
| 56 | TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type); | 56 | TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type); |
| 57 | uint32_t get_ptr_align(TypeTableEntry *type); | 57 | uint32_t get_ptr_align(TypeTableEntry *type); |
| 58 | bool get_ptr_const(TypeTableEntry *type); | ||
| 58 | TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry); | 59 | TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry); |
| 59 | TypeTableEntry *container_ref_type(TypeTableEntry *type_entry); | 60 | TypeTableEntry *container_ref_type(TypeTableEntry *type_entry); |
| 60 | bool type_is_complete(TypeTableEntry *type_entry); | 61 | bool type_is_complete(TypeTableEntry *type_entry); |
src/ast_render.cpp+16-12| ... | @@ -236,8 +236,6 @@ static const char *node_type_str(NodeType node_type) { | ... | @@ -236,8 +236,6 @@ static const char *node_type_str(NodeType node_type) { |
| 236 | return "ArrayType"; | 236 | return "ArrayType"; |
| 237 | case NodeTypeErrorType: | 237 | case NodeTypeErrorType: |
| 238 | return "ErrorType"; | 238 | return "ErrorType"; |
| 239 | case NodeTypeVarLiteral: | ||
| 240 | return "VarLiteral"; | ||
| 241 | case NodeTypeIfErrorExpr: | 239 | case NodeTypeIfErrorExpr: |
| 242 | return "IfErrorExpr"; | 240 | return "IfErrorExpr"; |
| 243 | case NodeTypeTestExpr: | 241 | case NodeTypeTestExpr: |
| ... | @@ -436,6 +434,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -436,6 +434,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 436 | } | 434 | } |
| 437 | if (param_decl->data.param_decl.is_var_args) { | 435 | if (param_decl->data.param_decl.is_var_args) { |
| 438 | fprintf(ar->f, "..."); | 436 | fprintf(ar->f, "..."); |
| 437 | } else if (param_decl->data.param_decl.var_token != nullptr) { | ||
| 438 | fprintf(ar->f, "var"); | ||
| 439 | } else { | 439 | } else { |
| 440 | render_node_grouped(ar, param_decl->data.param_decl.type); | 440 | render_node_grouped(ar, param_decl->data.param_decl.type); |
| 441 | } | 441 | } |
| ... | @@ -456,13 +456,17 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -456,13 +456,17 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 456 | fprintf(ar->f, ")"); | 456 | fprintf(ar->f, ")"); |
| 457 | } | 457 | } |
| 458 | 458 | ||
| 459 | AstNode *return_type_node = node->data.fn_proto.return_type; | 459 | if (node->data.fn_proto.return_var_token != nullptr) { |
| 460 | assert(return_type_node != nullptr); | 460 | fprintf(ar->f, "var"); |
| 461 | fprintf(ar->f, " "); | 461 | } else { |
| 462 | if (node->data.fn_proto.auto_err_set) { | 462 | AstNode *return_type_node = node->data.fn_proto.return_type; |
| 463 | fprintf(ar->f, "!"); | 463 | assert(return_type_node != nullptr); |
| 464 | fprintf(ar->f, " "); | ||
| 465 | if (node->data.fn_proto.auto_err_set) { | ||
| 466 | fprintf(ar->f, "!"); | ||
| 467 | } | ||
| 468 | render_node_grouped(ar, return_type_node); | ||
| 464 | } | 469 | } |
| 465 | render_node_grouped(ar, return_type_node); | ||
| 466 | break; | 470 | break; |
| 467 | } | 471 | } |
| 468 | case NodeTypeFnDef: | 472 | case NodeTypeFnDef: |
| ... | @@ -486,7 +490,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -486,7 +490,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 486 | AstNode *statement = node->data.block.statements.at(i); | 490 | AstNode *statement = node->data.block.statements.at(i); |
| 487 | print_indent(ar); | 491 | print_indent(ar); |
| 488 | render_node_grouped(ar, statement); | 492 | render_node_grouped(ar, statement); |
| 489 | fprintf(ar->f, ";"); | 493 | |
| 494 | if (!statement_terminates_without_semicolon(statement)) | ||
| 495 | fprintf(ar->f, ";"); | ||
| 496 | |||
| 490 | fprintf(ar->f, "\n"); | 497 | fprintf(ar->f, "\n"); |
| 491 | } | 498 | } |
| 492 | ar->indent -= ar->indent_size; | 499 | ar->indent -= ar->indent_size; |
| ... | @@ -768,9 +775,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -768,9 +775,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 768 | case NodeTypeErrorType: | 775 | case NodeTypeErrorType: |
| 769 | fprintf(ar->f, "error"); | 776 | fprintf(ar->f, "error"); |
| 770 | break; | 777 | break; |
| 771 | case NodeTypeVarLiteral: | ||
| 772 | fprintf(ar->f, "var"); | ||
| 773 | break; | ||
| 774 | case NodeTypeAsmExpr: | 778 | case NodeTypeAsmExpr: |
| 775 | { | 779 | { |
| 776 | AstNodeAsmExpr *asm_expr = &node->data.asm_expr; | 780 | AstNodeAsmExpr *asm_expr = &node->data.asm_expr; |
src/codegen.cpp-10| ... | @@ -4508,7 +4508,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con | ... | @@ -4508,7 +4508,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con |
| 4508 | assert(!type_entry->zero_bits); | 4508 | assert(!type_entry->zero_bits); |
| 4509 | switch (type_entry->id) { | 4509 | switch (type_entry->id) { |
| 4510 | case TypeTableEntryIdInvalid: | 4510 | case TypeTableEntryIdInvalid: |
| 4511 | case TypeTableEntryIdVar: | ||
| 4512 | case TypeTableEntryIdMetaType: | 4511 | case TypeTableEntryIdMetaType: |
| 4513 | case TypeTableEntryIdUnreachable: | 4512 | case TypeTableEntryIdUnreachable: |
| 4514 | case TypeTableEntryIdNumLitFloat: | 4513 | case TypeTableEntryIdNumLitFloat: |
| ... | @@ -4960,7 +4959,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c | ... | @@ -4960,7 +4959,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 4960 | case TypeTableEntryIdNamespace: | 4959 | case TypeTableEntryIdNamespace: |
| 4961 | case TypeTableEntryIdBlock: | 4960 | case TypeTableEntryIdBlock: |
| 4962 | case TypeTableEntryIdBoundFn: | 4961 | case TypeTableEntryIdBoundFn: |
| 4963 | case TypeTableEntryIdVar: | ||
| 4964 | case TypeTableEntryIdArgTuple: | 4962 | case TypeTableEntryIdArgTuple: |
| 4965 | case TypeTableEntryIdOpaque: | 4963 | case TypeTableEntryIdOpaque: |
| 4966 | case TypeTableEntryIdPromise: | 4964 | case TypeTableEntryIdPromise: |
| ... | @@ -5611,11 +5609,6 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -5611,11 +5609,6 @@ static void define_builtin_types(CodeGen *g) { |
| 5611 | entry->zero_bits = true; | 5609 | entry->zero_bits = true; |
| 5612 | g->builtin_types.entry_null = entry; | 5610 | g->builtin_types.entry_null = entry; |
| 5613 | } | 5611 | } |
| 5614 | { | ||
| 5615 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVar); | ||
| 5616 | buf_init_from_str(&entry->name, "(var)"); | ||
| 5617 | g->builtin_types.entry_var = entry; | ||
| 5618 | } | ||
| 5619 | { | 5612 | { |
| 5620 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArgTuple); | 5613 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArgTuple); |
| 5621 | buf_init_from_str(&entry->name, "(args)"); | 5614 | buf_init_from_str(&entry->name, "(args)"); |
| ... | @@ -6444,7 +6437,6 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry | ... | @@ -6444,7 +6437,6 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry |
| 6444 | 6437 | ||
| 6445 | switch (type_entry->id) { | 6438 | switch (type_entry->id) { |
| 6446 | case TypeTableEntryIdInvalid: | 6439 | case TypeTableEntryIdInvalid: |
| 6447 | case TypeTableEntryIdVar: | ||
| 6448 | case TypeTableEntryIdMetaType: | 6440 | case TypeTableEntryIdMetaType: |
| 6449 | case TypeTableEntryIdNumLitFloat: | 6441 | case TypeTableEntryIdNumLitFloat: |
| 6450 | case TypeTableEntryIdNumLitInt: | 6442 | case TypeTableEntryIdNumLitInt: |
| ... | @@ -6639,7 +6631,6 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf | ... | @@ -6639,7 +6631,6 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf |
| 6639 | case TypeTableEntryIdNumLitInt: | 6631 | case TypeTableEntryIdNumLitInt: |
| 6640 | case TypeTableEntryIdUndefLit: | 6632 | case TypeTableEntryIdUndefLit: |
| 6641 | case TypeTableEntryIdNullLit: | 6633 | case TypeTableEntryIdNullLit: |
| 6642 | case TypeTableEntryIdVar: | ||
| 6643 | case TypeTableEntryIdArgTuple: | 6634 | case TypeTableEntryIdArgTuple: |
| 6644 | case TypeTableEntryIdPromise: | 6635 | case TypeTableEntryIdPromise: |
| 6645 | zig_unreachable(); | 6636 | zig_unreachable(); |
| ... | @@ -6781,7 +6772,6 @@ static void gen_h_file(CodeGen *g) { | ... | @@ -6781,7 +6772,6 @@ static void gen_h_file(CodeGen *g) { |
| 6781 | TypeTableEntry *type_entry = gen_h->types_to_declare.at(type_i); | 6772 | TypeTableEntry *type_entry = gen_h->types_to_declare.at(type_i); |
| 6782 | switch (type_entry->id) { | 6773 | switch (type_entry->id) { |
| 6783 | case TypeTableEntryIdInvalid: | 6774 | case TypeTableEntryIdInvalid: |
| 6784 | case TypeTableEntryIdVar: | ||
| 6785 | case TypeTableEntryIdMetaType: | 6775 | case TypeTableEntryIdMetaType: |
| 6786 | case TypeTableEntryIdVoid: | 6776 | case TypeTableEntryIdVoid: |
| 6787 | case TypeTableEntryIdBool: | 6777 | case TypeTableEntryIdBool: |
src/ir.cpp+80-92| ... | @@ -948,12 +948,10 @@ static IrInstruction *ir_build_const_promise_init(IrBuilder *irb, Scope *scope, | ... | @@ -948,12 +948,10 @@ static IrInstruction *ir_build_const_promise_init(IrBuilder *irb, Scope *scope, |
| 948 | const_instruction->base.value.data.x_struct.fields[0].type = struct_type->data.structure.fields[0].type_entry; | 948 | const_instruction->base.value.data.x_struct.fields[0].type = struct_type->data.structure.fields[0].type_entry; |
| 949 | const_instruction->base.value.data.x_struct.fields[0].special = ConstValSpecialStatic; | 949 | const_instruction->base.value.data.x_struct.fields[0].special = ConstValSpecialStatic; |
| 950 | const_instruction->base.value.data.x_struct.fields[0].data.x_maybe = nullptr; | 950 | const_instruction->base.value.data.x_struct.fields[0].data.x_maybe = nullptr; |
| 951 | if (struct_type->data.structure.src_field_count > 1) { | 951 | const_instruction->base.value.data.x_struct.fields[1].type = return_type; |
| 952 | const_instruction->base.value.data.x_struct.fields[1].type = return_type; | 952 | const_instruction->base.value.data.x_struct.fields[1].special = ConstValSpecialUndef; |
| 953 | const_instruction->base.value.data.x_struct.fields[1].special = ConstValSpecialUndef; | 953 | const_instruction->base.value.data.x_struct.fields[2].type = struct_type->data.structure.fields[2].type_entry; |
| 954 | const_instruction->base.value.data.x_struct.fields[2].type = struct_type->data.structure.fields[2].type_entry; | 954 | const_instruction->base.value.data.x_struct.fields[2].special = ConstValSpecialUndef; |
| 955 | const_instruction->base.value.data.x_struct.fields[2].special = ConstValSpecialUndef; | ||
| 956 | } | ||
| 957 | return &const_instruction->base; | 955 | return &const_instruction->base; |
| 958 | } | 956 | } |
| 959 | 957 | ||
| ... | @@ -2147,7 +2145,7 @@ static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *s | ... | @@ -2147,7 +2145,7 @@ static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *s |
| 2147 | size_t param_count = source_node->data.fn_proto.params.length; | 2145 | size_t param_count = source_node->data.fn_proto.params.length; |
| 2148 | if (is_var_args) param_count -= 1; | 2146 | if (is_var_args) param_count -= 1; |
| 2149 | for (size_t i = 0; i < param_count; i += 1) { | 2147 | for (size_t i = 0; i < param_count; i += 1) { |
| 2150 | ir_ref_instruction(param_types[i], irb->current_basic_block); | 2148 | if (param_types[i] != nullptr) ir_ref_instruction(param_types[i], irb->current_basic_block); |
| 2151 | } | 2149 | } |
| 2152 | if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); | 2150 | if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); |
| 2153 | ir_ref_instruction(return_type, irb->current_basic_block); | 2151 | ir_ref_instruction(return_type, irb->current_basic_block); |
| ... | @@ -2741,10 +2739,8 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -2741,10 +2739,8 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode |
| 2741 | return return_inst; | 2739 | return return_inst; |
| 2742 | } | 2740 | } |
| 2743 | 2741 | ||
| 2744 | if (irb->exec->coro_result_ptr_field_ptr) { | 2742 | IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr); |
| 2745 | IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr); | 2743 | ir_build_store_ptr(irb, scope, node, result_ptr, return_value); |
| 2746 | ir_build_store_ptr(irb, scope, node, result_ptr, return_value); | ||
| 2747 | } | ||
| 2748 | IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node, | 2744 | IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node, |
| 2749 | get_maybe_type(irb->codegen, irb->codegen->builtin_types.entry_promise)); | 2745 | get_maybe_type(irb->codegen, irb->codegen->builtin_types.entry_promise)); |
| 2750 | // TODO replace replacement_value with @intToPtr(?promise, 0x1) when it doesn't crash zig | 2746 | // TODO replace replacement_value with @intToPtr(?promise, 0x1) when it doesn't crash zig |
| ... | @@ -3305,12 +3301,6 @@ static IrInstruction *ir_gen_null_literal(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -3305,12 +3301,6 @@ static IrInstruction *ir_gen_null_literal(IrBuilder *irb, Scope *scope, AstNode |
| 3305 | return ir_build_const_null(irb, scope, node); | 3301 | return ir_build_const_null(irb, scope, node); |
| 3306 | } | 3302 | } |
| 3307 | 3303 | ||
| 3308 | static IrInstruction *ir_gen_var_literal(IrBuilder *irb, Scope *scope, AstNode *node) { | ||
| 3309 | assert(node->type == NodeTypeVarLiteral); | ||
| 3310 | |||
| 3311 | return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_var); | ||
| 3312 | } | ||
| 3313 | |||
| 3314 | static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { | 3304 | static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) { |
| 3315 | assert(node->type == NodeTypeSymbol); | 3305 | assert(node->type == NodeTypeSymbol); |
| 3316 | 3306 | ||
| ... | @@ -5916,11 +5906,15 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -5916,11 +5906,15 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5916 | is_var_args = true; | 5906 | is_var_args = true; |
| 5917 | break; | 5907 | break; |
| 5918 | } | 5908 | } |
| 5919 | AstNode *type_node = param_node->data.param_decl.type; | 5909 | if (param_node->data.param_decl.var_token == nullptr) { |
| 5920 | IrInstruction *type_value = ir_gen_node(irb, type_node, parent_scope); | 5910 | AstNode *type_node = param_node->data.param_decl.type; |
| 5921 | if (type_value == irb->codegen->invalid_instruction) | 5911 | IrInstruction *type_value = ir_gen_node(irb, type_node, parent_scope); |
| 5922 | return irb->codegen->invalid_instruction; | 5912 | if (type_value == irb->codegen->invalid_instruction) |
| 5923 | param_types[i] = type_value; | 5913 | return irb->codegen->invalid_instruction; |
| 5914 | param_types[i] = type_value; | ||
| 5915 | } else { | ||
| 5916 | param_types[i] = nullptr; | ||
| 5917 | } | ||
| 5924 | } | 5918 | } |
| 5925 | 5919 | ||
| 5926 | IrInstruction *align_value = nullptr; | 5920 | IrInstruction *align_value = nullptr; |
| ... | @@ -5931,12 +5925,16 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -5931,12 +5925,16 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5931 | } | 5925 | } |
| 5932 | 5926 | ||
| 5933 | IrInstruction *return_type; | 5927 | IrInstruction *return_type; |
| 5934 | if (node->data.fn_proto.return_type == nullptr) { | 5928 | if (node->data.fn_proto.return_var_token == nullptr) { |
| 5935 | return_type = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_void); | 5929 | if (node->data.fn_proto.return_type == nullptr) { |
| 5930 | return_type = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_void); | ||
| 5931 | } else { | ||
| 5932 | return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope); | ||
| 5933 | if (return_type == irb->codegen->invalid_instruction) | ||
| 5934 | return irb->codegen->invalid_instruction; | ||
| 5935 | } | ||
| 5936 | } else { | 5936 | } else { |
| 5937 | return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope); | 5937 | return_type = nullptr; |
| 5938 | if (return_type == irb->codegen->invalid_instruction) | ||
| 5939 | return irb->codegen->invalid_instruction; | ||
| 5940 | } | 5938 | } |
| 5941 | 5939 | ||
| 5942 | return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, return_type, is_var_args); | 5940 | return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, return_type, is_var_args); |
| ... | @@ -6189,8 +6187,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop | ... | @@ -6189,8 +6187,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 6189 | return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval); | 6187 | return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval); |
| 6190 | case NodeTypeNullLiteral: | 6188 | case NodeTypeNullLiteral: |
| 6191 | return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval); | 6189 | return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval); |
| 6192 | case NodeTypeVarLiteral: | ||
| 6193 | return ir_lval_wrap(irb, scope, ir_gen_var_literal(irb, scope, node), lval); | ||
| 6194 | case NodeTypeIfErrorExpr: | 6190 | case NodeTypeIfErrorExpr: |
| 6195 | return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval); | 6191 | return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval); |
| 6196 | case NodeTypeTestExpr: | 6192 | case NodeTypeTestExpr: |
| ... | @@ -6328,14 +6324,11 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec | ... | @@ -6328,14 +6324,11 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 6328 | Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME); | 6324 | Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME); |
| 6329 | irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, | 6325 | irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, |
| 6330 | awaiter_handle_field_name); | 6326 | awaiter_handle_field_name); |
| 6331 | if (type_has_bits(return_type)) { | 6327 | Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME); |
| 6332 | Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME); | 6328 | coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name); |
| 6333 | coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name); | 6329 | result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME); |
| 6334 | result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME); | 6330 | irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name); |
| 6335 | irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, | 6331 | ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, coro_result_field_ptr); |
| 6336 | result_ptr_field_name); | ||
| 6337 | ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, coro_result_field_ptr); | ||
| 6338 | } | ||
| 6339 | 6332 | ||
| 6340 | 6333 | ||
| 6341 | irb->exec->coro_early_final = ir_create_basic_block(irb, scope, "CoroEarlyFinal"); | 6334 | irb->exec->coro_early_final = ir_create_basic_block(irb, scope, "CoroEarlyFinal"); |
| ... | @@ -7515,11 +7508,6 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, | ... | @@ -7515,11 +7508,6 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, |
| 7515 | return ImplicitCastMatchResultReportedError; | 7508 | return ImplicitCastMatchResultReportedError; |
| 7516 | } | 7509 | } |
| 7517 | 7510 | ||
| 7518 | // implicit conversion from anything to var | ||
| 7519 | if (expected_type->id == TypeTableEntryIdVar) { | ||
| 7520 | return ImplicitCastMatchResultYes; | ||
| 7521 | } | ||
| 7522 | |||
| 7523 | // implicit conversion from non maybe type to maybe type | 7511 | // implicit conversion from non maybe type to maybe type |
| 7524 | if (expected_type->id == TypeTableEntryIdMaybe && | 7512 | if (expected_type->id == TypeTableEntryIdMaybe && |
| 7525 | ir_types_match_with_implicit_cast(ira, expected_type->data.maybe.child_type, actual_type, value)) | 7513 | ir_types_match_with_implicit_cast(ira, expected_type->data.maybe.child_type, actual_type, value)) |
| ... | @@ -9341,9 +9329,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -9341,9 +9329,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 9341 | return ira->codegen->invalid_instruction; | 9329 | return ira->codegen->invalid_instruction; |
| 9342 | } | 9330 | } |
| 9343 | 9331 | ||
| 9344 | if (wanted_type->id == TypeTableEntryIdVar) | ||
| 9345 | return value; | ||
| 9346 | |||
| 9347 | // explicit match or non-const to const | 9332 | // explicit match or non-const to const |
| 9348 | if (types_match_const_cast_only(ira, wanted_type, actual_type, source_node).id == ConstCastResultIdOk) { | 9333 | if (types_match_const_cast_only(ira, wanted_type, actual_type, source_node).id == ConstCastResultIdOk) { |
| 9349 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false); | 9334 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false); |
| ... | @@ -10311,9 +10296,6 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -10311,9 +10296,6 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 10311 | ir_add_error_node(ira, source_node, | 10296 | ir_add_error_node(ira, source_node, |
| 10312 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); | 10297 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); |
| 10313 | return ira->codegen->builtin_types.entry_invalid; | 10298 | return ira->codegen->builtin_types.entry_invalid; |
| 10314 | |||
| 10315 | case TypeTableEntryIdVar: | ||
| 10316 | zig_unreachable(); | ||
| 10317 | } | 10299 | } |
| 10318 | 10300 | ||
| 10319 | IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, resolved_type); | 10301 | IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, resolved_type); |
| ... | @@ -11106,7 +11088,6 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) { | ... | @@ -11106,7 +11088,6 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) { |
| 11106 | case TypeTableEntryIdInvalid: | 11088 | case TypeTableEntryIdInvalid: |
| 11107 | zig_unreachable(); | 11089 | zig_unreachable(); |
| 11108 | case TypeTableEntryIdUnreachable: | 11090 | case TypeTableEntryIdUnreachable: |
| 11109 | case TypeTableEntryIdVar: | ||
| 11110 | return VarClassRequiredIllegal; | 11091 | return VarClassRequiredIllegal; |
| 11111 | case TypeTableEntryIdBool: | 11092 | case TypeTableEntryIdBool: |
| 11112 | case TypeTableEntryIdInt: | 11093 | case TypeTableEntryIdInt: |
| ... | @@ -11279,7 +11260,6 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi | ... | @@ -11279,7 +11260,6 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi |
| 11279 | 11260 | ||
| 11280 | switch (target->value.type->id) { | 11261 | switch (target->value.type->id) { |
| 11281 | case TypeTableEntryIdInvalid: | 11262 | case TypeTableEntryIdInvalid: |
| 11282 | case TypeTableEntryIdVar: | ||
| 11283 | case TypeTableEntryIdUnreachable: | 11263 | case TypeTableEntryIdUnreachable: |
| 11284 | zig_unreachable(); | 11264 | zig_unreachable(); |
| 11285 | case TypeTableEntryIdFn: { | 11265 | case TypeTableEntryIdFn: { |
| ... | @@ -11332,7 +11312,6 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi | ... | @@ -11332,7 +11312,6 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi |
| 11332 | TypeTableEntry *type_value = target->value.data.x_type; | 11312 | TypeTableEntry *type_value = target->value.data.x_type; |
| 11333 | switch (type_value->id) { | 11313 | switch (type_value->id) { |
| 11334 | case TypeTableEntryIdInvalid: | 11314 | case TypeTableEntryIdInvalid: |
| 11335 | case TypeTableEntryIdVar: | ||
| 11336 | zig_unreachable(); | 11315 | zig_unreachable(); |
| 11337 | case TypeTableEntryIdStruct: | 11316 | case TypeTableEntryIdStruct: |
| 11338 | if (is_slice(type_value)) { | 11317 | if (is_slice(type_value)) { |
| ... | @@ -11543,14 +11522,20 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node | ... | @@ -11543,14 +11522,20 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node |
| 11543 | { | 11522 | { |
| 11544 | AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(*next_proto_i); | 11523 | AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(*next_proto_i); |
| 11545 | assert(param_decl_node->type == NodeTypeParamDecl); | 11524 | assert(param_decl_node->type == NodeTypeParamDecl); |
| 11546 | AstNode *param_type_node = param_decl_node->data.param_decl.type; | ||
| 11547 | TypeTableEntry *param_type = analyze_type_expr(ira->codegen, *exec_scope, param_type_node); | ||
| 11548 | if (type_is_invalid(param_type)) | ||
| 11549 | return false; | ||
| 11550 | 11525 | ||
| 11551 | IrInstruction *casted_arg = ir_implicit_cast(ira, arg, param_type); | 11526 | IrInstruction *casted_arg; |
| 11552 | if (type_is_invalid(casted_arg->value.type)) | 11527 | if (param_decl_node->data.param_decl.var_token == nullptr) { |
| 11553 | return false; | 11528 | AstNode *param_type_node = param_decl_node->data.param_decl.type; |
| 11529 | TypeTableEntry *param_type = analyze_type_expr(ira->codegen, *exec_scope, param_type_node); | ||
| 11530 | if (type_is_invalid(param_type)) | ||
| 11531 | return false; | ||
| 11532 | |||
| 11533 | casted_arg = ir_implicit_cast(ira, arg, param_type); | ||
| 11534 | if (type_is_invalid(casted_arg->value.type)) | ||
| 11535 | return false; | ||
| 11536 | } else { | ||
| 11537 | casted_arg = arg; | ||
| 11538 | } | ||
| 11554 | 11539 | ||
| 11555 | ConstExprValue *arg_val = ir_resolve_const(ira, casted_arg, UndefBad); | 11540 | ConstExprValue *arg_val = ir_resolve_const(ira, casted_arg, UndefBad); |
| 11556 | if (!arg_val) | 11541 | if (!arg_val) |
| ... | @@ -11579,19 +11564,18 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod | ... | @@ -11579,19 +11564,18 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod |
| 11579 | arg_part_of_generic_id = true; | 11564 | arg_part_of_generic_id = true; |
| 11580 | casted_arg = ir_implicit_byval_const_ref_cast(ira, arg); | 11565 | casted_arg = ir_implicit_byval_const_ref_cast(ira, arg); |
| 11581 | } else { | 11566 | } else { |
| 11582 | AstNode *param_type_node = param_decl_node->data.param_decl.type; | 11567 | if (param_decl_node->data.param_decl.var_token == nullptr) { |
| 11583 | TypeTableEntry *param_type = analyze_type_expr(ira->codegen, *child_scope, param_type_node); | 11568 | AstNode *param_type_node = param_decl_node->data.param_decl.type; |
| 11584 | if (type_is_invalid(param_type)) | 11569 | TypeTableEntry *param_type = analyze_type_expr(ira->codegen, *child_scope, param_type_node); |
| 11585 | return false; | 11570 | if (type_is_invalid(param_type)) |
| 11571 | return false; | ||
| 11586 | 11572 | ||
| 11587 | bool is_var_type = (param_type->id == TypeTableEntryIdVar); | ||
| 11588 | if (is_var_type) { | ||
| 11589 | arg_part_of_generic_id = true; | ||
| 11590 | casted_arg = ir_implicit_byval_const_ref_cast(ira, arg); | ||
| 11591 | } else { | ||
| 11592 | casted_arg = ir_implicit_cast(ira, arg, param_type); | 11573 | casted_arg = ir_implicit_cast(ira, arg, param_type); |
| 11593 | if (type_is_invalid(casted_arg->value.type)) | 11574 | if (type_is_invalid(casted_arg->value.type)) |
| 11594 | return false; | 11575 | return false; |
| 11576 | } else { | ||
| 11577 | arg_part_of_generic_id = true; | ||
| 11578 | casted_arg = ir_implicit_byval_const_ref_cast(ira, arg); | ||
| 11595 | } | 11579 | } |
| 11596 | } | 11580 | } |
| 11597 | 11581 | ||
| ... | @@ -12028,7 +12012,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -12028,7 +12012,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 12028 | inst_fn_type_id.alignment = align_bytes; | 12012 | inst_fn_type_id.alignment = align_bytes; |
| 12029 | } | 12013 | } |
| 12030 | 12014 | ||
| 12031 | { | 12015 | if (fn_proto_node->data.fn_proto.return_var_token == nullptr) { |
| 12032 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; | 12016 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; |
| 12033 | TypeTableEntry *specified_return_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, return_type_node); | 12017 | TypeTableEntry *specified_return_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, return_type_node); |
| 12034 | if (type_is_invalid(specified_return_type)) | 12018 | if (type_is_invalid(specified_return_type)) |
| ... | @@ -12304,7 +12288,6 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op | ... | @@ -12304,7 +12288,6 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op |
| 12304 | return ira->codegen->builtin_types.entry_invalid; | 12288 | return ira->codegen->builtin_types.entry_invalid; |
| 12305 | switch (type_entry->id) { | 12289 | switch (type_entry->id) { |
| 12306 | case TypeTableEntryIdInvalid: | 12290 | case TypeTableEntryIdInvalid: |
| 12307 | case TypeTableEntryIdVar: | ||
| 12308 | zig_unreachable(); | 12291 | zig_unreachable(); |
| 12309 | case TypeTableEntryIdMetaType: | 12292 | case TypeTableEntryIdMetaType: |
| 12310 | case TypeTableEntryIdVoid: | 12293 | case TypeTableEntryIdVoid: |
| ... | @@ -13539,10 +13522,6 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi | ... | @@ -13539,10 +13522,6 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi |
| 13539 | switch (type_entry->id) { | 13522 | switch (type_entry->id) { |
| 13540 | case TypeTableEntryIdInvalid: | 13523 | case TypeTableEntryIdInvalid: |
| 13541 | zig_unreachable(); // handled above | 13524 | zig_unreachable(); // handled above |
| 13542 | case TypeTableEntryIdVar: | ||
| 13543 | ir_add_error_node(ira, expr_value->source_node, | ||
| 13544 | buf_sprintf("type '%s' not eligible for @typeOf", buf_ptr(&type_entry->name))); | ||
| 13545 | return ira->codegen->builtin_types.entry_invalid; | ||
| 13546 | case TypeTableEntryIdNumLitFloat: | 13525 | case TypeTableEntryIdNumLitFloat: |
| 13547 | case TypeTableEntryIdNumLitInt: | 13526 | case TypeTableEntryIdNumLitInt: |
| 13548 | case TypeTableEntryIdUndefLit: | 13527 | case TypeTableEntryIdUndefLit: |
| ... | @@ -13807,7 +13786,6 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, | ... | @@ -13807,7 +13786,6 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira, |
| 13807 | switch (child_type->id) { | 13786 | switch (child_type->id) { |
| 13808 | case TypeTableEntryIdInvalid: // handled above | 13787 | case TypeTableEntryIdInvalid: // handled above |
| 13809 | zig_unreachable(); | 13788 | zig_unreachable(); |
| 13810 | case TypeTableEntryIdVar: | ||
| 13811 | case TypeTableEntryIdUnreachable: | 13789 | case TypeTableEntryIdUnreachable: |
| 13812 | case TypeTableEntryIdUndefLit: | 13790 | case TypeTableEntryIdUndefLit: |
| 13813 | case TypeTableEntryIdNullLit: | 13791 | case TypeTableEntryIdNullLit: |
| ... | @@ -13916,7 +13894,6 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira, | ... | @@ -13916,7 +13894,6 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira, |
| 13916 | switch (child_type->id) { | 13894 | switch (child_type->id) { |
| 13917 | case TypeTableEntryIdInvalid: // handled above | 13895 | case TypeTableEntryIdInvalid: // handled above |
| 13918 | zig_unreachable(); | 13896 | zig_unreachable(); |
| 13919 | case TypeTableEntryIdVar: | ||
| 13920 | case TypeTableEntryIdUnreachable: | 13897 | case TypeTableEntryIdUnreachable: |
| 13921 | case TypeTableEntryIdUndefLit: | 13898 | case TypeTableEntryIdUndefLit: |
| 13922 | case TypeTableEntryIdNullLit: | 13899 | case TypeTableEntryIdNullLit: |
| ... | @@ -13968,7 +13945,6 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, | ... | @@ -13968,7 +13945,6 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 13968 | switch (type_entry->id) { | 13945 | switch (type_entry->id) { |
| 13969 | case TypeTableEntryIdInvalid: // handled above | 13946 | case TypeTableEntryIdInvalid: // handled above |
| 13970 | zig_unreachable(); | 13947 | zig_unreachable(); |
| 13971 | case TypeTableEntryIdVar: | ||
| 13972 | case TypeTableEntryIdUnreachable: | 13948 | case TypeTableEntryIdUnreachable: |
| 13973 | case TypeTableEntryIdUndefLit: | 13949 | case TypeTableEntryIdUndefLit: |
| 13974 | case TypeTableEntryIdNullLit: | 13950 | case TypeTableEntryIdNullLit: |
| ... | @@ -14161,6 +14137,14 @@ static IrInstruction *ir_analyze_union_tag(IrAnalyze *ira, IrInstruction *source | ... | @@ -14161,6 +14137,14 @@ static IrInstruction *ir_analyze_union_tag(IrAnalyze *ira, IrInstruction *source |
| 14161 | buf_sprintf("expected enum or union type, found '%s'", buf_ptr(&value->value.type->name))); | 14137 | buf_sprintf("expected enum or union type, found '%s'", buf_ptr(&value->value.type->name))); |
| 14162 | return ira->codegen->invalid_instruction; | 14138 | return ira->codegen->invalid_instruction; |
| 14163 | } | 14139 | } |
| 14140 | if (!value->value.type->data.unionation.have_explicit_tag_type && !source_instr->is_gen) { | ||
| 14141 | ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("union has no associated enum")); | ||
| 14142 | if (value->value.type->data.unionation.decl_node != nullptr) { | ||
| 14143 | add_error_note(ira->codegen, msg, value->value.type->data.unionation.decl_node, | ||
| 14144 | buf_sprintf("declared here")); | ||
| 14145 | } | ||
| 14146 | return ira->codegen->invalid_instruction; | ||
| 14147 | } | ||
| 14164 | 14148 | ||
| 14165 | TypeTableEntry *tag_type = value->value.type->data.unionation.tag_type; | 14149 | TypeTableEntry *tag_type = value->value.type->data.unionation.tag_type; |
| 14166 | assert(tag_type->id == TypeTableEntryIdEnum); | 14150 | assert(tag_type->id == TypeTableEntryIdEnum); |
| ... | @@ -14316,7 +14300,6 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -14316,7 +14300,6 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 14316 | 14300 | ||
| 14317 | switch (target_type->id) { | 14301 | switch (target_type->id) { |
| 14318 | case TypeTableEntryIdInvalid: | 14302 | case TypeTableEntryIdInvalid: |
| 14319 | case TypeTableEntryIdVar: | ||
| 14320 | zig_unreachable(); | 14303 | zig_unreachable(); |
| 14321 | case TypeTableEntryIdMetaType: | 14304 | case TypeTableEntryIdMetaType: |
| 14322 | case TypeTableEntryIdVoid: | 14305 | case TypeTableEntryIdVoid: |
| ... | @@ -14911,7 +14894,6 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -14911,7 +14894,6 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_ |
| 14911 | } | 14894 | } |
| 14912 | case TypeTableEntryIdEnum: | 14895 | case TypeTableEntryIdEnum: |
| 14913 | zig_panic("TODO min/max value for enum type"); | 14896 | zig_panic("TODO min/max value for enum type"); |
| 14914 | case TypeTableEntryIdVar: | ||
| 14915 | case TypeTableEntryIdMetaType: | 14897 | case TypeTableEntryIdMetaType: |
| 14916 | case TypeTableEntryIdUnreachable: | 14898 | case TypeTableEntryIdUnreachable: |
| 14917 | case TypeTableEntryIdPointer: | 14899 | case TypeTableEntryIdPointer: |
| ... | @@ -15821,9 +15803,13 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio | ... | @@ -15821,9 +15803,13 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 15821 | TypeTableEntry *return_type; | 15803 | TypeTableEntry *return_type; |
| 15822 | 15804 | ||
| 15823 | if (array_type->id == TypeTableEntryIdArray) { | 15805 | if (array_type->id == TypeTableEntryIdArray) { |
| 15806 | uint32_t byte_alignment = ptr_type->data.pointer.alignment; | ||
| 15807 | if (array_type->data.array.len == 0 && byte_alignment == 0) { | ||
| 15808 | byte_alignment = get_abi_alignment(ira->codegen, array_type->data.array.child_type); | ||
| 15809 | } | ||
| 15824 | TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type, | 15810 | TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type, |
| 15825 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | 15811 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, |
| 15826 | ptr_type->data.pointer.alignment, 0, 0); | 15812 | byte_alignment, 0, 0); |
| 15827 | return_type = get_slice_type(ira->codegen, slice_ptr_type); | 15813 | return_type = get_slice_type(ira->codegen, slice_ptr_type); |
| 15828 | } else if (array_type->id == TypeTableEntryIdPointer) { | 15814 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 15829 | TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.pointer.child_type, | 15815 | TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.pointer.child_type, |
| ... | @@ -16155,7 +16141,6 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc | ... | @@ -16155,7 +16141,6 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc |
| 16155 | 16141 | ||
| 16156 | switch (type_entry->id) { | 16142 | switch (type_entry->id) { |
| 16157 | case TypeTableEntryIdInvalid: | 16143 | case TypeTableEntryIdInvalid: |
| 16158 | case TypeTableEntryIdVar: | ||
| 16159 | zig_unreachable(); | 16144 | zig_unreachable(); |
| 16160 | case TypeTableEntryIdMetaType: | 16145 | case TypeTableEntryIdMetaType: |
| 16161 | case TypeTableEntryIdUnreachable: | 16146 | case TypeTableEntryIdUnreachable: |
| ... | @@ -16457,21 +16442,23 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc | ... | @@ -16457,21 +16442,23 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc |
| 16457 | zig_unreachable(); | 16442 | zig_unreachable(); |
| 16458 | } | 16443 | } |
| 16459 | } | 16444 | } |
| 16460 | IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->other; | ||
| 16461 | if (type_is_invalid(param_type_value->value.type)) | ||
| 16462 | return ira->codegen->builtin_types.entry_invalid; | ||
| 16463 | |||
| 16464 | FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index]; | 16445 | FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index]; |
| 16465 | param_info->is_noalias = param_node->data.param_decl.is_noalias; | 16446 | param_info->is_noalias = param_node->data.param_decl.is_noalias; |
| 16466 | param_info->type = ir_resolve_type(ira, param_type_value); | ||
| 16467 | if (type_is_invalid(param_info->type)) | ||
| 16468 | return ira->codegen->builtin_types.entry_invalid; | ||
| 16469 | 16447 | ||
| 16470 | if (param_info->type->id == TypeTableEntryIdVar) { | 16448 | if (instruction->param_types[fn_type_id.next_param_index] == nullptr) { |
| 16449 | param_info->type = nullptr; | ||
| 16471 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | 16450 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 16472 | out_val->data.x_type = get_generic_fn_type(ira->codegen, &fn_type_id); | 16451 | out_val->data.x_type = get_generic_fn_type(ira->codegen, &fn_type_id); |
| 16473 | return ira->codegen->builtin_types.entry_type; | 16452 | return ira->codegen->builtin_types.entry_type; |
| 16453 | } else { | ||
| 16454 | IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->other; | ||
| 16455 | if (type_is_invalid(param_type_value->value.type)) | ||
| 16456 | return ira->codegen->builtin_types.entry_invalid; | ||
| 16457 | param_info->type = ir_resolve_type(ira, param_type_value); | ||
| 16458 | if (type_is_invalid(param_info->type)) | ||
| 16459 | return ira->codegen->builtin_types.entry_invalid; | ||
| 16474 | } | 16460 | } |
| 16461 | |||
| 16475 | } | 16462 | } |
| 16476 | 16463 | ||
| 16477 | if (instruction->align_value != nullptr) { | 16464 | if (instruction->align_value != nullptr) { |
| ... | @@ -16816,6 +16803,11 @@ static TypeTableEntry *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruc | ... | @@ -16816,6 +16803,11 @@ static TypeTableEntry *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruc |
| 16816 | return ira->codegen->builtin_types.entry_invalid; | 16803 | return ira->codegen->builtin_types.entry_invalid; |
| 16817 | } | 16804 | } |
| 16818 | 16805 | ||
| 16806 | if (get_ptr_const(src_type) && !get_ptr_const(dest_type)) { | ||
| 16807 | ir_add_error(ira, &instruction->base, buf_sprintf("cast discards const qualifier")); | ||
| 16808 | return ira->codegen->builtin_types.entry_invalid; | ||
| 16809 | } | ||
| 16810 | |||
| 16819 | if (instr_is_comptime(ptr)) { | 16811 | if (instr_is_comptime(ptr)) { |
| 16820 | ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk); | 16812 | ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk); |
| 16821 | if (!val) | 16813 | if (!val) |
| ... | @@ -16860,7 +16852,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -16860,7 +16852,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 16860 | assert(val->special == ConstValSpecialStatic); | 16852 | assert(val->special == ConstValSpecialStatic); |
| 16861 | switch (val->type->id) { | 16853 | switch (val->type->id) { |
| 16862 | case TypeTableEntryIdInvalid: | 16854 | case TypeTableEntryIdInvalid: |
| 16863 | case TypeTableEntryIdVar: | ||
| 16864 | case TypeTableEntryIdMetaType: | 16855 | case TypeTableEntryIdMetaType: |
| 16865 | case TypeTableEntryIdOpaque: | 16856 | case TypeTableEntryIdOpaque: |
| 16866 | case TypeTableEntryIdBoundFn: | 16857 | case TypeTableEntryIdBoundFn: |
| ... | @@ -16928,7 +16919,6 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -16928,7 +16919,6 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 16928 | assert(val->special == ConstValSpecialStatic); | 16919 | assert(val->special == ConstValSpecialStatic); |
| 16929 | switch (val->type->id) { | 16920 | switch (val->type->id) { |
| 16930 | case TypeTableEntryIdInvalid: | 16921 | case TypeTableEntryIdInvalid: |
| 16931 | case TypeTableEntryIdVar: | ||
| 16932 | case TypeTableEntryIdMetaType: | 16922 | case TypeTableEntryIdMetaType: |
| 16933 | case TypeTableEntryIdOpaque: | 16923 | case TypeTableEntryIdOpaque: |
| 16934 | case TypeTableEntryIdBoundFn: | 16924 | case TypeTableEntryIdBoundFn: |
| ... | @@ -17005,7 +16995,6 @@ static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruc | ... | @@ -17005,7 +16995,6 @@ static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruc |
| 17005 | 16995 | ||
| 17006 | switch (src_type->id) { | 16996 | switch (src_type->id) { |
| 17007 | case TypeTableEntryIdInvalid: | 16997 | case TypeTableEntryIdInvalid: |
| 17008 | case TypeTableEntryIdVar: | ||
| 17009 | case TypeTableEntryIdMetaType: | 16998 | case TypeTableEntryIdMetaType: |
| 17010 | case TypeTableEntryIdOpaque: | 16999 | case TypeTableEntryIdOpaque: |
| 17011 | case TypeTableEntryIdBoundFn: | 17000 | case TypeTableEntryIdBoundFn: |
| ... | @@ -17032,7 +17021,6 @@ static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruc | ... | @@ -17032,7 +17021,6 @@ static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruc |
| 17032 | 17021 | ||
| 17033 | switch (dest_type->id) { | 17022 | switch (dest_type->id) { |
| 17034 | case TypeTableEntryIdInvalid: | 17023 | case TypeTableEntryIdInvalid: |
| 17035 | case TypeTableEntryIdVar: | ||
| 17036 | case TypeTableEntryIdMetaType: | 17024 | case TypeTableEntryIdMetaType: |
| 17037 | case TypeTableEntryIdOpaque: | 17025 | case TypeTableEntryIdOpaque: |
| 17038 | case TypeTableEntryIdBoundFn: | 17026 | case TypeTableEntryIdBoundFn: |
src/parser.cpp+24-25| ... | @@ -263,21 +263,14 @@ static AstNode *ast_parse_error_set_expr(ParseContext *pc, size_t *token_index, | ... | @@ -263,21 +263,14 @@ static AstNode *ast_parse_error_set_expr(ParseContext *pc, size_t *token_index, |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | /* | 265 | /* |
| 266 | TypeExpr = ErrorSetExpr | "var" | 266 | TypeExpr = ErrorSetExpr |
| 267 | */ | 267 | */ |
| 268 | static AstNode *ast_parse_type_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 268 | static AstNode *ast_parse_type_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 269 | Token *token = &pc->tokens->at(*token_index); | 269 | return ast_parse_error_set_expr(pc, token_index, mandatory); |
| 270 | if (token->id == TokenIdKeywordVar) { | ||
| 271 | AstNode *node = ast_create_node(pc, NodeTypeVarLiteral, token); | ||
| 272 | *token_index += 1; | ||
| 273 | return node; | ||
| 274 | } else { | ||
| 275 | return ast_parse_error_set_expr(pc, token_index, mandatory); | ||
| 276 | } | ||
| 277 | } | 270 | } |
| 278 | 271 | ||
| 279 | /* | 272 | /* |
| 280 | ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "...") | 273 | ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "var" | "...") |
| 281 | */ | 274 | */ |
| 282 | static AstNode *ast_parse_param_decl(ParseContext *pc, size_t *token_index) { | 275 | static AstNode *ast_parse_param_decl(ParseContext *pc, size_t *token_index) { |
| 283 | Token *token = &pc->tokens->at(*token_index); | 276 | Token *token = &pc->tokens->at(*token_index); |
| ... | @@ -308,6 +301,9 @@ static AstNode *ast_parse_param_decl(ParseContext *pc, size_t *token_index) { | ... | @@ -308,6 +301,9 @@ static AstNode *ast_parse_param_decl(ParseContext *pc, size_t *token_index) { |
| 308 | if (ellipsis_tok->id == TokenIdEllipsis3) { | 301 | if (ellipsis_tok->id == TokenIdEllipsis3) { |
| 309 | *token_index += 1; | 302 | *token_index += 1; |
| 310 | node->data.param_decl.is_var_args = true; | 303 | node->data.param_decl.is_var_args = true; |
| 304 | } else if (ellipsis_tok->id == TokenIdKeywordVar) { | ||
| 305 | *token_index += 1; | ||
| 306 | node->data.param_decl.var_token = ellipsis_tok; | ||
| 311 | } else { | 307 | } else { |
| 312 | node->data.param_decl.type = ast_parse_type_expr(pc, token_index, true); | 308 | node->data.param_decl.type = ast_parse_type_expr(pc, token_index, true); |
| 313 | } | 309 | } |
| ... | @@ -2319,7 +2315,7 @@ static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool | ... | @@ -2319,7 +2315,7 @@ static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool |
| 2319 | return nullptr; | 2315 | return nullptr; |
| 2320 | } | 2316 | } |
| 2321 | 2317 | ||
| 2322 | static bool statement_terminates_without_semicolon(AstNode *node) { | 2318 | bool statement_terminates_without_semicolon(AstNode *node) { |
| 2323 | switch (node->type) { | 2319 | switch (node->type) { |
| 2324 | case NodeTypeIfBoolExpr: | 2320 | case NodeTypeIfBoolExpr: |
| 2325 | if (node->data.if_bool_expr.else_node) | 2321 | if (node->data.if_bool_expr.else_node) |
| ... | @@ -2421,7 +2417,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand | ... | @@ -2421,7 +2417,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand |
| 2421 | } | 2417 | } |
| 2422 | 2418 | ||
| 2423 | /* | 2419 | /* |
| 2424 | FnProto = option("nakedcc" | "stdcallcc" | "extern" | ("async" option("(" Expression ")"))) "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr | 2420 | FnProto = option("nakedcc" | "stdcallcc" | "extern" | ("async" option("(" Expression ")"))) "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") (TypeExpr | "var") |
| 2425 | */ | 2421 | */ |
| 2426 | static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { | 2422 | static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { |
| 2427 | Token *first_token = &pc->tokens->at(*token_index); | 2423 | Token *first_token = &pc->tokens->at(*token_index); |
| ... | @@ -2507,19 +2503,25 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m | ... | @@ -2507,19 +2503,25 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2507 | ast_eat_token(pc, token_index, TokenIdRParen); | 2503 | ast_eat_token(pc, token_index, TokenIdRParen); |
| 2508 | next_token = &pc->tokens->at(*token_index); | 2504 | next_token = &pc->tokens->at(*token_index); |
| 2509 | } | 2505 | } |
| 2510 | if (next_token->id == TokenIdKeywordError) { | 2506 | if (next_token->id == TokenIdKeywordVar) { |
| 2511 | Token *maybe_lbrace_tok = &pc->tokens->at(*token_index + 1); | 2507 | node->data.fn_proto.return_var_token = next_token; |
| 2512 | if (maybe_lbrace_tok->id == TokenIdLBrace) { | ||
| 2513 | *token_index += 1; | ||
| 2514 | node->data.fn_proto.return_type = ast_create_node(pc, NodeTypeErrorType, next_token); | ||
| 2515 | return node; | ||
| 2516 | } | ||
| 2517 | } else if (next_token->id == TokenIdBang) { | ||
| 2518 | *token_index += 1; | 2508 | *token_index += 1; |
| 2519 | node->data.fn_proto.auto_err_set = true; | ||
| 2520 | next_token = &pc->tokens->at(*token_index); | 2509 | next_token = &pc->tokens->at(*token_index); |
| 2510 | } else { | ||
| 2511 | if (next_token->id == TokenIdKeywordError) { | ||
| 2512 | Token *maybe_lbrace_tok = &pc->tokens->at(*token_index + 1); | ||
| 2513 | if (maybe_lbrace_tok->id == TokenIdLBrace) { | ||
| 2514 | *token_index += 1; | ||
| 2515 | node->data.fn_proto.return_type = ast_create_node(pc, NodeTypeErrorType, next_token); | ||
| 2516 | return node; | ||
| 2517 | } | ||
| 2518 | } else if (next_token->id == TokenIdBang) { | ||
| 2519 | *token_index += 1; | ||
| 2520 | node->data.fn_proto.auto_err_set = true; | ||
| 2521 | next_token = &pc->tokens->at(*token_index); | ||
| 2522 | } | ||
| 2523 | node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, true); | ||
| 2521 | } | 2524 | } |
| 2522 | node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, true); | ||
| 2523 | 2525 | ||
| 2524 | return node; | 2526 | return node; |
| 2525 | } | 2527 | } |
| ... | @@ -3069,9 +3071,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont | ... | @@ -3069,9 +3071,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 3069 | case NodeTypeErrorType: | 3071 | case NodeTypeErrorType: |
| 3070 | // none | 3072 | // none |
| 3071 | break; | 3073 | break; |
| 3072 | case NodeTypeVarLiteral: | ||
| 3073 | // none | ||
| 3074 | break; | ||
| 3075 | case NodeTypeAddrOfExpr: | 3074 | case NodeTypeAddrOfExpr: |
| 3076 | visit_field(&node->data.addr_of_expr.align_expr, visit, context); | 3075 | visit_field(&node->data.addr_of_expr.align_expr, visit, context); |
| 3077 | visit_field(&node->data.addr_of_expr.op_expr, visit, context); | 3076 | visit_field(&node->data.addr_of_expr.op_expr, visit, context); |
src/parser.hpp+2| ... | @@ -23,4 +23,6 @@ void ast_print(AstNode *node, int indent); | ... | @@ -23,4 +23,6 @@ void ast_print(AstNode *node, int indent); |
| 23 | 23 | ||
| 24 | void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context); | 24 | void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context); |
| 25 | 25 | ||
| 26 | bool statement_terminates_without_semicolon(AstNode *node); | ||
| 27 | |||
| 26 | #endif | 28 | #endif |
src/target.cpp+1-1| ... | @@ -787,7 +787,7 @@ static FloatAbi get_float_abi(ZigTarget *target) { | ... | @@ -787,7 +787,7 @@ static FloatAbi get_float_abi(ZigTarget *target) { |
| 787 | { | 787 | { |
| 788 | return FloatAbiHard; | 788 | return FloatAbiHard; |
| 789 | } else { | 789 | } else { |
| 790 | zig_panic("TODO: user needs to input if they want hard or soft floating point"); | 790 | return FloatAbiSoft; |
| 791 | } | 791 | } |
| 792 | } | 792 | } |
| 793 | 793 |
src/translate_c.cpp+482-111| ... | @@ -104,6 +104,7 @@ static TransScopeRoot *trans_scope_root_create(Context *c); | ... | @@ -104,6 +104,7 @@ static TransScopeRoot *trans_scope_root_create(Context *c); |
| 104 | static TransScopeWhile *trans_scope_while_create(Context *c, TransScope *parent_scope); | 104 | static TransScopeWhile *trans_scope_while_create(Context *c, TransScope *parent_scope); |
| 105 | static TransScopeBlock *trans_scope_block_create(Context *c, TransScope *parent_scope); | 105 | static TransScopeBlock *trans_scope_block_create(Context *c, TransScope *parent_scope); |
| 106 | static TransScopeVar *trans_scope_var_create(Context *c, TransScope *parent_scope, Buf *wanted_name); | 106 | static TransScopeVar *trans_scope_var_create(Context *c, TransScope *parent_scope, Buf *wanted_name); |
| 107 | static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *parent_scope); | ||
| 107 | 108 | ||
| 108 | static TransScopeBlock *trans_scope_block_find(TransScope *scope); | 109 | static TransScopeBlock *trans_scope_block_find(TransScope *scope); |
| 109 | 110 | ||
| ... | @@ -118,7 +119,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, | ... | @@ -118,7 +119,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, |
| 118 | static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node); | 119 | static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node); |
| 119 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval); | 120 | static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval); |
| 120 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); | 121 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); |
| 121 | 122 | static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval); | |
| 122 | 123 | ||
| 123 | ATTRIBUTE_PRINTF(3, 4) | 124 | ATTRIBUTE_PRINTF(3, 4) |
| 124 | static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) { | 125 | static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) { |
| ... | @@ -466,6 +467,14 @@ static QualType get_expr_qual_type(Context *c, const Expr *expr) { | ... | @@ -466,6 +467,14 @@ static QualType get_expr_qual_type(Context *c, const Expr *expr) { |
| 466 | return expr->getType(); | 467 | return expr->getType(); |
| 467 | } | 468 | } |
| 468 | 469 | ||
| 470 | static QualType get_expr_qual_type_before_implicit_cast(Context *c, const Expr *expr) { | ||
| 471 | if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) { | ||
| 472 | const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr); | ||
| 473 | return get_expr_qual_type(c, cast_expr->getSubExpr()); | ||
| 474 | } | ||
| 475 | return expr->getType(); | ||
| 476 | } | ||
| 477 | |||
| 469 | static AstNode *get_expr_type(Context *c, const Expr *expr) { | 478 | static AstNode *get_expr_type(Context *c, const Expr *expr) { |
| 470 | return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart()); | 479 | return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart()); |
| 471 | } | 480 | } |
| ... | @@ -499,15 +508,31 @@ static bool qual_type_is_ptr(QualType qt) { | ... | @@ -499,15 +508,31 @@ static bool qual_type_is_ptr(QualType qt) { |
| 499 | return ty->getTypeClass() == Type::Pointer; | 508 | return ty->getTypeClass() == Type::Pointer; |
| 500 | } | 509 | } |
| 501 | 510 | ||
| 502 | static bool qual_type_is_fn_ptr(Context *c, QualType qt) { | 511 | static const FunctionProtoType *qual_type_get_fn_proto(QualType qt, bool *is_ptr) { |
| 503 | const Type *ty = qual_type_canon(qt); | 512 | const Type *ty = qual_type_canon(qt); |
| 504 | if (ty->getTypeClass() != Type::Pointer) { | 513 | *is_ptr = false; |
| 505 | return false; | 514 | |
| 515 | if (ty->getTypeClass() == Type::Pointer) { | ||
| 516 | *is_ptr = true; | ||
| 517 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); | ||
| 518 | QualType child_qt = pointer_ty->getPointeeType(); | ||
| 519 | ty = child_qt.getTypePtr(); | ||
| 520 | } | ||
| 521 | |||
| 522 | if (ty->getTypeClass() == Type::FunctionProto) { | ||
| 523 | return static_cast<const FunctionProtoType*>(ty); | ||
| 506 | } | 524 | } |
| 507 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); | 525 | |
| 508 | QualType child_qt = pointer_ty->getPointeeType(); | 526 | return nullptr; |
| 509 | const Type *child_ty = child_qt.getTypePtr(); | 527 | } |
| 510 | return child_ty->getTypeClass() == Type::FunctionProto; | 528 | |
| 529 | static bool qual_type_is_fn_ptr(QualType qt) { | ||
| 530 | bool is_ptr; | ||
| 531 | if (qual_type_get_fn_proto(qt, &is_ptr)) { | ||
| 532 | return is_ptr; | ||
| 533 | } | ||
| 534 | |||
| 535 | return false; | ||
| 511 | } | 536 | } |
| 512 | 537 | ||
| 513 | static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) { | 538 | static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) { |
| ... | @@ -632,7 +657,7 @@ static bool c_is_signed_integer(Context *c, QualType qt) { | ... | @@ -632,7 +657,7 @@ static bool c_is_signed_integer(Context *c, QualType qt) { |
| 632 | case BuiltinType::Int128: | 657 | case BuiltinType::Int128: |
| 633 | case BuiltinType::WChar_S: | 658 | case BuiltinType::WChar_S: |
| 634 | return true; | 659 | return true; |
| 635 | default: | 660 | default: |
| 636 | return false; | 661 | return false; |
| 637 | } | 662 | } |
| 638 | } | 663 | } |
| ... | @@ -653,7 +678,7 @@ static bool c_is_unsigned_integer(Context *c, QualType qt) { | ... | @@ -653,7 +678,7 @@ static bool c_is_unsigned_integer(Context *c, QualType qt) { |
| 653 | case BuiltinType::UInt128: | 678 | case BuiltinType::UInt128: |
| 654 | case BuiltinType::WChar_U: | 679 | case BuiltinType::WChar_U: |
| 655 | return true; | 680 | return true; |
| 656 | default: | 681 | default: |
| 657 | return false; | 682 | return false; |
| 658 | } | 683 | } |
| 659 | } | 684 | } |
| ... | @@ -678,7 +703,7 @@ static bool c_is_float(Context *c, QualType qt) { | ... | @@ -678,7 +703,7 @@ static bool c_is_float(Context *c, QualType qt) { |
| 678 | case BuiltinType::Float128: | 703 | case BuiltinType::Float128: |
| 679 | case BuiltinType::LongDouble: | 704 | case BuiltinType::LongDouble: |
| 680 | return true; | 705 | return true; |
| 681 | default: | 706 | default: |
| 682 | return false; | 707 | return false; |
| 683 | } | 708 | } |
| 684 | } | 709 | } |
| ... | @@ -1138,6 +1163,22 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi | ... | @@ -1138,6 +1163,22 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi |
| 1138 | return node; | 1163 | return node; |
| 1139 | } | 1164 | } |
| 1140 | 1165 | ||
| 1166 | static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) { | ||
| 1167 | assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr); | ||
| 1168 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); | ||
| 1169 | node->data.bin_op_expr.bin_op = bin_op; | ||
| 1170 | |||
| 1171 | node->data.bin_op_expr.op1 = trans_bool_expr(c, ResultUsedYes, scope, lhs, TransRValue); | ||
| 1172 | if (node->data.bin_op_expr.op1 == nullptr) | ||
| 1173 | return nullptr; | ||
| 1174 | |||
| 1175 | node->data.bin_op_expr.op2 = trans_bool_expr(c, ResultUsedYes, scope, rhs, TransRValue); | ||
| 1176 | if (node->data.bin_op_expr.op2 == nullptr) | ||
| 1177 | return nullptr; | ||
| 1178 | |||
| 1179 | return node; | ||
| 1180 | } | ||
| 1181 | |||
| 1141 | static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, Expr *lhs, Expr *rhs) { | 1182 | static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, Expr *lhs, Expr *rhs) { |
| 1142 | if (result_used == ResultUsedNo) { | 1183 | if (result_used == ResultUsedNo) { |
| 1143 | // common case | 1184 | // common case |
| ... | @@ -1282,10 +1323,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS | ... | @@ -1282,10 +1323,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS |
| 1282 | case BO_Or: | 1323 | case BO_Or: |
| 1283 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS()); | 1324 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS()); |
| 1284 | case BO_LAnd: | 1325 | case BO_LAnd: |
| 1285 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS()); | 1326 | return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS()); |
| 1286 | case BO_LOr: | 1327 | case BO_LOr: |
| 1287 | // TODO: int vs bool | 1328 | return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); |
| 1288 | return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); | ||
| 1289 | case BO_Assign: | 1329 | case BO_Assign: |
| 1290 | return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS()); | 1330 | return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS()); |
| 1291 | case BO_Comma: | 1331 | case BO_Comma: |
| ... | @@ -1395,7 +1435,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result | ... | @@ -1395,7 +1435,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result |
| 1395 | if (result_used == ResultUsedYes) { | 1435 | if (result_used == ResultUsedYes) { |
| 1396 | // break :x *_ref | 1436 | // break :x *_ref |
| 1397 | child_scope->node->data.block.statements.append( | 1437 | child_scope->node->data.block.statements.append( |
| 1398 | trans_create_node_break(c, label_name, | 1438 | trans_create_node_break(c, label_name, |
| 1399 | trans_create_node_prefix_op(c, PrefixOpDereference, | 1439 | trans_create_node_prefix_op(c, PrefixOpDereference, |
| 1400 | trans_create_node_symbol(c, tmp_var_name)))); | 1440 | trans_create_node_symbol(c, tmp_var_name)))); |
| 1401 | } | 1441 | } |
| ... | @@ -1879,7 +1919,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc | ... | @@ -1879,7 +1919,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc |
| 1879 | AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue); | 1919 | AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue); |
| 1880 | if (value_node == nullptr) | 1920 | if (value_node == nullptr) |
| 1881 | return nullptr; | 1921 | return nullptr; |
| 1882 | bool is_fn_ptr = qual_type_is_fn_ptr(c, stmt->getSubExpr()->getType()); | 1922 | bool is_fn_ptr = qual_type_is_fn_ptr(stmt->getSubExpr()->getType()); |
| 1883 | if (is_fn_ptr) | 1923 | if (is_fn_ptr) |
| 1884 | return value_node; | 1924 | return value_node; |
| 1885 | AstNode *unwrapped = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, value_node); | 1925 | AstNode *unwrapped = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, value_node); |
| ... | @@ -1922,11 +1962,18 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc | ... | @@ -1922,11 +1962,18 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc |
| 1922 | AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue); | 1962 | AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue); |
| 1923 | if (sub_node == nullptr) | 1963 | if (sub_node == nullptr) |
| 1924 | return nullptr; | 1964 | return nullptr; |
| 1965 | |||
| 1925 | return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node); | 1966 | return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node); |
| 1926 | } | 1967 | } |
| 1927 | case UO_LNot: | 1968 | case UO_LNot: |
| 1928 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_LNot"); | 1969 | { |
| 1929 | return nullptr; | 1970 | Expr *op_expr = stmt->getSubExpr(); |
| 1971 | AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue); | ||
| 1972 | if (sub_node == nullptr) | ||
| 1973 | return nullptr; | ||
| 1974 | |||
| 1975 | return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node); | ||
| 1976 | } | ||
| 1930 | case UO_Real: | 1977 | case UO_Real: |
| 1931 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Real"); | 1978 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Real"); |
| 1932 | return nullptr; | 1979 | return nullptr; |
| ... | @@ -2206,16 +2253,246 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt | ... | @@ -2206,16 +2253,246 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt |
| 2206 | return ErrorNone; | 2253 | return ErrorNone; |
| 2207 | } | 2254 | } |
| 2208 | 2255 | ||
| 2256 | static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type) { | ||
| 2257 | AstNode *tag_type = trans_create_node_builtin_fn_call_str(c, "TagType"); | ||
| 2258 | tag_type->data.fn_call_expr.params.append(enum_type); | ||
| 2259 | |||
| 2260 | // @TagType(Enum)(0) | ||
| 2261 | AstNode *zero = trans_create_node_unsigned_negative(c, 0, false); | ||
| 2262 | AstNode *casted_zero = trans_create_node_fn_call_1(c, tag_type, zero); | ||
| 2263 | |||
| 2264 | // @bitCast(Enum, @TagType(Enum)(0)) | ||
| 2265 | AstNode *bitcast = trans_create_node_builtin_fn_call_str(c, "bitCast"); | ||
| 2266 | bitcast->data.fn_call_expr.params.append(enum_type); | ||
| 2267 | bitcast->data.fn_call_expr.params.append(casted_zero); | ||
| 2268 | |||
| 2269 | return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast); | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval) { | ||
| 2273 | AstNode *res = trans_expr(c, result_used, scope, expr, lrval); | ||
| 2274 | if (res == nullptr) | ||
| 2275 | return nullptr; | ||
| 2276 | |||
| 2277 | switch (res->type) { | ||
| 2278 | case NodeTypeBinOpExpr: | ||
| 2279 | switch (res->data.bin_op_expr.bin_op) { | ||
| 2280 | case BinOpTypeBoolOr: | ||
| 2281 | case BinOpTypeBoolAnd: | ||
| 2282 | case BinOpTypeCmpEq: | ||
| 2283 | case BinOpTypeCmpNotEq: | ||
| 2284 | case BinOpTypeCmpLessThan: | ||
| 2285 | case BinOpTypeCmpGreaterThan: | ||
| 2286 | case BinOpTypeCmpLessOrEq: | ||
| 2287 | case BinOpTypeCmpGreaterOrEq: | ||
| 2288 | return res; | ||
| 2289 | default: | ||
| 2290 | break; | ||
| 2291 | } | ||
| 2292 | |||
| 2293 | case NodeTypePrefixOpExpr: | ||
| 2294 | switch (res->data.prefix_op_expr.prefix_op) { | ||
| 2295 | case PrefixOpBoolNot: | ||
| 2296 | return res; | ||
| 2297 | default: | ||
| 2298 | break; | ||
| 2299 | } | ||
| 2300 | |||
| 2301 | case NodeTypeBoolLiteral: | ||
| 2302 | return res; | ||
| 2303 | |||
| 2304 | default: | ||
| 2305 | break; | ||
| 2306 | } | ||
| 2307 | |||
| 2308 | |||
| 2309 | const Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr(); | ||
| 2310 | auto classs = ty->getTypeClass(); | ||
| 2311 | switch (classs) { | ||
| 2312 | case Type::Builtin: | ||
| 2313 | { | ||
| 2314 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty); | ||
| 2315 | switch (builtin_ty->getKind()) { | ||
| 2316 | case BuiltinType::Bool: | ||
| 2317 | case BuiltinType::Char_U: | ||
| 2318 | case BuiltinType::UChar: | ||
| 2319 | case BuiltinType::Char_S: | ||
| 2320 | case BuiltinType::SChar: | ||
| 2321 | case BuiltinType::UShort: | ||
| 2322 | case BuiltinType::UInt: | ||
| 2323 | case BuiltinType::ULong: | ||
| 2324 | case BuiltinType::ULongLong: | ||
| 2325 | case BuiltinType::Short: | ||
| 2326 | case BuiltinType::Int: | ||
| 2327 | case BuiltinType::Long: | ||
| 2328 | case BuiltinType::LongLong: | ||
| 2329 | case BuiltinType::UInt128: | ||
| 2330 | case BuiltinType::Int128: | ||
| 2331 | case BuiltinType::Float: | ||
| 2332 | case BuiltinType::Double: | ||
| 2333 | case BuiltinType::Float128: | ||
| 2334 | case BuiltinType::LongDouble: | ||
| 2335 | case BuiltinType::WChar_U: | ||
| 2336 | case BuiltinType::Char16: | ||
| 2337 | case BuiltinType::Char32: | ||
| 2338 | case BuiltinType::WChar_S: | ||
| 2339 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false)); | ||
| 2340 | case BuiltinType::NullPtr: | ||
| 2341 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral)); | ||
| 2342 | |||
| 2343 | case BuiltinType::Void: | ||
| 2344 | case BuiltinType::Half: | ||
| 2345 | case BuiltinType::ObjCId: | ||
| 2346 | case BuiltinType::ObjCClass: | ||
| 2347 | case BuiltinType::ObjCSel: | ||
| 2348 | case BuiltinType::OMPArraySection: | ||
| 2349 | case BuiltinType::Dependent: | ||
| 2350 | case BuiltinType::Overload: | ||
| 2351 | case BuiltinType::BoundMember: | ||
| 2352 | case BuiltinType::PseudoObject: | ||
| 2353 | case BuiltinType::UnknownAny: | ||
| 2354 | case BuiltinType::BuiltinFn: | ||
| 2355 | case BuiltinType::ARCUnbridgedCast: | ||
| 2356 | case BuiltinType::OCLImage1dRO: | ||
| 2357 | case BuiltinType::OCLImage1dArrayRO: | ||
| 2358 | case BuiltinType::OCLImage1dBufferRO: | ||
| 2359 | case BuiltinType::OCLImage2dRO: | ||
| 2360 | case BuiltinType::OCLImage2dArrayRO: | ||
| 2361 | case BuiltinType::OCLImage2dDepthRO: | ||
| 2362 | case BuiltinType::OCLImage2dArrayDepthRO: | ||
| 2363 | case BuiltinType::OCLImage2dMSAARO: | ||
| 2364 | case BuiltinType::OCLImage2dArrayMSAARO: | ||
| 2365 | case BuiltinType::OCLImage2dMSAADepthRO: | ||
| 2366 | case BuiltinType::OCLImage2dArrayMSAADepthRO: | ||
| 2367 | case BuiltinType::OCLImage3dRO: | ||
| 2368 | case BuiltinType::OCLImage1dWO: | ||
| 2369 | case BuiltinType::OCLImage1dArrayWO: | ||
| 2370 | case BuiltinType::OCLImage1dBufferWO: | ||
| 2371 | case BuiltinType::OCLImage2dWO: | ||
| 2372 | case BuiltinType::OCLImage2dArrayWO: | ||
| 2373 | case BuiltinType::OCLImage2dDepthWO: | ||
| 2374 | case BuiltinType::OCLImage2dArrayDepthWO: | ||
| 2375 | case BuiltinType::OCLImage2dMSAAWO: | ||
| 2376 | case BuiltinType::OCLImage2dArrayMSAAWO: | ||
| 2377 | case BuiltinType::OCLImage2dMSAADepthWO: | ||
| 2378 | case BuiltinType::OCLImage2dArrayMSAADepthWO: | ||
| 2379 | case BuiltinType::OCLImage3dWO: | ||
| 2380 | case BuiltinType::OCLImage1dRW: | ||
| 2381 | case BuiltinType::OCLImage1dArrayRW: | ||
| 2382 | case BuiltinType::OCLImage1dBufferRW: | ||
| 2383 | case BuiltinType::OCLImage2dRW: | ||
| 2384 | case BuiltinType::OCLImage2dArrayRW: | ||
| 2385 | case BuiltinType::OCLImage2dDepthRW: | ||
| 2386 | case BuiltinType::OCLImage2dArrayDepthRW: | ||
| 2387 | case BuiltinType::OCLImage2dMSAARW: | ||
| 2388 | case BuiltinType::OCLImage2dArrayMSAARW: | ||
| 2389 | case BuiltinType::OCLImage2dMSAADepthRW: | ||
| 2390 | case BuiltinType::OCLImage2dArrayMSAADepthRW: | ||
| 2391 | case BuiltinType::OCLImage3dRW: | ||
| 2392 | case BuiltinType::OCLSampler: | ||
| 2393 | case BuiltinType::OCLEvent: | ||
| 2394 | case BuiltinType::OCLClkEvent: | ||
| 2395 | case BuiltinType::OCLQueue: | ||
| 2396 | case BuiltinType::OCLReserveID: | ||
| 2397 | return res; | ||
| 2398 | } | ||
| 2399 | break; | ||
| 2400 | } | ||
| 2401 | case Type::Pointer: | ||
| 2402 | return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral)); | ||
| 2403 | |||
| 2404 | case Type::Typedef: | ||
| 2405 | { | ||
| 2406 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); | ||
| 2407 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | ||
| 2408 | auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl()); | ||
| 2409 | if (existing_entry) { | ||
| 2410 | return existing_entry->value; | ||
| 2411 | } | ||
| 2412 | |||
| 2413 | return res; | ||
| 2414 | } | ||
| 2415 | |||
| 2416 | case Type::Enum: | ||
| 2417 | { | ||
| 2418 | const EnumType *enum_ty = static_cast<const EnumType*>(ty); | ||
| 2419 | AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl()); | ||
| 2420 | return to_enum_zero_cmp(c, res, enum_type); | ||
| 2421 | } | ||
| 2422 | |||
| 2423 | case Type::Elaborated: | ||
| 2424 | { | ||
| 2425 | const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty); | ||
| 2426 | switch (elaborated_ty->getKeyword()) { | ||
| 2427 | case ETK_Enum: { | ||
| 2428 | AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getLocStart()); | ||
| 2429 | return to_enum_zero_cmp(c, res, enum_type); | ||
| 2430 | } | ||
| 2431 | case ETK_Struct: | ||
| 2432 | case ETK_Union: | ||
| 2433 | case ETK_Interface: | ||
| 2434 | case ETK_Class: | ||
| 2435 | case ETK_Typename: | ||
| 2436 | case ETK_None: | ||
| 2437 | return res; | ||
| 2438 | } | ||
| 2439 | } | ||
| 2440 | |||
| 2441 | case Type::FunctionProto: | ||
| 2442 | case Type::Record: | ||
| 2443 | case Type::ConstantArray: | ||
| 2444 | case Type::Paren: | ||
| 2445 | case Type::Decayed: | ||
| 2446 | case Type::Attributed: | ||
| 2447 | case Type::IncompleteArray: | ||
| 2448 | case Type::BlockPointer: | ||
| 2449 | case Type::LValueReference: | ||
| 2450 | case Type::RValueReference: | ||
| 2451 | case Type::MemberPointer: | ||
| 2452 | case Type::VariableArray: | ||
| 2453 | case Type::DependentSizedArray: | ||
| 2454 | case Type::DependentSizedExtVector: | ||
| 2455 | case Type::Vector: | ||
| 2456 | case Type::ExtVector: | ||
| 2457 | case Type::FunctionNoProto: | ||
| 2458 | case Type::UnresolvedUsing: | ||
| 2459 | case Type::Adjusted: | ||
| 2460 | case Type::TypeOfExpr: | ||
| 2461 | case Type::TypeOf: | ||
| 2462 | case Type::Decltype: | ||
| 2463 | case Type::UnaryTransform: | ||
| 2464 | case Type::TemplateTypeParm: | ||
| 2465 | case Type::SubstTemplateTypeParm: | ||
| 2466 | case Type::SubstTemplateTypeParmPack: | ||
| 2467 | case Type::TemplateSpecialization: | ||
| 2468 | case Type::Auto: | ||
| 2469 | case Type::InjectedClassName: | ||
| 2470 | case Type::DependentName: | ||
| 2471 | case Type::DependentTemplateSpecialization: | ||
| 2472 | case Type::PackExpansion: | ||
| 2473 | case Type::ObjCObject: | ||
| 2474 | case Type::ObjCInterface: | ||
| 2475 | case Type::Complex: | ||
| 2476 | case Type::ObjCObjectPointer: | ||
| 2477 | case Type::Atomic: | ||
| 2478 | case Type::Pipe: | ||
| 2479 | case Type::ObjCTypeParam: | ||
| 2480 | case Type::DeducedTemplateSpecialization: | ||
| 2481 | return res; | ||
| 2482 | } | ||
| 2483 | zig_unreachable(); | ||
| 2484 | } | ||
| 2485 | |||
| 2209 | static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) { | 2486 | static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) { |
| 2210 | TransScopeWhile *while_scope = trans_scope_while_create(c, scope); | 2487 | TransScopeWhile *while_scope = trans_scope_while_create(c, scope); |
| 2211 | 2488 | ||
| 2212 | while_scope->node->data.while_expr.condition = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); | 2489 | while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); |
| 2213 | if (while_scope->node->data.while_expr.condition == nullptr) | 2490 | if (while_scope->node->data.while_expr.condition == nullptr) |
| 2214 | return nullptr; | 2491 | return nullptr; |
| 2215 | 2492 | ||
| 2216 | TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(), | 2493 | TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(), |
| 2217 | &while_scope->node->data.while_expr.body); | 2494 | &while_scope->node->data.while_expr.body); |
| 2218 | if (body_scope == nullptr) | 2495 | if (body_scope == nullptr) |
| 2219 | return nullptr; | 2496 | return nullptr; |
| 2220 | 2497 | ||
| 2221 | return while_scope->node; | 2498 | return while_scope->node; |
| ... | @@ -2236,87 +2513,11 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * | ... | @@ -2236,87 +2513,11 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * |
| 2236 | return nullptr; | 2513 | return nullptr; |
| 2237 | } | 2514 | } |
| 2238 | 2515 | ||
| 2239 | AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); | 2516 | if_node->data.if_bool_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); |
| 2240 | if (condition_node == nullptr) | 2517 | if (if_node->data.if_bool_expr.condition == nullptr) |
| 2241 | return nullptr; | 2518 | return nullptr; |
| 2242 | 2519 | ||
| 2243 | switch (condition_node->type) { | 2520 | return if_node; |
| 2244 | case NodeTypeBinOpExpr: | ||
| 2245 | switch (condition_node->data.bin_op_expr.bin_op) { | ||
| 2246 | case BinOpTypeBoolOr: | ||
| 2247 | case BinOpTypeBoolAnd: | ||
| 2248 | case BinOpTypeCmpEq: | ||
| 2249 | case BinOpTypeCmpNotEq: | ||
| 2250 | case BinOpTypeCmpLessThan: | ||
| 2251 | case BinOpTypeCmpGreaterThan: | ||
| 2252 | case BinOpTypeCmpLessOrEq: | ||
| 2253 | case BinOpTypeCmpGreaterOrEq: | ||
| 2254 | if_node->data.if_bool_expr.condition = condition_node; | ||
| 2255 | return if_node; | ||
| 2256 | default: | ||
| 2257 | goto convert_to_bitcast; | ||
| 2258 | } | ||
| 2259 | |||
| 2260 | case NodeTypePrefixOpExpr: | ||
| 2261 | switch (condition_node->data.prefix_op_expr.prefix_op) { | ||
| 2262 | case PrefixOpBoolNot: | ||
| 2263 | if_node->data.if_bool_expr.condition = condition_node; | ||
| 2264 | return if_node; | ||
| 2265 | default: | ||
| 2266 | goto convert_to_bitcast; | ||
| 2267 | } | ||
| 2268 | |||
| 2269 | case NodeTypeBoolLiteral: | ||
| 2270 | if_node->data.if_bool_expr.condition = condition_node; | ||
| 2271 | return if_node; | ||
| 2272 | |||
| 2273 | default: { | ||
| 2274 | // In Zig, float, int and pointer does not work in if statements. | ||
| 2275 | // To make it work, we bitcast any value we get to an int of the right size | ||
| 2276 | // and comp it to 0 | ||
| 2277 | // TODO: This doesn't work for pointers, as they become nullable on | ||
| 2278 | // translate | ||
| 2279 | // c: if (cond) { } | ||
| 2280 | // zig: { | ||
| 2281 | // zig: const _tmp = cond; | ||
| 2282 | // zig: if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { } | ||
| 2283 | // zig: } | ||
| 2284 | convert_to_bitcast: | ||
| 2285 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); | ||
| 2286 | |||
| 2287 | // const _tmp = cond; | ||
| 2288 | // TODO: avoid name collisions with generated variable names | ||
| 2289 | Buf* tmp_var_name = buf_create_from_str("_tmp"); | ||
| 2290 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, condition_node); | ||
| 2291 | child_scope->node->data.block.statements.append(tmp_var_decl); | ||
| 2292 | |||
| 2293 | // @sizeOf(@typeOf(_tmp)) * 8 | ||
| 2294 | AstNode *typeof_tmp = trans_create_node_builtin_fn_call_str(c, "typeOf"); | ||
| 2295 | typeof_tmp->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name)); | ||
| 2296 | AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf"); | ||
| 2297 | sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp); | ||
| 2298 | AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op( | ||
| 2299 | c, sizeof_tmp, BinOpTypeMult, | ||
| 2300 | trans_create_node_unsigned_negative(c, 8, false)); | ||
| 2301 | |||
| 2302 | // @IntType(false, @sizeOf(@typeOf(_tmp)) * 8) | ||
| 2303 | AstNode *int_type = trans_create_node_builtin_fn_call_str(c, "IntType"); | ||
| 2304 | int_type->data.fn_call_expr.params.append(trans_create_node_bool(c, false)); | ||
| 2305 | int_type->data.fn_call_expr.params.append(sizeof_tmp_in_bits); | ||
| 2306 | |||
| 2307 | // @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) | ||
| 2308 | AstNode *bit_cast = trans_create_node_builtin_fn_call_str(c, "bitCast"); | ||
| 2309 | bit_cast->data.fn_call_expr.params.append(int_type); | ||
| 2310 | bit_cast->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name)); | ||
| 2311 | |||
| 2312 | // if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { } | ||
| 2313 | AstNode *not_eql_zero = trans_create_node_bin_op(c, bit_cast, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false)); | ||
| 2314 | if_node->data.if_bool_expr.condition = not_eql_zero; | ||
| 2315 | child_scope->node->data.block.statements.append(if_node); | ||
| 2316 | |||
| 2317 | return child_scope->node; | ||
| 2318 | } | ||
| 2319 | } | ||
| 2320 | } | 2521 | } |
| 2321 | 2522 | ||
| 2322 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) { | 2523 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) { |
| ... | @@ -2326,8 +2527,10 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * | ... | @@ -2326,8 +2527,10 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * |
| 2326 | if (callee_raw_node == nullptr) | 2527 | if (callee_raw_node == nullptr) |
| 2327 | return nullptr; | 2528 | return nullptr; |
| 2328 | 2529 | ||
| 2530 | bool is_ptr = false; | ||
| 2531 | const FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr); | ||
| 2329 | AstNode *callee_node = nullptr; | 2532 | AstNode *callee_node = nullptr; |
| 2330 | if (qual_type_is_fn_ptr(c, stmt->getCallee()->getType())) { | 2533 | if (is_ptr && fn_ty) { |
| 2331 | if (stmt->getCallee()->getStmtClass() == Stmt::ImplicitCastExprClass) { | 2534 | if (stmt->getCallee()->getStmtClass() == Stmt::ImplicitCastExprClass) { |
| 2332 | const ImplicitCastExpr *implicit_cast = static_cast<const ImplicitCastExpr *>(stmt->getCallee()); | 2535 | const ImplicitCastExpr *implicit_cast = static_cast<const ImplicitCastExpr *>(stmt->getCallee()); |
| 2333 | if (implicit_cast->getCastKind() == CK_FunctionToPointerDecay) { | 2536 | if (implicit_cast->getCastKind() == CK_FunctionToPointerDecay) { |
| ... | @@ -2359,6 +2562,10 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * | ... | @@ -2359,6 +2562,10 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * |
| 2359 | node->data.fn_call_expr.params.append(arg_node); | 2562 | node->data.fn_call_expr.params.append(arg_node); |
| 2360 | } | 2563 | } |
| 2361 | 2564 | ||
| 2565 | if (result_used == ResultUsedNo && fn_ty && !qual_type_canon(fn_ty->getReturnType())->isVoidType()) { | ||
| 2566 | node = trans_create_node_bin_op(c, trans_create_node_symbol_str(c, "_"), BinOpTypeAssign, node); | ||
| 2567 | } | ||
| 2568 | |||
| 2362 | return node; | 2569 | return node; |
| 2363 | } | 2570 | } |
| 2364 | 2571 | ||
| ... | @@ -2501,10 +2708,18 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt | ... | @@ -2501,10 +2708,18 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt |
| 2501 | if (cond_stmt == nullptr) { | 2708 | if (cond_stmt == nullptr) { |
| 2502 | while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true); | 2709 | while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true); |
| 2503 | } else { | 2710 | } else { |
| 2504 | TransScope *end_cond_scope = trans_stmt(c, cond_scope, cond_stmt, | 2711 | if (Expr::classof(cond_stmt)) { |
| 2505 | &while_scope->node->data.while_expr.condition); | 2712 | const Expr *cond_expr = static_cast<const Expr*>(cond_stmt); |
| 2506 | if (end_cond_scope == nullptr) | 2713 | while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue); |
| 2507 | return nullptr; | 2714 | |
| 2715 | if (while_scope->node->data.while_expr.condition == nullptr) | ||
| 2716 | return nullptr; | ||
| 2717 | } else { | ||
| 2718 | TransScope *end_cond_scope = trans_stmt(c, cond_scope, cond_stmt, | ||
| 2719 | &while_scope->node->data.while_expr.condition); | ||
| 2720 | if (end_cond_scope == nullptr) | ||
| 2721 | return nullptr; | ||
| 2722 | } | ||
| 2508 | } | 2723 | } |
| 2509 | 2724 | ||
| 2510 | const Stmt *inc_stmt = stmt->getInc(); | 2725 | const Stmt *inc_stmt = stmt->getInc(); |
| ... | @@ -2525,6 +2740,155 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt | ... | @@ -2525,6 +2740,155 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt |
| 2525 | return loop_block_node; | 2740 | return loop_block_node; |
| 2526 | } | 2741 | } |
| 2527 | 2742 | ||
| 2743 | static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const SwitchStmt *stmt) { | ||
| 2744 | TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope); | ||
| 2745 | |||
| 2746 | TransScopeSwitch *switch_scope; | ||
| 2747 | |||
| 2748 | const DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt(); | ||
| 2749 | if (var_decl_stmt == nullptr) { | ||
| 2750 | switch_scope = trans_scope_switch_create(c, &block_scope->base); | ||
| 2751 | } else { | ||
| 2752 | AstNode *vars_node; | ||
| 2753 | TransScope *var_scope = trans_stmt(c, &block_scope->base, var_decl_stmt, &vars_node); | ||
| 2754 | if (var_scope == nullptr) | ||
| 2755 | return nullptr; | ||
| 2756 | if (vars_node != nullptr) | ||
| 2757 | block_scope->node->data.block.statements.append(vars_node); | ||
| 2758 | switch_scope = trans_scope_switch_create(c, var_scope); | ||
| 2759 | } | ||
| 2760 | block_scope->node->data.block.statements.append(switch_scope->switch_node); | ||
| 2761 | |||
| 2762 | // TODO avoid name collisions | ||
| 2763 | Buf *end_label_name = buf_create_from_str("__switch"); | ||
| 2764 | switch_scope->end_label_name = end_label_name; | ||
| 2765 | block_scope->node->data.block.name = end_label_name; | ||
| 2766 | |||
| 2767 | const Expr *cond_expr = stmt->getCond(); | ||
| 2768 | assert(cond_expr != nullptr); | ||
| 2769 | |||
| 2770 | AstNode *expr_node = trans_expr(c, ResultUsedYes, &block_scope->base, cond_expr, TransRValue); | ||
| 2771 | if (expr_node == nullptr) | ||
| 2772 | return nullptr; | ||
| 2773 | switch_scope->switch_node->data.switch_expr.expr = expr_node; | ||
| 2774 | |||
| 2775 | AstNode *body_node; | ||
| 2776 | const Stmt *body_stmt = stmt->getBody(); | ||
| 2777 | if (body_stmt->getStmtClass() == Stmt::CompoundStmtClass) { | ||
| 2778 | if (trans_compound_stmt_inline(c, &switch_scope->base, (const CompoundStmt *)body_stmt, | ||
| 2779 | block_scope->node, nullptr)) | ||
| 2780 | { | ||
| 2781 | return nullptr; | ||
| 2782 | } | ||
| 2783 | } else { | ||
| 2784 | TransScope *body_scope = trans_stmt(c, &switch_scope->base, body_stmt, &body_node); | ||
| 2785 | if (body_scope == nullptr) | ||
| 2786 | return nullptr; | ||
| 2787 | if (body_node != nullptr) | ||
| 2788 | block_scope->node->data.block.statements.append(body_node); | ||
| 2789 | } | ||
| 2790 | |||
| 2791 | if (!switch_scope->found_default && !stmt->isAllEnumCasesCovered()) { | ||
| 2792 | AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng); | ||
| 2793 | prong_node->data.switch_prong.expr = trans_create_node_break(c, end_label_name, nullptr); | ||
| 2794 | switch_scope->switch_node->data.switch_expr.prongs.append(prong_node); | ||
| 2795 | } | ||
| 2796 | |||
| 2797 | return block_scope->node; | ||
| 2798 | } | ||
| 2799 | |||
| 2800 | static TransScopeSwitch *trans_scope_switch_find(TransScope *scope) { | ||
| 2801 | while (scope != nullptr) { | ||
| 2802 | if (scope->id == TransScopeIdSwitch) { | ||
| 2803 | return (TransScopeSwitch *)scope; | ||
| 2804 | } | ||
| 2805 | scope = scope->parent; | ||
| 2806 | } | ||
| 2807 | return nullptr; | ||
| 2808 | } | ||
| 2809 | |||
| 2810 | static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStmt *stmt, AstNode **out_node, | ||
| 2811 | TransScope **out_scope) { | ||
| 2812 | *out_node = nullptr; | ||
| 2813 | |||
| 2814 | if (stmt->getRHS() != nullptr) { | ||
| 2815 | emit_warning(c, stmt->getLocStart(), "TODO support GNU switch case a ... b extension"); | ||
| 2816 | return ErrorUnexpected; | ||
| 2817 | } | ||
| 2818 | |||
| 2819 | TransScopeSwitch *switch_scope = trans_scope_switch_find(parent_scope); | ||
| 2820 | assert(switch_scope != nullptr); | ||
| 2821 | |||
| 2822 | Buf *label_name = buf_sprintf("__case_%" PRIu32, switch_scope->case_index); | ||
| 2823 | switch_scope->case_index += 1; | ||
| 2824 | |||
| 2825 | { | ||
| 2826 | // Add the prong | ||
| 2827 | AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng); | ||
| 2828 | AstNode *item_node = trans_expr(c, ResultUsedYes, &switch_scope->base, stmt->getLHS(), TransRValue); | ||
| 2829 | if (item_node == nullptr) | ||
| 2830 | return ErrorUnexpected; | ||
| 2831 | prong_node->data.switch_prong.items.append(item_node); | ||
| 2832 | prong_node->data.switch_prong.expr = trans_create_node_break(c, label_name, nullptr); | ||
| 2833 | switch_scope->switch_node->data.switch_expr.prongs.append(prong_node); | ||
| 2834 | } | ||
| 2835 | |||
| 2836 | TransScopeBlock *scope_block = trans_scope_block_find(parent_scope); | ||
| 2837 | |||
| 2838 | AstNode *case_block = trans_create_node(c, NodeTypeBlock); | ||
| 2839 | case_block->data.block.name = label_name; | ||
| 2840 | case_block->data.block.statements = scope_block->node->data.block.statements; | ||
| 2841 | scope_block->node->data.block.statements = {0}; | ||
| 2842 | scope_block->node->data.block.statements.append(case_block); | ||
| 2843 | |||
| 2844 | AstNode *sub_stmt_node; | ||
| 2845 | TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node); | ||
| 2846 | if (new_scope == nullptr) | ||
| 2847 | return ErrorUnexpected; | ||
| 2848 | if (sub_stmt_node != nullptr) | ||
| 2849 | scope_block->node->data.block.statements.append(sub_stmt_node); | ||
| 2850 | |||
| 2851 | *out_scope = new_scope; | ||
| 2852 | return ErrorNone; | ||
| 2853 | } | ||
| 2854 | |||
| 2855 | static int trans_switch_default(Context *c, TransScope *parent_scope, const DefaultStmt *stmt, AstNode **out_node, | ||
| 2856 | TransScope **out_scope) | ||
| 2857 | { | ||
| 2858 | *out_node = nullptr; | ||
| 2859 | |||
| 2860 | TransScopeSwitch *switch_scope = trans_scope_switch_find(parent_scope); | ||
| 2861 | assert(switch_scope != nullptr); | ||
| 2862 | |||
| 2863 | Buf *label_name = buf_sprintf("__default"); | ||
| 2864 | |||
| 2865 | { | ||
| 2866 | // Add the prong | ||
| 2867 | AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng); | ||
| 2868 | prong_node->data.switch_prong.expr = trans_create_node_break(c, label_name, nullptr); | ||
| 2869 | switch_scope->switch_node->data.switch_expr.prongs.append(prong_node); | ||
| 2870 | switch_scope->found_default = true; | ||
| 2871 | } | ||
| 2872 | |||
| 2873 | TransScopeBlock *scope_block = trans_scope_block_find(parent_scope); | ||
| 2874 | |||
| 2875 | AstNode *case_block = trans_create_node(c, NodeTypeBlock); | ||
| 2876 | case_block->data.block.name = label_name; | ||
| 2877 | case_block->data.block.statements = scope_block->node->data.block.statements; | ||
| 2878 | scope_block->node->data.block.statements = {0}; | ||
| 2879 | scope_block->node->data.block.statements.append(case_block); | ||
| 2880 | |||
| 2881 | AstNode *sub_stmt_node; | ||
| 2882 | TransScope *new_scope = trans_stmt(c, parent_scope, stmt->getSubStmt(), &sub_stmt_node); | ||
| 2883 | if (new_scope == nullptr) | ||
| 2884 | return ErrorUnexpected; | ||
| 2885 | if (sub_stmt_node != nullptr) | ||
| 2886 | scope_block->node->data.block.statements.append(sub_stmt_node); | ||
| 2887 | |||
| 2888 | *out_scope = new_scope; | ||
| 2889 | return ErrorNone; | ||
| 2890 | } | ||
| 2891 | |||
| 2528 | static AstNode *trans_string_literal(Context *c, TransScope *scope, const StringLiteral *stmt) { | 2892 | static AstNode *trans_string_literal(Context *c, TransScope *scope, const StringLiteral *stmt) { |
| 2529 | switch (stmt->getKind()) { | 2893 | switch (stmt->getKind()) { |
| 2530 | case StringLiteral::Ascii: | 2894 | case StringLiteral::Ascii: |
| ... | @@ -2549,7 +2913,8 @@ static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt | ... | @@ -2549,7 +2913,8 @@ static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt |
| 2549 | if (cur_scope->id == TransScopeIdWhile) { | 2913 | if (cur_scope->id == TransScopeIdWhile) { |
| 2550 | return trans_create_node(c, NodeTypeBreak); | 2914 | return trans_create_node(c, NodeTypeBreak); |
| 2551 | } else if (cur_scope->id == TransScopeIdSwitch) { | 2915 | } else if (cur_scope->id == TransScopeIdSwitch) { |
| 2552 | zig_panic("TODO"); | 2916 | TransScopeSwitch *switch_scope = (TransScopeSwitch *)cur_scope; |
| 2917 | return trans_create_node_break(c, switch_scope->end_label_name, nullptr); | ||
| 2553 | } | 2918 | } |
| 2554 | cur_scope = cur_scope->parent; | 2919 | cur_scope = cur_scope->parent; |
| 2555 | } | 2920 | } |
| ... | @@ -2649,14 +3014,12 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, | ... | @@ -2649,14 +3014,12 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt, |
| 2649 | return wrap_stmt(out_node, out_child_scope, scope, | 3014 | return wrap_stmt(out_node, out_child_scope, scope, |
| 2650 | trans_expr(c, result_used, scope, ((const ParenExpr*)stmt)->getSubExpr(), lrvalue)); | 3015 | trans_expr(c, result_used, scope, ((const ParenExpr*)stmt)->getSubExpr(), lrvalue)); |
| 2651 | case Stmt::SwitchStmtClass: | 3016 | case Stmt::SwitchStmtClass: |
| 2652 | emit_warning(c, stmt->getLocStart(), "TODO handle C SwitchStmtClass"); | 3017 | return wrap_stmt(out_node, out_child_scope, scope, |
| 2653 | return ErrorUnexpected; | 3018 | trans_switch_stmt(c, scope, (const SwitchStmt *)stmt)); |
| 2654 | case Stmt::CaseStmtClass: | 3019 | case Stmt::CaseStmtClass: |
| 2655 | emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass"); | 3020 | return trans_switch_case(c, scope, (const CaseStmt *)stmt, out_node, out_child_scope); |
| 2656 | return ErrorUnexpected; | ||
| 2657 | case Stmt::DefaultStmtClass: | 3021 | case Stmt::DefaultStmtClass: |
| 2658 | emit_warning(c, stmt->getLocStart(), "TODO handle C DefaultStmtClass"); | 3022 | return trans_switch_default(c, scope, (const DefaultStmt *)stmt, out_node, out_child_scope); |
| 2659 | return ErrorUnexpected; | ||
| 2660 | case Stmt::NoStmtClass: | 3023 | case Stmt::NoStmtClass: |
| 2661 | emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass"); | 3024 | emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass"); |
| 2662 | return ErrorUnexpected; | 3025 | return ErrorUnexpected; |
| ... | @@ -3826,6 +4189,14 @@ static TransScopeVar *trans_scope_var_create(Context *c, TransScope *parent_scop | ... | @@ -3826,6 +4189,14 @@ static TransScopeVar *trans_scope_var_create(Context *c, TransScope *parent_scop |
| 3826 | return result; | 4189 | return result; |
| 3827 | } | 4190 | } |
| 3828 | 4191 | ||
| 4192 | static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *parent_scope) { | ||
| 4193 | TransScopeSwitch *result = allocate<TransScopeSwitch>(1); | ||
| 4194 | result->base.id = TransScopeIdSwitch; | ||
| 4195 | result->base.parent = parent_scope; | ||
| 4196 | result->switch_node = trans_create_node(c, NodeTypeSwitchExpr); | ||
| 4197 | return result; | ||
| 4198 | } | ||
| 4199 | |||
| 3829 | static TransScopeBlock *trans_scope_block_find(TransScope *scope) { | 4200 | static TransScopeBlock *trans_scope_block_find(TransScope *scope) { |
| 3830 | while (scope != nullptr) { | 4201 | while (scope != nullptr) { |
| 3831 | if (scope->id == TransScopeIdBlock) { | 4202 | if (scope->id == TransScopeIdBlock) { |
std/buf_map.zig+1-3| ... | @@ -62,9 +62,7 @@ pub const BufMap = struct { | ... | @@ -62,9 +62,7 @@ pub const BufMap = struct { |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | fn free(self: &BufMap, value: []const u8) void { | 64 | fn free(self: &BufMap, value: []const u8) void { |
| 65 | // remove the const | 65 | self.hash_map.allocator.free(value); |
| 66 | const mut_value = @ptrCast(&u8, value.ptr)[0..value.len]; | ||
| 67 | self.hash_map.allocator.free(mut_value); | ||
| 68 | } | 66 | } |
| 69 | 67 | ||
| 70 | fn copy(self: &BufMap, value: []const u8) ![]const u8 { | 68 | fn copy(self: &BufMap, value: []const u8) ![]const u8 { |
std/buf_set.zig+1-3| ... | @@ -50,9 +50,7 @@ pub const BufSet = struct { | ... | @@ -50,9 +50,7 @@ pub const BufSet = struct { |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | fn free(self: &BufSet, value: []const u8) void { | 52 | fn free(self: &BufSet, value: []const u8) void { |
| 53 | // remove the const | 53 | self.hash_map.allocator.free(value); |
| 54 | const mut_value = @ptrCast(&u8, value.ptr)[0..value.len]; | ||
| 55 | self.hash_map.allocator.free(mut_value); | ||
| 56 | } | 54 | } |
| 57 | 55 | ||
| 58 | fn copy(self: &BufSet, value: []const u8) ![]const u8 { | 56 | fn copy(self: &BufSet, value: []const u8) ![]const u8 { |
std/os/index.zig+1-1| ... | @@ -1634,7 +1634,7 @@ pub fn argsFree(allocator: &mem.Allocator, args_alloc: []const []u8) void { | ... | @@ -1634,7 +1634,7 @@ pub fn argsFree(allocator: &mem.Allocator, args_alloc: []const []u8) void { |
| 1634 | for (args_alloc) |arg| { | 1634 | for (args_alloc) |arg| { |
| 1635 | total_bytes += @sizeOf([]u8) + arg.len; | 1635 | total_bytes += @sizeOf([]u8) + arg.len; |
| 1636 | } | 1636 | } |
| 1637 | const unaligned_allocated_buf = @ptrCast(&u8, args_alloc.ptr)[0..total_bytes]; | 1637 | const unaligned_allocated_buf = @ptrCast(&const u8, args_alloc.ptr)[0..total_bytes]; |
| 1638 | const aligned_allocated_buf = @alignCast(@alignOf([]u8), unaligned_allocated_buf); | 1638 | const aligned_allocated_buf = @alignCast(@alignOf([]u8), unaligned_allocated_buf); |
| 1639 | return allocator.free(aligned_allocated_buf); | 1639 | return allocator.free(aligned_allocated_buf); |
| 1640 | } | 1640 | } |
std/special/compiler_rt/udivmod.zig+2-2| ... | @@ -11,8 +11,8 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: | ... | @@ -11,8 +11,8 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: |
| 11 | const SignedDoubleInt = @IntType(true, DoubleInt.bit_count); | 11 | const SignedDoubleInt = @IntType(true, DoubleInt.bit_count); |
| 12 | const Log2SingleInt = @import("../../math/index.zig").Log2Int(SingleInt); | 12 | const Log2SingleInt = @import("../../math/index.zig").Log2Int(SingleInt); |
| 13 | 13 | ||
| 14 | const n = *@ptrCast(&[2]SingleInt, &a); // TODO issue #421 | 14 | const n = *@ptrCast(&const [2]SingleInt, &a); // TODO issue #421 |
| 15 | const d = *@ptrCast(&[2]SingleInt, &b); // TODO issue #421 | 15 | const d = *@ptrCast(&const [2]SingleInt, &b); // TODO issue #421 |
| 16 | var q: [2]SingleInt = undefined; | 16 | var q: [2]SingleInt = undefined; |
| 17 | var r: [2]SingleInt = undefined; | 17 | var r: [2]SingleInt = undefined; |
| 18 | var sr: c_uint = undefined; | 18 | var sr: c_uint = undefined; |
std/unicode.zig+14-6| ... | @@ -96,7 +96,15 @@ pub fn utf8ValidateSlice(s: []const u8) bool { | ... | @@ -96,7 +96,15 @@ pub fn utf8ValidateSlice(s: []const u8) bool { |
| 96 | return true; | 96 | return true; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | const Utf8View = struct { | 99 | /// Utf8View iterates the code points of a utf-8 encoded string. |
| 100 | /// | ||
| 101 | /// ``` | ||
| 102 | /// var utf8 = (try std.unicode.Utf8View.init("hi there")).iterator(); | ||
| 103 | /// while (utf8.nextCodepointSlice()) |codepoint| { | ||
| 104 | /// std.debug.warn("got codepoint {}\n", codepoint); | ||
| 105 | /// } | ||
| 106 | /// ``` | ||
| 107 | pub const Utf8View = struct { | ||
| 100 | bytes: []const u8, | 108 | bytes: []const u8, |
| 101 | 109 | ||
| 102 | pub fn init(s: []const u8) !Utf8View { | 110 | pub fn init(s: []const u8) !Utf8View { |
| ... | @@ -124,7 +132,7 @@ const Utf8View = struct { | ... | @@ -124,7 +132,7 @@ const Utf8View = struct { |
| 124 | } | 132 | } |
| 125 | } | 133 | } |
| 126 | 134 | ||
| 127 | pub fn Iterator(s: &const Utf8View) Utf8Iterator { | 135 | pub fn iterator(s: &const Utf8View) Utf8Iterator { |
| 128 | return Utf8Iterator { | 136 | return Utf8Iterator { |
| 129 | .bytes = s.bytes, | 137 | .bytes = s.bytes, |
| 130 | .i = 0, | 138 | .i = 0, |
| ... | @@ -165,13 +173,13 @@ const Utf8Iterator = struct { | ... | @@ -165,13 +173,13 @@ const Utf8Iterator = struct { |
| 165 | test "utf8 iterator on ascii" { | 173 | test "utf8 iterator on ascii" { |
| 166 | const s = Utf8View.initComptime("abc"); | 174 | const s = Utf8View.initComptime("abc"); |
| 167 | 175 | ||
| 168 | var it1 = s.Iterator(); | 176 | var it1 = s.iterator(); |
| 169 | debug.assert(std.mem.eql(u8, "a", ??it1.nextCodepointSlice())); | 177 | debug.assert(std.mem.eql(u8, "a", ??it1.nextCodepointSlice())); |
| 170 | debug.assert(std.mem.eql(u8, "b", ??it1.nextCodepointSlice())); | 178 | debug.assert(std.mem.eql(u8, "b", ??it1.nextCodepointSlice())); |
| 171 | debug.assert(std.mem.eql(u8, "c", ??it1.nextCodepointSlice())); | 179 | debug.assert(std.mem.eql(u8, "c", ??it1.nextCodepointSlice())); |
| 172 | debug.assert(it1.nextCodepointSlice() == null); | 180 | debug.assert(it1.nextCodepointSlice() == null); |
| 173 | 181 | ||
| 174 | var it2 = s.Iterator(); | 182 | var it2 = s.iterator(); |
| 175 | debug.assert(??it2.nextCodepoint() == 'a'); | 183 | debug.assert(??it2.nextCodepoint() == 'a'); |
| 176 | debug.assert(??it2.nextCodepoint() == 'b'); | 184 | debug.assert(??it2.nextCodepoint() == 'b'); |
| 177 | debug.assert(??it2.nextCodepoint() == 'c'); | 185 | debug.assert(??it2.nextCodepoint() == 'c'); |
| ... | @@ -189,13 +197,13 @@ test "utf8 view bad" { | ... | @@ -189,13 +197,13 @@ test "utf8 view bad" { |
| 189 | test "utf8 view ok" { | 197 | test "utf8 view ok" { |
| 190 | const s = Utf8View.initComptime("東京市"); | 198 | const s = Utf8View.initComptime("東京市"); |
| 191 | 199 | ||
| 192 | var it1 = s.Iterator(); | 200 | var it1 = s.iterator(); |
| 193 | debug.assert(std.mem.eql(u8, "東", ??it1.nextCodepointSlice())); | 201 | debug.assert(std.mem.eql(u8, "東", ??it1.nextCodepointSlice())); |
| 194 | debug.assert(std.mem.eql(u8, "京", ??it1.nextCodepointSlice())); | 202 | debug.assert(std.mem.eql(u8, "京", ??it1.nextCodepointSlice())); |
| 195 | debug.assert(std.mem.eql(u8, "市", ??it1.nextCodepointSlice())); | 203 | debug.assert(std.mem.eql(u8, "市", ??it1.nextCodepointSlice())); |
| 196 | debug.assert(it1.nextCodepointSlice() == null); | 204 | debug.assert(it1.nextCodepointSlice() == null); |
| 197 | 205 | ||
| 198 | var it2 = s.Iterator(); | 206 | var it2 = s.iterator(); |
| 199 | debug.assert(??it2.nextCodepoint() == 0x6771); | 207 | debug.assert(??it2.nextCodepoint() == 0x6771); |
| 200 | debug.assert(??it2.nextCodepoint() == 0x4eac); | 208 | debug.assert(??it2.nextCodepoint() == 0x4eac); |
| 201 | debug.assert(??it2.nextCodepoint() == 0x5e02); | 209 | debug.assert(??it2.nextCodepoint() == 0x5e02); |
test/cases/cast.zig+1-1| ... | @@ -16,7 +16,7 @@ test "integer literal to pointer cast" { | ... | @@ -16,7 +16,7 @@ test "integer literal to pointer cast" { |
| 16 | test "pointer reinterpret const float to int" { | 16 | test "pointer reinterpret const float to int" { |
| 17 | const float: f64 = 5.99999999999994648725e-01; | 17 | const float: f64 = 5.99999999999994648725e-01; |
| 18 | const float_ptr = &float; | 18 | const float_ptr = &float; |
| 19 | const int_ptr = @ptrCast(&i32, float_ptr); | 19 | const int_ptr = @ptrCast(&const i32, float_ptr); |
| 20 | const int_val = *int_ptr; | 20 | const int_val = *int_ptr; |
| 21 | assert(int_val == 858993411); | 21 | assert(int_val == 858993411); |
| 22 | } | 22 | } |
test/cases/misc.zig+11-1| ... | @@ -261,7 +261,7 @@ test "generic malloc free" { | ... | @@ -261,7 +261,7 @@ test "generic malloc free" { |
| 261 | const a = memAlloc(u8, 10) catch unreachable; | 261 | const a = memAlloc(u8, 10) catch unreachable; |
| 262 | memFree(u8, a); | 262 | memFree(u8, a); |
| 263 | } | 263 | } |
| 264 | const some_mem : [100]u8 = undefined; | 264 | var some_mem : [100]u8 = undefined; |
| 265 | fn memAlloc(comptime T: type, n: usize) error![]T { | 265 | fn memAlloc(comptime T: type, n: usize) error![]T { |
| 266 | return @ptrCast(&T, &some_mem[0])[0..n]; | 266 | return @ptrCast(&T, &some_mem[0])[0..n]; |
| 267 | } | 267 | } |
| ... | @@ -650,3 +650,13 @@ test "packed struct, enum, union parameters in extern function" { | ... | @@ -650,3 +650,13 @@ test "packed struct, enum, union parameters in extern function" { |
| 650 | 650 | ||
| 651 | export fn testPackedStuff(a: &const PackedStruct, b: &const PackedUnion, c: PackedEnum) void { | 651 | export fn testPackedStuff(a: &const PackedStruct, b: &const PackedUnion, c: PackedEnum) void { |
| 652 | } | 652 | } |
| 653 | |||
| 654 | |||
| 655 | test "slicing zero length array" { | ||
| 656 | const s1 = ""[0..]; | ||
| 657 | const s2 = ([]u32{})[0..]; | ||
| 658 | assert(s1.len == 0); | ||
| 659 | assert(s2.len == 0); | ||
| 660 | assert(mem.eql(u8, s1, "")); | ||
| 661 | assert(mem.eql(u32, s2, []u32{})); | ||
| 662 | } |
test/compare_output.zig+2-2| ... | @@ -285,8 +285,8 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { | ... | @@ -285,8 +285,8 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { |
| 285 | \\const c = @cImport(@cInclude("stdlib.h")); | 285 | \\const c = @cImport(@cInclude("stdlib.h")); |
| 286 | \\ | 286 | \\ |
| 287 | \\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) c_int { | 287 | \\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) c_int { |
| 288 | \\ const a_int = @ptrCast(&align(1) i32, a ?? unreachable); | 288 | \\ const a_int = @ptrCast(&align(1) const i32, a ?? unreachable); |
| 289 | \\ const b_int = @ptrCast(&align(1) i32, b ?? unreachable); | 289 | \\ const b_int = @ptrCast(&align(1) const i32, b ?? unreachable); |
| 290 | \\ if (*a_int < *b_int) { | 290 | \\ if (*a_int < *b_int) { |
| 291 | \\ return -1; | 291 | \\ return -1; |
| 292 | \\ } else if (*a_int > *b_int) { | 292 | \\ } else if (*a_int > *b_int) { |
test/compile_errors.zig+40-1| ... | @@ -1,6 +1,45 @@ | ... | @@ -1,6 +1,45 @@ |
| 1 | const tests = @import("tests.zig"); | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | ||
| 3 | pub fn addCases(cases: &tests.CompileErrorContext) void { | 3 | pub fn addCases(cases: &tests.CompileErrorContext) void { |
| 4 | cases.add("@tagName used on union with no associated enum tag", | ||
| 5 | \\const FloatInt = extern union { | ||
| 6 | \\ Float: f32, | ||
| 7 | \\ Int: i32, | ||
| 8 | \\}; | ||
| 9 | \\export fn entry() void { | ||
| 10 | \\ var fi = FloatInt{.Float = 123.45}; | ||
| 11 | \\ var tagName = @tagName(fi); | ||
| 12 | \\} | ||
| 13 | , | ||
| 14 | ".tmp_source.zig:7:19: error: union has no associated enum", | ||
| 15 | ".tmp_source.zig:1:18: note: declared here"); | ||
| 16 | |||
| 17 | cases.add("returning error from void async function", | ||
| 18 | \\const std = @import("std"); | ||
| 19 | \\export fn entry() void { | ||
| 20 | \\ const p = async(std.debug.global_allocator) amain() catch unreachable; | ||
| 21 | \\} | ||
| 22 | \\async fn amain() void { | ||
| 23 | \\ return error.ShouldBeCompileError; | ||
| 24 | \\} | ||
| 25 | , | ||
| 26 | ".tmp_source.zig:6:17: error: expected type 'void', found 'error{ShouldBeCompileError}'"); | ||
| 27 | |||
| 28 | cases.add("var not allowed in structs", | ||
| 29 | \\export fn entry() void { | ||
| 30 | \\ var s = (struct{v: var}){.v=i32(10)}; | ||
| 31 | \\} | ||
| 32 | , | ||
| 33 | ".tmp_source.zig:2:23: error: invalid token: 'var'"); | ||
| 34 | |||
| 35 | cases.add("@ptrCast discards const qualifier", | ||
| 36 | \\export fn entry() void { | ||
| 37 | \\ const x: i32 = 1234; | ||
| 38 | \\ const y = @ptrCast(&i32, &x); | ||
| 39 | \\} | ||
| 40 | , | ||
| 41 | ".tmp_source.zig:3:15: error: cast discards const qualifier"); | ||
| 42 | |||
| 4 | cases.add("comptime slice of undefined pointer non-zero len", | 43 | cases.add("comptime slice of undefined pointer non-zero len", |
| 5 | \\export fn entry() void { | 44 | \\export fn entry() void { |
| 6 | \\ const slice = (&i32)(undefined)[0..1]; | 45 | \\ const slice = (&i32)(undefined)[0..1]; |
| ... | @@ -2432,7 +2471,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { | ... | @@ -2432,7 +2471,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { |
| 2432 | \\const Derp = @OpaqueType(); | 2471 | \\const Derp = @OpaqueType(); |
| 2433 | \\extern fn bar(d: &Derp) void; | 2472 | \\extern fn bar(d: &Derp) void; |
| 2434 | \\export fn foo() void { | 2473 | \\export fn foo() void { |
| 2435 | \\ const x = u8(1); | 2474 | \\ var x = u8(1); |
| 2436 | \\ bar(@ptrCast(&c_void, &x)); | 2475 | \\ bar(@ptrCast(&c_void, &x)); |
| 2437 | \\} | 2476 | \\} |
| 2438 | , | 2477 | , |
test/translate_c.zig+167-31| ... | @@ -351,7 +351,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { | ... | @@ -351,7 +351,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 351 | \\ var i: c_int = 0; | 351 | \\ var i: c_int = 0; |
| 352 | \\ while (a > c_uint(0)) { | 352 | \\ while (a > c_uint(0)) { |
| 353 | \\ a >>= @import("std").math.Log2Int(c_uint)(1); | 353 | \\ a >>= @import("std").math.Log2Int(c_uint)(1); |
| 354 | \\ }; | 354 | \\ } |
| 355 | \\ return i; | 355 | \\ return i; |
| 356 | \\} | 356 | \\} |
| 357 | ); | 357 | ); |
| ... | @@ -451,6 +451,28 @@ pub fn addCases(cases: &tests.TranslateCContext) void { | ... | @@ -451,6 +451,28 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 451 | \\} | 451 | \\} |
| 452 | ); | 452 | ); |
| 453 | 453 | ||
| 454 | cases.addC("logical and, logical or on none bool values", | ||
| 455 | \\int and_or_none_bool(int a, float b, void *c) { | ||
| 456 | \\ if (a && b) return 0; | ||
| 457 | \\ if (b && c) return 1; | ||
| 458 | \\ if (a && c) return 2; | ||
| 459 | \\ if (a || b) return 3; | ||
| 460 | \\ if (b || c) return 4; | ||
| 461 | \\ if (a || c) return 5; | ||
| 462 | \\ return 6; | ||
| 463 | \\} | ||
| 464 | , | ||
| 465 | \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?&c_void) c_int { | ||
| 466 | \\ if ((a != 0) and (b != 0)) return 0; | ||
| 467 | \\ if ((b != 0) and (c != null)) return 1; | ||
| 468 | \\ if ((a != 0) and (c != null)) return 2; | ||
| 469 | \\ if ((a != 0) or (b != 0)) return 3; | ||
| 470 | \\ if ((b != 0) or (c != null)) return 4; | ||
| 471 | \\ if ((a != 0) or (c != null)) return 5; | ||
| 472 | \\ return 6; | ||
| 473 | \\} | ||
| 474 | ); | ||
| 475 | |||
| 454 | cases.addC("assign", | 476 | cases.addC("assign", |
| 455 | \\int max(int a) { | 477 | \\int max(int a) { |
| 456 | \\ int tmp; | 478 | \\ int tmp; |
| ... | @@ -498,7 +520,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { | ... | @@ -498,7 +520,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 498 | \\ var i: c_int = 0; | 520 | \\ var i: c_int = 0; |
| 499 | \\ while (a > c_uint(0)) { | 521 | \\ while (a > c_uint(0)) { |
| 500 | \\ a >>= u5(1); | 522 | \\ a >>= u5(1); |
| 501 | \\ }; | 523 | \\ } |
| 502 | \\ return i; | 524 | \\ return i; |
| 503 | \\} | 525 | \\} |
| 504 | ); | 526 | ); |
| ... | @@ -515,11 +537,19 @@ pub fn addCases(cases: &tests.TranslateCContext) void { | ... | @@ -515,11 +537,19 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 515 | 537 | ||
| 516 | cases.addC("function call", | 538 | cases.addC("function call", |
| 517 | \\static void bar(void) { } | 539 | \\static void bar(void) { } |
| 518 | \\void foo(void) { bar(); } | 540 | \\static int baz(void) { return 0; } |
| 541 | \\void foo(void) { | ||
| 542 | \\ bar(); | ||
| 543 | \\ baz(); | ||
| 544 | \\} | ||
| 519 | , | 545 | , |
| 520 | \\pub fn bar() void {} | 546 | \\pub fn bar() void {} |
| 547 | \\pub fn baz() c_int { | ||
| 548 | \\ return 0; | ||
| 549 | \\} | ||
| 521 | \\pub export fn foo() void { | 550 | \\pub export fn foo() void { |
| 522 | \\ bar(); | 551 | \\ bar(); |
| 552 | \\ _ = baz(); | ||
| 523 | \\} | 553 | \\} |
| 524 | ); | 554 | ); |
| 525 | 555 | ||
| ... | @@ -867,32 +897,42 @@ pub fn addCases(cases: &tests.TranslateCContext) void { | ... | @@ -867,32 +897,42 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 867 | \\ while (true) { | 897 | \\ while (true) { |
| 868 | \\ a -= 1; | 898 | \\ a -= 1; |
| 869 | \\ if (!(a != 0)) break; | 899 | \\ if (!(a != 0)) break; |
| 870 | \\ }; | 900 | \\ } |
| 871 | \\ var b: c_int = 2; | 901 | \\ var b: c_int = 2; |
| 872 | \\ while (true) { | 902 | \\ while (true) { |
| 873 | \\ b -= 1; | 903 | \\ b -= 1; |
| 874 | \\ if (!(b != 0)) break; | 904 | \\ if (!(b != 0)) break; |
| 875 | \\ }; | 905 | \\ } |
| 876 | \\} | 906 | \\} |
| 877 | ); | 907 | ); |
| 878 | 908 | ||
| 879 | cases.addC("deref function pointer", | 909 | cases.addC("deref function pointer", |
| 880 | \\void foo(void) {} | 910 | \\void foo(void) {} |
| 881 | \\void baz(void) {} | 911 | \\int baz(void) { return 0; } |
| 882 | \\void bar(void) { | 912 | \\void bar(void) { |
| 883 | \\ void(*f)(void) = foo; | 913 | \\ void(*f)(void) = foo; |
| 914 | \\ int(*b)(void) = baz; | ||
| 884 | \\ f(); | 915 | \\ f(); |
| 885 | \\ (*(f))(); | 916 | \\ (*(f))(); |
| 917 | \\ foo(); | ||
| 918 | \\ b(); | ||
| 919 | \\ (*(b))(); | ||
| 886 | \\ baz(); | 920 | \\ baz(); |
| 887 | \\} | 921 | \\} |
| 888 | , | 922 | , |
| 889 | \\pub export fn foo() void {} | 923 | \\pub export fn foo() void {} |
| 890 | \\pub export fn baz() void {} | 924 | \\pub export fn baz() c_int { |
| 925 | \\ return 0; | ||
| 926 | \\} | ||
| 891 | \\pub export fn bar() void { | 927 | \\pub export fn bar() void { |
| 892 | \\ var f: ?extern fn() void = foo; | 928 | \\ var f: ?extern fn() void = foo; |
| 929 | \\ var b: ?extern fn() c_int = baz; | ||
| 893 | \\ (??f)(); | 930 | \\ (??f)(); |
| 894 | \\ (??f)(); | 931 | \\ (??f)(); |
| 895 | \\ baz(); | 932 | \\ foo(); |
| 933 | \\ _ = (??b)(); | ||
| 934 | \\ _ = (??b)(); | ||
| 935 | \\ _ = baz(); | ||
| 896 | \\} | 936 | \\} |
| 897 | ); | 937 | ); |
| 898 | 938 | ||
| ... | @@ -962,8 +1002,8 @@ pub fn addCases(cases: &tests.TranslateCContext) void { | ... | @@ -962,8 +1002,8 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 962 | \\pub fn foo() void { | 1002 | \\pub fn foo() void { |
| 963 | \\ { | 1003 | \\ { |
| 964 | \\ var i: c_int = 0; | 1004 | \\ var i: c_int = 0; |
| 965 | \\ while (i < 10) : (i += 1) {}; | 1005 | \\ while (i < 10) : (i += 1) {} |
| 966 | \\ }; | 1006 | \\ } |
| 967 | \\} | 1007 | \\} |
| 968 | ); | 1008 | ); |
| 969 | 1009 | ||
| ... | @@ -973,7 +1013,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { | ... | @@ -973,7 +1013,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 973 | \\} | 1013 | \\} |
| 974 | , | 1014 | , |
| 975 | \\pub fn foo() void { | 1015 | \\pub fn foo() void { |
| 976 | \\ while (true) {}; | 1016 | \\ while (true) {} |
| 977 | \\} | 1017 | \\} |
| 978 | ); | 1018 | ); |
| 979 | 1019 | ||
| ... | @@ -987,7 +1027,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { | ... | @@ -987,7 +1027,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 987 | \\pub fn foo() void { | 1027 | \\pub fn foo() void { |
| 988 | \\ while (true) { | 1028 | \\ while (true) { |
| 989 | \\ break; | 1029 | \\ break; |
| 990 | \\ }; | 1030 | \\ } |
| 991 | \\} | 1031 | \\} |
| 992 | ); | 1032 | ); |
| 993 | 1033 | ||
| ... | @@ -1001,7 +1041,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { | ... | @@ -1001,7 +1041,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 1001 | \\pub fn foo() void { | 1041 | \\pub fn foo() void { |
| 1002 | \\ while (true) { | 1042 | \\ while (true) { |
| 1003 | \\ continue; | 1043 | \\ continue; |
| 1004 | \\ }; | 1044 | \\ } |
| 1005 | \\} | 1045 | \\} |
| 1006 | ); | 1046 | ); |
| 1007 | 1047 | ||
| ... | @@ -1058,7 +1098,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { | ... | @@ -1058,7 +1098,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 1058 | \\ { | 1098 | \\ { |
| 1059 | \\ var x_0: c_int = 2; | 1099 | \\ var x_0: c_int = 2; |
| 1060 | \\ x_0 += 1; | 1100 | \\ x_0 += 1; |
| 1061 | \\ }; | 1101 | \\ } |
| 1062 | \\ return x; | 1102 | \\ return x; |
| 1063 | \\} | 1103 | \\} |
| 1064 | ); | 1104 | ); |
| ... | @@ -1083,6 +1123,22 @@ pub fn addCases(cases: &tests.TranslateCContext) void { | ... | @@ -1083,6 +1123,22 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 1083 | \\} | 1123 | \\} |
| 1084 | ); | 1124 | ); |
| 1085 | 1125 | ||
| 1126 | cases.add("bool not", | ||
| 1127 | \\int foo(int a, float b, void *c) { | ||
| 1128 | \\ return !(a == 0); | ||
| 1129 | \\ return !a; | ||
| 1130 | \\ return !b; | ||
| 1131 | \\ return !c; | ||
| 1132 | \\} | ||
| 1133 | , | ||
| 1134 | \\pub fn foo(a: c_int, b: f32, c: ?&c_void) c_int { | ||
| 1135 | \\ return !(a == 0); | ||
| 1136 | \\ return !(a != 0); | ||
| 1137 | \\ return !(b != 0); | ||
| 1138 | \\ return !(c != null); | ||
| 1139 | \\} | ||
| 1140 | ); | ||
| 1141 | |||
| 1086 | cases.add("primitive types included in defined symbols", | 1142 | cases.add("primitive types included in defined symbols", |
| 1087 | \\int foo(int u32) { | 1143 | \\int foo(int u32) { |
| 1088 | \\ return u32; | 1144 | \\ return u32; |
| ... | @@ -1110,29 +1166,109 @@ pub fn addCases(cases: &tests.TranslateCContext) void { | ... | @@ -1110,29 +1166,109 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 1110 | ); | 1166 | ); |
| 1111 | 1167 | ||
| 1112 | cases.add("macro pointer cast", | 1168 | cases.add("macro pointer cast", |
| 1113 | \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) | 1169 | \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) |
| 1114 | , | 1170 | , |
| 1115 | \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast(&NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr(&NRF_GPIO_Type, NRF_GPIO_BASE) else (&NRF_GPIO_Type)(NRF_GPIO_BASE); | 1171 | \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast(&NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr(&NRF_GPIO_Type, NRF_GPIO_BASE) else (&NRF_GPIO_Type)(NRF_GPIO_BASE); |
| 1116 | ); | 1172 | ); |
| 1117 | 1173 | ||
| 1118 | cases.add("if on int", | 1174 | cases.add("if on none bool", |
| 1119 | \\int if_int(int i) { | 1175 | \\enum SomeEnum { A, B, C }; |
| 1120 | \\ if (i) { | 1176 | \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) { |
| 1121 | \\ return 0; | 1177 | \\ if (a) return 0; |
| 1122 | \\ } else { | 1178 | \\ if (b) return 1; |
| 1123 | \\ return 1; | 1179 | \\ if (c) return 2; |
| 1124 | \\ } | 1180 | \\ if (d) return 3; |
| 1181 | \\ return 4; | ||
| 1125 | \\} | 1182 | \\} |
| 1126 | , | 1183 | , |
| 1127 | \\pub fn if_int(i: c_int) c_int { | 1184 | \\pub const A = enum_SomeEnum.A; |
| 1128 | \\ { | 1185 | \\pub const B = enum_SomeEnum.B; |
| 1129 | \\ const _tmp = i; | 1186 | \\pub const C = enum_SomeEnum.C; |
| 1130 | \\ if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { | 1187 | \\pub const enum_SomeEnum = extern enum { |
| 1131 | \\ return 0; | 1188 | \\ A, |
| 1132 | \\ } else { | 1189 | \\ B, |
| 1133 | \\ return 1; | 1190 | \\ C, |
| 1134 | \\ }; | 1191 | \\}; |
| 1135 | \\ }; | 1192 | \\pub fn if_none_bool(a: c_int, b: f32, c: ?&c_void, d: enum_SomeEnum) c_int { |
| 1193 | \\ if (a != 0) return 0; | ||
| 1194 | \\ if (b != 0) return 1; | ||
| 1195 | \\ if (c != null) return 2; | ||
| 1196 | \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3; | ||
| 1197 | \\ return 4; | ||
| 1198 | \\} | ||
| 1199 | ); | ||
| 1200 | |||
| 1201 | cases.add("while on none bool", | ||
| 1202 | \\int while_none_bool(int a, float b, void *c) { | ||
| 1203 | \\ while (a) return 0; | ||
| 1204 | \\ while (b) return 1; | ||
| 1205 | \\ while (c) return 2; | ||
| 1206 | \\ return 3; | ||
| 1207 | \\} | ||
| 1208 | , | ||
| 1209 | \\pub fn while_none_bool(a: c_int, b: f32, c: ?&c_void) c_int { | ||
| 1210 | \\ while (a != 0) return 0; | ||
| 1211 | \\ while (b != 0) return 1; | ||
| 1212 | \\ while (c != null) return 2; | ||
| 1213 | \\ return 3; | ||
| 1214 | \\} | ||
| 1215 | ); | ||
| 1216 | |||
| 1217 | cases.add("for on none bool", | ||
| 1218 | \\int for_none_bool(int a, float b, void *c) { | ||
| 1219 | \\ for (;a;) return 0; | ||
| 1220 | \\ for (;b;) return 1; | ||
| 1221 | \\ for (;c;) return 2; | ||
| 1222 | \\ return 3; | ||
| 1136 | \\} | 1223 | \\} |
| 1224 | , | ||
| 1225 | \\pub fn for_none_bool(a: c_int, b: f32, c: ?&c_void) c_int { | ||
| 1226 | \\ while (a != 0) return 0; | ||
| 1227 | \\ while (b != 0) return 1; | ||
| 1228 | \\ while (c != null) return 2; | ||
| 1229 | \\ return 3; | ||
| 1230 | \\} | ||
| 1231 | ); | ||
| 1232 | |||
| 1233 | cases.add("switch on int", | ||
| 1234 | \\int switch_fn(int i) { | ||
| 1235 | \\ int res = 0; | ||
| 1236 | \\ switch (i) { | ||
| 1237 | \\ case 0: | ||
| 1238 | \\ res = 1; | ||
| 1239 | \\ case 1: | ||
| 1240 | \\ res = 2; | ||
| 1241 | \\ default: | ||
| 1242 | \\ res = 3 * i; | ||
| 1243 | \\ break; | ||
| 1244 | \\ case 2: | ||
| 1245 | \\ res = 5; | ||
| 1246 | \\ } | ||
| 1247 | \\} | ||
| 1248 | , | ||
| 1249 | \\pub fn switch_fn(i: c_int) c_int { | ||
| 1250 | \\ var res: c_int = 0; | ||
| 1251 | \\ __switch: { | ||
| 1252 | \\ __case_2: { | ||
| 1253 | \\ __default: { | ||
| 1254 | \\ __case_1: { | ||
| 1255 | \\ __case_0: { | ||
| 1256 | \\ switch (i) { | ||
| 1257 | \\ 0 => break :__case_0, | ||
| 1258 | \\ 1 => break :__case_1, | ||
| 1259 | \\ else => break :__default, | ||
| 1260 | \\ 2 => break :__case_2, | ||
| 1261 | \\ } | ||
| 1262 | \\ } | ||
| 1263 | \\ res = 1; | ||
| 1264 | \\ } | ||
| 1265 | \\ res = 2; | ||
| 1266 | \\ } | ||
| 1267 | \\ res = (3 * i); | ||
| 1268 | \\ break :__switch; | ||
| 1269 | \\ } | ||
| 1270 | \\ res = 5; | ||
| 1271 | \\ } | ||
| 1272 | \\} | ||
| 1137 | ); | 1273 | ); |
| 1138 | } | 1274 | } |