| author | |
| committer | |
| log | c12704a3395a11c28569ebb160e6ac33091d983a |
| tree | cf2e0055c53eac499b1fb66e2472a2036286afd6 |
| parent | 3f5ca3920a58d44a018ff2a2e277e60813e20d5a |
| parent | d888fa12a88ae7e5332de669b3c3a1dac57f5c19 |
| signature |
stage1: rework tokenizer to match stage228 files changed, 11675 insertions(+), 12678 deletions(-)
CMakeLists.txt+2-2| ... | @@ -292,7 +292,7 @@ set(ZIG0_SOURCES | ... | @@ -292,7 +292,7 @@ set(ZIG0_SOURCES |
| 292 | 292 | ||
| 293 | set(STAGE1_SOURCES | 293 | set(STAGE1_SOURCES |
| 294 | "${CMAKE_SOURCE_DIR}/src/stage1/analyze.cpp" | 294 | "${CMAKE_SOURCE_DIR}/src/stage1/analyze.cpp" |
| 295 | "${CMAKE_SOURCE_DIR}/src/stage1/ast_render.cpp" | 295 | "${CMAKE_SOURCE_DIR}/src/stage1/astgen.cpp" |
| 296 | "${CMAKE_SOURCE_DIR}/src/stage1/bigfloat.cpp" | 296 | "${CMAKE_SOURCE_DIR}/src/stage1/bigfloat.cpp" |
| 297 | "${CMAKE_SOURCE_DIR}/src/stage1/bigint.cpp" | 297 | "${CMAKE_SOURCE_DIR}/src/stage1/bigint.cpp" |
| 298 | "${CMAKE_SOURCE_DIR}/src/stage1/buffer.cpp" | 298 | "${CMAKE_SOURCE_DIR}/src/stage1/buffer.cpp" |
| ... | @@ -307,11 +307,11 @@ set(STAGE1_SOURCES | ... | @@ -307,11 +307,11 @@ set(STAGE1_SOURCES |
| 307 | "${CMAKE_SOURCE_DIR}/src/stage1/os.cpp" | 307 | "${CMAKE_SOURCE_DIR}/src/stage1/os.cpp" |
| 308 | "${CMAKE_SOURCE_DIR}/src/stage1/parser.cpp" | 308 | "${CMAKE_SOURCE_DIR}/src/stage1/parser.cpp" |
| 309 | "${CMAKE_SOURCE_DIR}/src/stage1/range_set.cpp" | 309 | "${CMAKE_SOURCE_DIR}/src/stage1/range_set.cpp" |
| 310 | "${CMAKE_SOURCE_DIR}/src/stage1/softfloat_ext.cpp" | ||
| 310 | "${CMAKE_SOURCE_DIR}/src/stage1/stage1.cpp" | 311 | "${CMAKE_SOURCE_DIR}/src/stage1/stage1.cpp" |
| 311 | "${CMAKE_SOURCE_DIR}/src/stage1/target.cpp" | 312 | "${CMAKE_SOURCE_DIR}/src/stage1/target.cpp" |
| 312 | "${CMAKE_SOURCE_DIR}/src/stage1/tokenizer.cpp" | 313 | "${CMAKE_SOURCE_DIR}/src/stage1/tokenizer.cpp" |
| 313 | "${CMAKE_SOURCE_DIR}/src/stage1/util.cpp" | 314 | "${CMAKE_SOURCE_DIR}/src/stage1/util.cpp" |
| 314 | "${CMAKE_SOURCE_DIR}/src/stage1/softfloat_ext.cpp" | ||
| 315 | ) | 315 | ) |
| 316 | set(OPTIMIZED_C_SOURCES | 316 | set(OPTIMIZED_C_SOURCES |
| 317 | "${CMAKE_SOURCE_DIR}/src/stage1/parse_f128.c" | 317 | "${CMAKE_SOURCE_DIR}/src/stage1/parse_f128.c" |
lib/std/zig/string_literal.zig+1| ... | @@ -107,6 +107,7 @@ pub fn parseAppend(buf: *std.ArrayList(u8), bytes: []const u8) error{OutOfMemory | ... | @@ -107,6 +107,7 @@ pub fn parseAppend(buf: *std.ArrayList(u8), bytes: []const u8) error{OutOfMemory |
| 107 | const hex_str = slice[index + 2 .. index_end]; | 107 | const hex_str = slice[index + 2 .. index_end]; |
| 108 | if (std.fmt.parseUnsigned(u32, hex_str, 16)) |uint| { | 108 | if (std.fmt.parseUnsigned(u32, hex_str, 16)) |uint| { |
| 109 | if (uint <= 0x10ffff) { | 109 | if (uint <= 0x10ffff) { |
| 110 | // TODO this incorrectly depends on endianness | ||
| 110 | try buf.appendSlice(std.mem.toBytes(uint)[0..]); | 111 | try buf.appendSlice(std.mem.toBytes(uint)[0..]); |
| 111 | state = State.Start; | 112 | state = State.Start; |
| 112 | index = index_end; // loop-header increments | 113 | index = index_end; // loop-header increments |
src/stage1.zig+2| ... | @@ -252,6 +252,8 @@ const Error = extern enum { | ... | @@ -252,6 +252,8 @@ const Error = extern enum { |
| 252 | ZigIsTheCCompiler, | 252 | ZigIsTheCCompiler, |
| 253 | FileBusy, | 253 | FileBusy, |
| 254 | Locked, | 254 | Locked, |
| 255 | InvalidCharacter, | ||
| 256 | UnicodePointTooLarge, | ||
| 255 | }; | 257 | }; |
| 256 | 258 | ||
| 257 | // ABI warning | 259 | // ABI warning |
src/stage1/all_types.hpp+60-118| ... | @@ -38,7 +38,7 @@ struct IrInstGenCast; | ... | @@ -38,7 +38,7 @@ struct IrInstGenCast; |
| 38 | struct IrInstGenAlloca; | 38 | struct IrInstGenAlloca; |
| 39 | struct IrInstGenCall; | 39 | struct IrInstGenCall; |
| 40 | struct IrInstGenAwait; | 40 | struct IrInstGenAwait; |
| 41 | struct IrBasicBlockSrc; | 41 | struct Stage1ZirBasicBlock; |
| 42 | struct IrBasicBlockGen; | 42 | struct IrBasicBlockGen; |
| 43 | struct ScopeDecls; | 43 | struct ScopeDecls; |
| 44 | struct ZigWindowsSDK; | 44 | struct ZigWindowsSDK; |
| ... | @@ -51,7 +51,7 @@ struct ResultLocPeerParent; | ... | @@ -51,7 +51,7 @@ struct ResultLocPeerParent; |
| 51 | struct ResultLocBitCast; | 51 | struct ResultLocBitCast; |
| 52 | struct ResultLocCast; | 52 | struct ResultLocCast; |
| 53 | struct ResultLocReturn; | 53 | struct ResultLocReturn; |
| 54 | struct IrExecutableGen; | 54 | struct Stage1Air; |
| 55 | 55 | ||
| 56 | enum FileExt { | 56 | enum FileExt { |
| 57 | FileExtUnknown, | 57 | FileExtUnknown, |
| ... | @@ -110,51 +110,33 @@ enum X64CABIClass { | ... | @@ -110,51 +110,33 @@ enum X64CABIClass { |
| 110 | X64CABIClass_SSE, | 110 | X64CABIClass_SSE, |
| 111 | }; | 111 | }; |
| 112 | 112 | ||
| 113 | struct IrExecutableSrc { | 113 | struct Stage1Zir { |
| 114 | ZigList<IrBasicBlockSrc *> basic_block_list; | 114 | ZigList<Stage1ZirBasicBlock *> basic_block_list; |
| 115 | Buf *name; | 115 | Buf *name; |
| 116 | ZigFn *name_fn; | 116 | ZigFn *name_fn; |
| 117 | size_t mem_slot_count; | ||
| 118 | size_t next_debug_id; | ||
| 119 | size_t *backward_branch_count; | ||
| 120 | size_t *backward_branch_quota; | ||
| 121 | ZigFn *fn_entry; | ||
| 122 | Buf *c_import_buf; | ||
| 123 | AstNode *source_node; | ||
| 124 | IrExecutableGen *parent_exec; | ||
| 125 | IrAnalyze *analysis; | ||
| 126 | Scope *begin_scope; | 117 | Scope *begin_scope; |
| 127 | ErrorMsg *first_err_trace_msg; | 118 | ErrorMsg *first_err_trace_msg; |
| 128 | ZigList<Tld *> tld_list; | 119 | ZigList<Tld *> tld_list; |
| 129 | 120 | ||
| 130 | bool is_inline; | 121 | bool is_inline; |
| 131 | bool is_generic_instantiation; | ||
| 132 | bool need_err_code_spill; | 122 | bool need_err_code_spill; |
| 133 | |||
| 134 | // This is a function for use in the debugger to print | ||
| 135 | // the source location. | ||
| 136 | void src(); | ||
| 137 | }; | 123 | }; |
| 138 | 124 | ||
| 139 | struct IrExecutableGen { | 125 | struct Stage1Air { |
| 140 | ZigList<IrBasicBlockGen *> basic_block_list; | 126 | ZigList<IrBasicBlockGen *> basic_block_list; |
| 141 | Buf *name; | 127 | Buf *name; |
| 142 | ZigFn *name_fn; | 128 | ZigFn *name_fn; |
| 143 | size_t mem_slot_count; | 129 | size_t mem_slot_count; |
| 144 | size_t next_debug_id; | 130 | size_t next_debug_id; |
| 145 | size_t *backward_branch_count; | ||
| 146 | size_t *backward_branch_quota; | ||
| 147 | ZigFn *fn_entry; | ||
| 148 | Buf *c_import_buf; | 131 | Buf *c_import_buf; |
| 149 | AstNode *source_node; | 132 | AstNode *source_node; |
| 150 | IrExecutableGen *parent_exec; | 133 | Stage1Air *parent_exec; |
| 151 | IrExecutableSrc *source_exec; | 134 | Stage1Zir *source_exec; |
| 152 | Scope *begin_scope; | 135 | Scope *begin_scope; |
| 153 | ErrorMsg *first_err_trace_msg; | 136 | ErrorMsg *first_err_trace_msg; |
| 154 | ZigList<Tld *> tld_list; | 137 | ZigList<Tld *> tld_list; |
| 155 | 138 | ||
| 156 | bool is_inline; | 139 | bool is_inline; |
| 157 | bool is_generic_instantiation; | ||
| 158 | bool need_err_code_spill; | 140 | bool need_err_code_spill; |
| 159 | 141 | ||
| 160 | // This is a function for use in the debugger to print | 142 | // This is a function for use in the debugger to print |
| ... | @@ -670,7 +652,7 @@ enum NodeType { | ... | @@ -670,7 +652,7 @@ enum NodeType { |
| 670 | NodeTypeIntLiteral, | 652 | NodeTypeIntLiteral, |
| 671 | NodeTypeStringLiteral, | 653 | NodeTypeStringLiteral, |
| 672 | NodeTypeCharLiteral, | 654 | NodeTypeCharLiteral, |
| 673 | NodeTypeSymbol, | 655 | NodeTypeIdentifier, |
| 674 | NodeTypePrefixOpExpr, | 656 | NodeTypePrefixOpExpr, |
| 675 | NodeTypePointerType, | 657 | NodeTypePointerType, |
| 676 | NodeTypeFnCallExpr, | 658 | NodeTypeFnCallExpr, |
| ... | @@ -710,6 +692,7 @@ enum NodeType { | ... | @@ -710,6 +692,7 @@ enum NodeType { |
| 710 | NodeTypeAwaitExpr, | 692 | NodeTypeAwaitExpr, |
| 711 | NodeTypeSuspend, | 693 | NodeTypeSuspend, |
| 712 | NodeTypeAnyFrameType, | 694 | NodeTypeAnyFrameType, |
| 695 | // main_token points to the identifier. | ||
| 713 | NodeTypeEnumLiteral, | 696 | NodeTypeEnumLiteral, |
| 714 | NodeTypeAnyTypeField, | 697 | NodeTypeAnyTypeField, |
| 715 | }; | 698 | }; |
| ... | @@ -733,7 +716,8 @@ struct AstNodeFnProto { | ... | @@ -733,7 +716,8 @@ struct AstNodeFnProto { |
| 733 | AstNode *section_expr; | 716 | AstNode *section_expr; |
| 734 | // populated if the "callconv(S)" is present | 717 | // populated if the "callconv(S)" is present |
| 735 | AstNode *callconv_expr; | 718 | AstNode *callconv_expr; |
| 736 | Buf doc_comments; | 719 | |
| 720 | TokenIndex doc_comments; | ||
| 737 | 721 | ||
| 738 | // This is set based only on the existence of a noinline or inline keyword. | 722 | // This is set based only on the existence of a noinline or inline keyword. |
| 739 | // This is then resolved to an is_noinline bool and (potentially .Inline) | 723 | // This is then resolved to an is_noinline bool and (potentially .Inline) |
| ... | @@ -755,8 +739,8 @@ struct AstNodeFnDef { | ... | @@ -755,8 +739,8 @@ struct AstNodeFnDef { |
| 755 | struct AstNodeParamDecl { | 739 | struct AstNodeParamDecl { |
| 756 | Buf *name; | 740 | Buf *name; |
| 757 | AstNode *type; | 741 | AstNode *type; |
| 758 | Token *anytype_token; | 742 | TokenIndex doc_comments; |
| 759 | Buf doc_comments; | 743 | TokenIndex anytype_token; |
| 760 | bool is_noalias; | 744 | bool is_noalias; |
| 761 | bool is_comptime; | 745 | bool is_comptime; |
| 762 | bool is_var_args; | 746 | bool is_var_args; |
| ... | @@ -799,9 +783,9 @@ struct AstNodeVariableDeclaration { | ... | @@ -799,9 +783,9 @@ struct AstNodeVariableDeclaration { |
| 799 | AstNode *align_expr; | 783 | AstNode *align_expr; |
| 800 | // populated if the "section(S)" is present | 784 | // populated if the "section(S)" is present |
| 801 | AstNode *section_expr; | 785 | AstNode *section_expr; |
| 802 | Token *threadlocal_tok; | 786 | TokenIndex doc_comments; |
| 803 | Buf doc_comments; | ||
| 804 | 787 | ||
| 788 | TokenIndex threadlocal_tok; | ||
| 805 | VisibMod visib_mod; | 789 | VisibMod visib_mod; |
| 806 | bool is_const; | 790 | bool is_const; |
| 807 | bool is_comptime; | 791 | bool is_comptime; |
| ... | @@ -935,13 +919,14 @@ struct AstNodePrefixOpExpr { | ... | @@ -935,13 +919,14 @@ struct AstNodePrefixOpExpr { |
| 935 | }; | 919 | }; |
| 936 | 920 | ||
| 937 | struct AstNodePointerType { | 921 | struct AstNodePointerType { |
| 938 | Token *star_token; | 922 | TokenIndex star_token; |
| 923 | TokenIndex allow_zero_token; | ||
| 924 | TokenIndex bit_offset_start; | ||
| 925 | TokenIndex host_int_bytes; | ||
| 926 | |||
| 939 | AstNode *sentinel; | 927 | AstNode *sentinel; |
| 940 | AstNode *align_expr; | 928 | AstNode *align_expr; |
| 941 | BigInt *bit_offset_start; | ||
| 942 | BigInt *host_int_bytes; | ||
| 943 | AstNode *op_expr; | 929 | AstNode *op_expr; |
| 944 | Token *allow_zero_token; | ||
| 945 | bool is_const; | 930 | bool is_const; |
| 946 | bool is_volatile; | 931 | bool is_volatile; |
| 947 | }; | 932 | }; |
| ... | @@ -956,7 +941,7 @@ struct AstNodeArrayType { | ... | @@ -956,7 +941,7 @@ struct AstNodeArrayType { |
| 956 | AstNode *sentinel; | 941 | AstNode *sentinel; |
| 957 | AstNode *child_type; | 942 | AstNode *child_type; |
| 958 | AstNode *align_expr; | 943 | AstNode *align_expr; |
| 959 | Token *allow_zero_token; | 944 | TokenIndex allow_zero_token; |
| 960 | bool is_const; | 945 | bool is_const; |
| 961 | bool is_volatile; | 946 | bool is_volatile; |
| 962 | }; | 947 | }; |
| ... | @@ -974,11 +959,11 @@ struct AstNodeIfBoolExpr { | ... | @@ -974,11 +959,11 @@ struct AstNodeIfBoolExpr { |
| 974 | 959 | ||
| 975 | struct AstNodeTryExpr { | 960 | struct AstNodeTryExpr { |
| 976 | Buf *var_symbol; | 961 | Buf *var_symbol; |
| 977 | bool var_is_ptr; | ||
| 978 | AstNode *target_node; | 962 | AstNode *target_node; |
| 979 | AstNode *then_node; | 963 | AstNode *then_node; |
| 980 | AstNode *else_node; | 964 | AstNode *else_node; |
| 981 | Buf *err_symbol; | 965 | Buf *err_symbol; |
| 966 | bool var_is_ptr; | ||
| 982 | }; | 967 | }; |
| 983 | 968 | ||
| 984 | struct AstNodeTestExpr { | 969 | struct AstNodeTestExpr { |
| ... | @@ -993,12 +978,12 @@ struct AstNodeWhileExpr { | ... | @@ -993,12 +978,12 @@ struct AstNodeWhileExpr { |
| 993 | Buf *name; | 978 | Buf *name; |
| 994 | AstNode *condition; | 979 | AstNode *condition; |
| 995 | Buf *var_symbol; | 980 | Buf *var_symbol; |
| 996 | bool var_is_ptr; | ||
| 997 | AstNode *continue_expr; | 981 | AstNode *continue_expr; |
| 998 | AstNode *body; | 982 | AstNode *body; |
| 999 | AstNode *else_node; | 983 | AstNode *else_node; |
| 1000 | Buf *err_symbol; | 984 | Buf *err_symbol; |
| 1001 | bool is_inline; | 985 | bool is_inline; |
| 986 | bool var_is_ptr; | ||
| 1002 | }; | 987 | }; |
| 1003 | 988 | ||
| 1004 | struct AstNodeForExpr { | 989 | struct AstNodeForExpr { |
| ... | @@ -1070,7 +1055,7 @@ struct AsmToken { | ... | @@ -1070,7 +1055,7 @@ struct AsmToken { |
| 1070 | }; | 1055 | }; |
| 1071 | 1056 | ||
| 1072 | struct AstNodeAsmExpr { | 1057 | struct AstNodeAsmExpr { |
| 1073 | Token *volatile_token; | 1058 | TokenIndex volatile_token; |
| 1074 | AstNode *asm_template; | 1059 | AstNode *asm_template; |
| 1075 | ZigList<AsmOutput*> output_list; | 1060 | ZigList<AsmOutput*> output_list; |
| 1076 | ZigList<AsmInput*> input_list; | 1061 | ZigList<AsmInput*> input_list; |
| ... | @@ -1094,7 +1079,7 @@ struct AstNodeContainerDecl { | ... | @@ -1094,7 +1079,7 @@ struct AstNodeContainerDecl { |
| 1094 | AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T)) | 1079 | AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T)) |
| 1095 | ZigList<AstNode *> fields; | 1080 | ZigList<AstNode *> fields; |
| 1096 | ZigList<AstNode *> decls; | 1081 | ZigList<AstNode *> decls; |
| 1097 | Buf doc_comments; | 1082 | TokenIndex doc_comments; |
| 1098 | 1083 | ||
| 1099 | ContainerKind kind; | 1084 | ContainerKind kind; |
| 1100 | ContainerLayout layout; | 1085 | ContainerLayout layout; |
| ... | @@ -1103,7 +1088,7 @@ struct AstNodeContainerDecl { | ... | @@ -1103,7 +1088,7 @@ struct AstNodeContainerDecl { |
| 1103 | }; | 1088 | }; |
| 1104 | 1089 | ||
| 1105 | struct AstNodeErrorSetField { | 1090 | struct AstNodeErrorSetField { |
| 1106 | Buf doc_comments; | 1091 | TokenIndex doc_comments; |
| 1107 | AstNode *field_name; | 1092 | AstNode *field_name; |
| 1108 | }; | 1093 | }; |
| 1109 | 1094 | ||
| ... | @@ -1118,28 +1103,8 @@ struct AstNodeStructField { | ... | @@ -1118,28 +1103,8 @@ struct AstNodeStructField { |
| 1118 | AstNode *value; | 1103 | AstNode *value; |
| 1119 | // populated if the "align(A)" is present | 1104 | // populated if the "align(A)" is present |
| 1120 | AstNode *align_expr; | 1105 | AstNode *align_expr; |
| 1121 | Buf doc_comments; | 1106 | TokenIndex doc_comments; |
| 1122 | Token *comptime_token; | 1107 | TokenIndex comptime_token; |
| 1123 | }; | ||
| 1124 | |||
| 1125 | struct AstNodeStringLiteral { | ||
| 1126 | Buf *buf; | ||
| 1127 | }; | ||
| 1128 | |||
| 1129 | struct AstNodeCharLiteral { | ||
| 1130 | uint32_t value; | ||
| 1131 | }; | ||
| 1132 | |||
| 1133 | struct AstNodeFloatLiteral { | ||
| 1134 | BigFloat *bigfloat; | ||
| 1135 | |||
| 1136 | // overflow is true if when parsing the number, we discovered it would not | ||
| 1137 | // fit without losing data in a double | ||
| 1138 | bool overflow; | ||
| 1139 | }; | ||
| 1140 | |||
| 1141 | struct AstNodeIntLiteral { | ||
| 1142 | BigInt *bigint; | ||
| 1143 | }; | 1108 | }; |
| 1144 | 1109 | ||
| 1145 | struct AstNodeStructValueField { | 1110 | struct AstNodeStructValueField { |
| ... | @@ -1158,17 +1123,12 @@ struct AstNodeContainerInitExpr { | ... | @@ -1158,17 +1123,12 @@ struct AstNodeContainerInitExpr { |
| 1158 | ContainerInitKind kind; | 1123 | ContainerInitKind kind; |
| 1159 | }; | 1124 | }; |
| 1160 | 1125 | ||
| 1161 | struct AstNodeNullLiteral { | 1126 | struct AstNodeIdentifier { |
| 1162 | }; | 1127 | Buf *name; |
| 1163 | |||
| 1164 | struct AstNodeUndefinedLiteral { | ||
| 1165 | }; | ||
| 1166 | |||
| 1167 | struct AstNodeThisLiteral { | ||
| 1168 | }; | 1128 | }; |
| 1169 | 1129 | ||
| 1170 | struct AstNodeSymbolExpr { | 1130 | struct AstNodeEnumLiteral { |
| 1171 | Buf *symbol; | 1131 | Buf *name; |
| 1172 | }; | 1132 | }; |
| 1173 | 1133 | ||
| 1174 | struct AstNodeBoolLiteral { | 1134 | struct AstNodeBoolLiteral { |
| ... | @@ -1188,13 +1148,6 @@ struct AstNodeContinueExpr { | ... | @@ -1188,13 +1148,6 @@ struct AstNodeContinueExpr { |
| 1188 | Buf *name; | 1148 | Buf *name; |
| 1189 | }; | 1149 | }; |
| 1190 | 1150 | ||
| 1191 | struct AstNodeUnreachableExpr { | ||
| 1192 | }; | ||
| 1193 | |||
| 1194 | |||
| 1195 | struct AstNodeErrorType { | ||
| 1196 | }; | ||
| 1197 | |||
| 1198 | struct AstNodeAwaitExpr { | 1151 | struct AstNodeAwaitExpr { |
| 1199 | AstNode *expr; | 1152 | AstNode *expr; |
| 1200 | }; | 1153 | }; |
| ... | @@ -1207,16 +1160,10 @@ struct AstNodeAnyFrameType { | ... | @@ -1207,16 +1160,10 @@ struct AstNodeAnyFrameType { |
| 1207 | AstNode *payload_type; // can be NULL | 1160 | AstNode *payload_type; // can be NULL |
| 1208 | }; | 1161 | }; |
| 1209 | 1162 | ||
| 1210 | struct AstNodeEnumLiteral { | ||
| 1211 | Token *period; | ||
| 1212 | Token *identifier; | ||
| 1213 | }; | ||
| 1214 | |||
| 1215 | struct AstNode { | 1163 | struct AstNode { |
| 1216 | enum NodeType type; | 1164 | enum NodeType type; |
| 1165 | TokenIndex main_token; | ||
| 1217 | bool already_traced_this_node; | 1166 | bool already_traced_this_node; |
| 1218 | size_t line; | ||
| 1219 | size_t column; | ||
| 1220 | ZigType *owner; | 1167 | ZigType *owner; |
| 1221 | union { | 1168 | union { |
| 1222 | AstNodeFnDef fn_def; | 1169 | AstNodeFnDef fn_def; |
| ... | @@ -1252,29 +1199,24 @@ struct AstNode { | ... | @@ -1252,29 +1199,24 @@ struct AstNode { |
| 1252 | AstNodePtrDerefExpr ptr_deref_expr; | 1199 | AstNodePtrDerefExpr ptr_deref_expr; |
| 1253 | AstNodeContainerDecl container_decl; | 1200 | AstNodeContainerDecl container_decl; |
| 1254 | AstNodeStructField struct_field; | 1201 | AstNodeStructField struct_field; |
| 1255 | AstNodeStringLiteral string_literal; | ||
| 1256 | AstNodeCharLiteral char_literal; | ||
| 1257 | AstNodeFloatLiteral float_literal; | ||
| 1258 | AstNodeIntLiteral int_literal; | ||
| 1259 | AstNodeContainerInitExpr container_init_expr; | 1202 | AstNodeContainerInitExpr container_init_expr; |
| 1260 | AstNodeStructValueField struct_val_field; | 1203 | AstNodeStructValueField struct_val_field; |
| 1261 | AstNodeNullLiteral null_literal; | ||
| 1262 | AstNodeUndefinedLiteral undefined_literal; | ||
| 1263 | AstNodeThisLiteral this_literal; | ||
| 1264 | AstNodeSymbolExpr symbol_expr; | ||
| 1265 | AstNodeBoolLiteral bool_literal; | 1204 | AstNodeBoolLiteral bool_literal; |
| 1266 | AstNodeBreakExpr break_expr; | 1205 | AstNodeBreakExpr break_expr; |
| 1267 | AstNodeContinueExpr continue_expr; | 1206 | AstNodeContinueExpr continue_expr; |
| 1268 | AstNodeUnreachableExpr unreachable_expr; | ||
| 1269 | AstNodeArrayType array_type; | 1207 | AstNodeArrayType array_type; |
| 1270 | AstNodeInferredArrayType inferred_array_type; | 1208 | AstNodeInferredArrayType inferred_array_type; |
| 1271 | AstNodeErrorType error_type; | ||
| 1272 | AstNodeErrorSetDecl err_set_decl; | 1209 | AstNodeErrorSetDecl err_set_decl; |
| 1273 | AstNodeErrorSetField err_set_field; | 1210 | AstNodeErrorSetField err_set_field; |
| 1274 | AstNodeResumeExpr resume_expr; | 1211 | AstNodeResumeExpr resume_expr; |
| 1275 | AstNodeAwaitExpr await_expr; | 1212 | AstNodeAwaitExpr await_expr; |
| 1276 | AstNodeSuspend suspend; | 1213 | AstNodeSuspend suspend; |
| 1277 | AstNodeAnyFrameType anyframe_type; | 1214 | AstNodeAnyFrameType anyframe_type; |
| 1215 | |||
| 1216 | // These are part of an astgen workaround to use less memory by | ||
| 1217 | // memoizing into the AST. Once astgen is modified to only run once | ||
| 1218 | // per corresponding source, this workaround can be removed. | ||
| 1219 | AstNodeIdentifier identifier; | ||
| 1278 | AstNodeEnumLiteral enum_literal; | 1220 | AstNodeEnumLiteral enum_literal; |
| 1279 | } data; | 1221 | } data; |
| 1280 | 1222 | ||
| ... | @@ -1409,9 +1351,11 @@ struct ZigPackage { | ... | @@ -1409,9 +1351,11 @@ struct ZigPackage { |
| 1409 | struct RootStruct { | 1351 | struct RootStruct { |
| 1410 | ZigPackage *package; | 1352 | ZigPackage *package; |
| 1411 | Buf *path; // relative to root_package->root_src_dir | 1353 | Buf *path; // relative to root_package->root_src_dir |
| 1412 | ZigList<size_t> *line_offsets; | ||
| 1413 | Buf *source_code; | 1354 | Buf *source_code; |
| 1414 | ZigLLVMDIFile *di_file; | 1355 | ZigLLVMDIFile *di_file; |
| 1356 | size_t token_count; | ||
| 1357 | TokenId *token_ids; | ||
| 1358 | TokenLoc *token_locs; | ||
| 1415 | }; | 1359 | }; |
| 1416 | 1360 | ||
| 1417 | enum StructSpecial { | 1361 | enum StructSpecial { |
| ... | @@ -1703,10 +1647,9 @@ struct ZigFn { | ... | @@ -1703,10 +1647,9 @@ struct ZigFn { |
| 1703 | // in the case of async functions this is the implicit return type according to the | 1647 | // in the case of async functions this is the implicit return type according to the |
| 1704 | // zig source code, not according to zig ir | 1648 | // zig source code, not according to zig ir |
| 1705 | ZigType *src_implicit_return_type; | 1649 | ZigType *src_implicit_return_type; |
| 1706 | IrExecutableSrc *ir_executable; | 1650 | Stage1Zir *stage1_zir; |
| 1707 | IrExecutableGen analyzed_executable; | 1651 | Stage1Air analyzed_executable; |
| 1708 | size_t prealloc_bbc; | 1652 | size_t branch_quota; |
| 1709 | size_t prealloc_backward_branch_quota; | ||
| 1710 | AstNode **param_source_nodes; | 1653 | AstNode **param_source_nodes; |
| 1711 | Buf **param_names; | 1654 | Buf **param_names; |
| 1712 | IrInstGen *err_code_spill; | 1655 | IrInstGen *err_code_spill; |
| ... | @@ -2326,11 +2269,11 @@ struct ScopeBlock { | ... | @@ -2326,11 +2269,11 @@ struct ScopeBlock { |
| 2326 | Scope base; | 2269 | Scope base; |
| 2327 | 2270 | ||
| 2328 | Buf *name; | 2271 | Buf *name; |
| 2329 | IrBasicBlockSrc *end_block; | 2272 | Stage1ZirBasicBlock *end_block; |
| 2330 | IrInstSrc *is_comptime; | 2273 | IrInstSrc *is_comptime; |
| 2331 | ResultLocPeerParent *peer_parent; | 2274 | ResultLocPeerParent *peer_parent; |
| 2332 | ZigList<IrInstSrc *> *incoming_values; | 2275 | ZigList<IrInstSrc *> *incoming_values; |
| 2333 | ZigList<IrBasicBlockSrc *> *incoming_blocks; | 2276 | ZigList<Stage1ZirBasicBlock *> *incoming_blocks; |
| 2334 | 2277 | ||
| 2335 | AstNode *safety_set_node; | 2278 | AstNode *safety_set_node; |
| 2336 | AstNode *fast_math_set_node; | 2279 | AstNode *fast_math_set_node; |
| ... | @@ -2382,11 +2325,11 @@ struct ScopeLoop { | ... | @@ -2382,11 +2325,11 @@ struct ScopeLoop { |
| 2382 | 2325 | ||
| 2383 | LVal lval; | 2326 | LVal lval; |
| 2384 | Buf *name; | 2327 | Buf *name; |
| 2385 | IrBasicBlockSrc *break_block; | 2328 | Stage1ZirBasicBlock *break_block; |
| 2386 | IrBasicBlockSrc *continue_block; | 2329 | Stage1ZirBasicBlock *continue_block; |
| 2387 | IrInstSrc *is_comptime; | 2330 | IrInstSrc *is_comptime; |
| 2388 | ZigList<IrInstSrc *> *incoming_values; | 2331 | ZigList<IrInstSrc *> *incoming_values; |
| 2389 | ZigList<IrBasicBlockSrc *> *incoming_blocks; | 2332 | ZigList<Stage1ZirBasicBlock *> *incoming_blocks; |
| 2390 | ResultLocPeerParent *peer_parent; | 2333 | ResultLocPeerParent *peer_parent; |
| 2391 | ScopeExpr *spill_scope; | 2334 | ScopeExpr *spill_scope; |
| 2392 | 2335 | ||
| ... | @@ -2497,7 +2440,7 @@ enum AtomicRmwOp { | ... | @@ -2497,7 +2440,7 @@ enum AtomicRmwOp { |
| 2497 | // to another basic block. | 2440 | // to another basic block. |
| 2498 | // Phi instructions must be first in a basic block. | 2441 | // Phi instructions must be first in a basic block. |
| 2499 | // The last instruction in a basic block must be of type unreachable. | 2442 | // The last instruction in a basic block must be of type unreachable. |
| 2500 | struct IrBasicBlockSrc { | 2443 | struct Stage1ZirBasicBlock { |
| 2501 | ZigList<IrInstSrc *> instruction_list; | 2444 | ZigList<IrInstSrc *> instruction_list; |
| 2502 | IrBasicBlockGen *child; | 2445 | IrBasicBlockGen *child; |
| 2503 | Scope *scope; | 2446 | Scope *scope; |
| ... | @@ -2772,8 +2715,7 @@ enum IrInstGenId { | ... | @@ -2772,8 +2715,7 @@ enum IrInstGenId { |
| 2772 | IrInstGenIdExtern, | 2715 | IrInstGenIdExtern, |
| 2773 | }; | 2716 | }; |
| 2774 | 2717 | ||
| 2775 | // Common fields between IrInstSrc and IrInstGen. This allows future passes | 2718 | // Common fields between IrInstSrc and IrInstGen. |
| 2776 | // after pass2 to be added to zig. | ||
| 2777 | struct IrInst { | 2719 | struct IrInst { |
| 2778 | // if ref_count is zero and the instruction has no side effects, | 2720 | // if ref_count is zero and the instruction has no side effects, |
| 2779 | // the instruction can be omitted in codegen | 2721 | // the instruction can be omitted in codegen |
| ... | @@ -2801,7 +2743,7 @@ struct IrInstSrc { | ... | @@ -2801,7 +2743,7 @@ struct IrInstSrc { |
| 2801 | // can find the instruction that corresponds to this value in the "new ir" | 2743 | // can find the instruction that corresponds to this value in the "new ir" |
| 2802 | // with this child field. | 2744 | // with this child field. |
| 2803 | IrInstGen *child; | 2745 | IrInstGen *child; |
| 2804 | IrBasicBlockSrc *owner_bb; | 2746 | Stage1ZirBasicBlock *owner_bb; |
| 2805 | 2747 | ||
| 2806 | // for debugging purposes, these are useful to call to inspect the instruction | 2748 | // for debugging purposes, these are useful to call to inspect the instruction |
| 2807 | void dump(); | 2749 | void dump(); |
| ... | @@ -2846,8 +2788,8 @@ struct IrInstSrcCondBr { | ... | @@ -2846,8 +2788,8 @@ struct IrInstSrcCondBr { |
| 2846 | IrInstSrc base; | 2788 | IrInstSrc base; |
| 2847 | 2789 | ||
| 2848 | IrInstSrc *condition; | 2790 | IrInstSrc *condition; |
| 2849 | IrBasicBlockSrc *then_block; | 2791 | Stage1ZirBasicBlock *then_block; |
| 2850 | IrBasicBlockSrc *else_block; | 2792 | Stage1ZirBasicBlock *else_block; |
| 2851 | IrInstSrc *is_comptime; | 2793 | IrInstSrc *is_comptime; |
| 2852 | ResultLoc *result_loc; | 2794 | ResultLoc *result_loc; |
| 2853 | }; | 2795 | }; |
| ... | @@ -2863,7 +2805,7 @@ struct IrInstGenCondBr { | ... | @@ -2863,7 +2805,7 @@ struct IrInstGenCondBr { |
| 2863 | struct IrInstSrcBr { | 2805 | struct IrInstSrcBr { |
| 2864 | IrInstSrc base; | 2806 | IrInstSrc base; |
| 2865 | 2807 | ||
| 2866 | IrBasicBlockSrc *dest_block; | 2808 | Stage1ZirBasicBlock *dest_block; |
| 2867 | IrInstSrc *is_comptime; | 2809 | IrInstSrc *is_comptime; |
| 2868 | }; | 2810 | }; |
| 2869 | 2811 | ||
| ... | @@ -2875,14 +2817,14 @@ struct IrInstGenBr { | ... | @@ -2875,14 +2817,14 @@ struct IrInstGenBr { |
| 2875 | 2817 | ||
| 2876 | struct IrInstSrcSwitchBrCase { | 2818 | struct IrInstSrcSwitchBrCase { |
| 2877 | IrInstSrc *value; | 2819 | IrInstSrc *value; |
| 2878 | IrBasicBlockSrc *block; | 2820 | Stage1ZirBasicBlock *block; |
| 2879 | }; | 2821 | }; |
| 2880 | 2822 | ||
| 2881 | struct IrInstSrcSwitchBr { | 2823 | struct IrInstSrcSwitchBr { |
| 2882 | IrInstSrc base; | 2824 | IrInstSrc base; |
| 2883 | 2825 | ||
| 2884 | IrInstSrc *target_value; | 2826 | IrInstSrc *target_value; |
| 2885 | IrBasicBlockSrc *else_block; | 2827 | Stage1ZirBasicBlock *else_block; |
| 2886 | size_t case_count; | 2828 | size_t case_count; |
| 2887 | IrInstSrcSwitchBrCase *cases; | 2829 | IrInstSrcSwitchBrCase *cases; |
| 2888 | IrInstSrc *is_comptime; | 2830 | IrInstSrc *is_comptime; |
| ... | @@ -2928,7 +2870,7 @@ struct IrInstSrcPhi { | ... | @@ -2928,7 +2870,7 @@ struct IrInstSrcPhi { |
| 2928 | IrInstSrc base; | 2870 | IrInstSrc base; |
| 2929 | 2871 | ||
| 2930 | size_t incoming_count; | 2872 | size_t incoming_count; |
| 2931 | IrBasicBlockSrc **incoming_blocks; | 2873 | Stage1ZirBasicBlock **incoming_blocks; |
| 2932 | IrInstSrc **incoming_values; | 2874 | IrInstSrc **incoming_values; |
| 2933 | ResultLocPeerParent *peer_parent; | 2875 | ResultLocPeerParent *peer_parent; |
| 2934 | }; | 2876 | }; |
| ... | @@ -4592,7 +4534,7 @@ struct ResultLocPeerParent { | ... | @@ -4592,7 +4534,7 @@ struct ResultLocPeerParent { |
| 4592 | 4534 | ||
| 4593 | bool skipped; | 4535 | bool skipped; |
| 4594 | bool done_resuming; | 4536 | bool done_resuming; |
| 4595 | IrBasicBlockSrc *end_bb; | 4537 | Stage1ZirBasicBlock *end_bb; |
| 4596 | ResultLoc *parent; | 4538 | ResultLoc *parent; |
| 4597 | ZigList<ResultLocPeer *> peers; | 4539 | ZigList<ResultLocPeer *> peers; |
| 4598 | ZigType *resolved_type; | 4540 | ZigType *resolved_type; |
| ... | @@ -4603,7 +4545,7 @@ struct ResultLocPeer { | ... | @@ -4603,7 +4545,7 @@ struct ResultLocPeer { |
| 4603 | ResultLoc base; | 4545 | ResultLoc base; |
| 4604 | 4546 | ||
| 4605 | ResultLocPeerParent *parent; | 4547 | ResultLocPeerParent *parent; |
| 4606 | IrBasicBlockSrc *next_bb; | 4548 | Stage1ZirBasicBlock *next_bb; |
| 4607 | IrSuspendPosition suspend_pos; | 4549 | IrSuspendPosition suspend_pos; |
| 4608 | }; | 4550 | }; |
| 4609 | 4551 |
src/stage1/analyze.cpp+97-91| ... | @@ -6,9 +6,9 @@ | ... | @@ -6,9 +6,9 @@ |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include "analyze.hpp" | 8 | #include "analyze.hpp" |
| 9 | #include "ast_render.hpp" | ||
| 10 | #include "codegen.hpp" | 9 | #include "codegen.hpp" |
| 11 | #include "error.hpp" | 10 | #include "error.hpp" |
| 11 | #include "astgen.hpp" | ||
| 12 | #include "ir.hpp" | 12 | #include "ir.hpp" |
| 13 | #include "ir_print.hpp" | 13 | #include "ir_print.hpp" |
| 14 | #include "os.hpp" | 14 | #include "os.hpp" |
| ... | @@ -41,41 +41,44 @@ static bool is_top_level_struct(ZigType *import) { | ... | @@ -41,41 +41,44 @@ static bool is_top_level_struct(ZigType *import) { |
| 41 | return import->id == ZigTypeIdStruct && import->data.structure.root_struct != nullptr; | 41 | return import->id == ZigTypeIdStruct && import->data.structure.root_struct != nullptr; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ZigType *owner, Token *token, Buf *msg) { | 44 | static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ZigType *owner, |
| 45 | TokenIndex token, Buf *msg) | ||
| 46 | { | ||
| 45 | assert(is_top_level_struct(owner)); | 47 | assert(is_top_level_struct(owner)); |
| 46 | RootStruct *root_struct = owner->data.structure.root_struct; | 48 | RootStruct *root_struct = owner->data.structure.root_struct; |
| 47 | 49 | uint32_t byte_offset = root_struct->token_locs[token].offset; | |
| 48 | ErrorMsg *err = err_msg_create_with_line(root_struct->path, token->start_line, token->start_column, | 50 | ErrorMsg *err = err_msg_create_with_offset(root_struct->path, byte_offset, |
| 49 | root_struct->source_code, root_struct->line_offsets, msg); | 51 | buf_ptr(root_struct->source_code), msg); |
| 50 | 52 | ||
| 51 | err_msg_add_note(parent_msg, err); | 53 | err_msg_add_note(parent_msg, err); |
| 52 | return err; | 54 | return err; |
| 53 | } | 55 | } |
| 54 | 56 | ||
| 55 | ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg) { | 57 | ErrorMsg *add_token_error_offset(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg, |
| 58 | uint32_t bad_index) | ||
| 59 | { | ||
| 56 | assert(is_top_level_struct(owner)); | 60 | assert(is_top_level_struct(owner)); |
| 57 | RootStruct *root_struct = owner->data.structure.root_struct; | 61 | RootStruct *root_struct = owner->data.structure.root_struct; |
| 58 | ErrorMsg *err = err_msg_create_with_line(root_struct->path, token->start_line, token->start_column, | 62 | uint32_t byte_offset = root_struct->token_locs[token].offset + bad_index; |
| 59 | root_struct->source_code, root_struct->line_offsets, msg); | 63 | ErrorMsg *err = err_msg_create_with_offset(root_struct->path, byte_offset, |
| 64 | buf_ptr(root_struct->source_code), msg); | ||
| 60 | 65 | ||
| 61 | g->errors.append(err); | 66 | g->errors.append(err); |
| 62 | g->trace_err = err; | 67 | g->trace_err = err; |
| 63 | return err; | 68 | return err; |
| 64 | } | 69 | } |
| 65 | 70 | ||
| 71 | ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg) { | ||
| 72 | return add_token_error_offset(g, owner, token, msg, 0); | ||
| 73 | } | ||
| 74 | |||
| 66 | ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { | 75 | ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { |
| 67 | Token fake_token; | ||
| 68 | fake_token.start_line = node->line; | ||
| 69 | fake_token.start_column = node->column; | ||
| 70 | node->already_traced_this_node = true; | 76 | node->already_traced_this_node = true; |
| 71 | return add_token_error(g, node->owner, &fake_token, msg); | 77 | return add_token_error(g, node->owner, node->main_token, msg); |
| 72 | } | 78 | } |
| 73 | 79 | ||
| 74 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg) { | 80 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg) { |
| 75 | Token fake_token; | 81 | return add_error_note_token(g, parent_msg, node->owner, node->main_token, msg); |
| 76 | fake_token.start_line = node->line; | ||
| 77 | fake_token.start_column = node->column; | ||
| 78 | return add_error_note_token(g, parent_msg, node->owner, &fake_token, msg); | ||
| 79 | } | 82 | } |
| 80 | 83 | ||
| 81 | ZigType *new_type_table_entry(ZigTypeId id) { | 84 | ZigType *new_type_table_entry(ZigTypeId id) { |
| ... | @@ -913,13 +916,27 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { | ... | @@ -913,13 +916,27 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { |
| 913 | return entry; | 916 | return entry; |
| 914 | } | 917 | } |
| 915 | 918 | ||
| 916 | ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *full_name, Buf *bare_name) { | 919 | static uint32_t node_line_onebased(AstNode *node) { |
| 920 | RootStruct *root_struct = node->owner->data.structure.root_struct; | ||
| 921 | assert(node->main_token < root_struct->token_count); | ||
| 922 | return root_struct->token_locs[node->main_token].line + 1; | ||
| 923 | } | ||
| 924 | |||
| 925 | static uint32_t node_column_onebased(AstNode *node) { | ||
| 926 | RootStruct *root_struct = node->owner->data.structure.root_struct; | ||
| 927 | assert(node->main_token < root_struct->token_count); | ||
| 928 | return root_struct->token_locs[node->main_token].column + 1; | ||
| 929 | } | ||
| 930 | |||
| 931 | ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *full_name, | ||
| 932 | Buf *bare_name) | ||
| 933 | { | ||
| 917 | ZigType *entry = new_type_table_entry(ZigTypeIdOpaque); | 934 | ZigType *entry = new_type_table_entry(ZigTypeIdOpaque); |
| 918 | 935 | ||
| 919 | buf_init_from_str(&entry->name, full_name); | 936 | buf_init_from_str(&entry->name, full_name); |
| 920 | 937 | ||
| 921 | ZigType *import = scope ? get_scope_import(scope) : nullptr; | 938 | ZigType *import = scope ? get_scope_import(scope) : nullptr; |
| 922 | unsigned line = source_node ? (unsigned)(source_node->line + 1) : 0; | 939 | unsigned line = source_node ? node_line_onebased(source_node) : 0; |
| 923 | 940 | ||
| 924 | // Note: duplicated in get_partial_container_type | 941 | // Note: duplicated in get_partial_container_type |
| 925 | entry->llvm_type = LLVMInt8Type(); | 942 | entry->llvm_type = LLVMInt8Type(); |
| ... | @@ -1142,7 +1159,7 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind | ... | @@ -1142,7 +1159,7 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind |
| 1142 | break; | 1159 | break; |
| 1143 | case ContainerKindOpaque: { | 1160 | case ContainerKindOpaque: { |
| 1144 | ZigType *import = scope ? get_scope_import(scope) : nullptr; | 1161 | ZigType *import = scope ? get_scope_import(scope) : nullptr; |
| 1145 | unsigned line = decl_node ? (unsigned)(decl_node->line + 1) : 0; | 1162 | unsigned line = decl_node ? node_line_onebased(decl_node) : 0; |
| 1146 | // Note: duplicated in get_opaque_type | 1163 | // Note: duplicated in get_opaque_type |
| 1147 | entry->llvm_type = LLVMInt8Type(); | 1164 | entry->llvm_type = LLVMInt8Type(); |
| 1148 | entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder, | 1165 | entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder, |
| ... | @@ -1584,8 +1601,9 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV | ... | @@ -1584,8 +1601,9 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV |
| 1584 | ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { | 1601 | ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { |
| 1585 | Error err; | 1602 | Error err; |
| 1586 | // Hot path for simple identifiers, to avoid unnecessary memory allocations. | 1603 | // Hot path for simple identifiers, to avoid unnecessary memory allocations. |
| 1587 | if (node->type == NodeTypeSymbol) { | 1604 | if (node->type == NodeTypeIdentifier) { |
| 1588 | Buf *variable_name = node->data.symbol_expr.symbol; | 1605 | RootStruct *root_struct = node->owner->data.structure.root_struct; |
| 1606 | Buf *variable_name = token_identifier_buf(root_struct, node->main_token); | ||
| 1589 | if (buf_eql_str(variable_name, "_")) | 1607 | if (buf_eql_str(variable_name, "_")) |
| 1590 | goto abort_hot_path; | 1608 | goto abort_hot_path; |
| 1591 | ZigType *primitive_type; | 1609 | ZigType *primitive_type; |
| ... | @@ -2034,7 +2052,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc | ... | @@ -2034,7 +2052,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 2034 | buf_sprintf("var args only allowed in functions with C calling convention")); | 2052 | buf_sprintf("var args only allowed in functions with C calling convention")); |
| 2035 | return g->builtin_types.entry_invalid; | 2053 | return g->builtin_types.entry_invalid; |
| 2036 | } | 2054 | } |
| 2037 | } else if (param_node->data.param_decl.anytype_token != nullptr) { | 2055 | } else if (param_node->data.param_decl.anytype_token != 0) { |
| 2038 | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { | 2056 | if (!calling_convention_allows_zig_types(fn_type_id.cc)) { |
| 2039 | add_node_error(g, param_node, | 2057 | add_node_error(g, param_node, |
| 2040 | buf_sprintf("parameter of type 'anytype' not allowed in function with calling convention '%s'", | 2058 | buf_sprintf("parameter of type 'anytype' not allowed in function with calling convention '%s'", |
| ... | @@ -3021,7 +3039,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { | ... | @@ -3021,7 +3039,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { |
| 3021 | field_node = decl_node->data.container_decl.fields.at(i); | 3039 | field_node = decl_node->data.container_decl.fields.at(i); |
| 3022 | type_struct_field->name = field_node->data.struct_field.name; | 3040 | type_struct_field->name = field_node->data.struct_field.name; |
| 3023 | type_struct_field->decl_node = field_node; | 3041 | type_struct_field->decl_node = field_node; |
| 3024 | if (field_node->data.struct_field.comptime_token != nullptr) { | 3042 | if (field_node->data.struct_field.comptime_token != 0) { |
| 3025 | if (field_node->data.struct_field.value == nullptr) { | 3043 | if (field_node->data.struct_field.value == nullptr) { |
| 3026 | add_token_error(g, field_node->owner, | 3044 | add_token_error(g, field_node->owner, |
| 3027 | field_node->data.struct_field.comptime_token, | 3045 | field_node->data.struct_field.comptime_token, |
| ... | @@ -3635,14 +3653,7 @@ static void get_fully_qualified_decl_name(CodeGen *g, Buf *buf, Tld *tld, bool i | ... | @@ -3635,14 +3653,7 @@ static void get_fully_qualified_decl_name(CodeGen *g, Buf *buf, Tld *tld, bool i |
| 3635 | 3653 | ||
| 3636 | static ZigFn *create_fn_raw(CodeGen *g, bool is_noinline) { | 3654 | static ZigFn *create_fn_raw(CodeGen *g, bool is_noinline) { |
| 3637 | ZigFn *fn_entry = heap::c_allocator.create<ZigFn>(); | 3655 | ZigFn *fn_entry = heap::c_allocator.create<ZigFn>(); |
| 3638 | fn_entry->ir_executable = heap::c_allocator.create<IrExecutableSrc>(); | 3656 | fn_entry->stage1_zir = heap::c_allocator.create<Stage1Zir>(); |
| 3639 | |||
| 3640 | fn_entry->prealloc_backward_branch_quota = default_backward_branch_quota; | ||
| 3641 | |||
| 3642 | fn_entry->analyzed_executable.backward_branch_count = &fn_entry->prealloc_bbc; | ||
| 3643 | fn_entry->analyzed_executable.backward_branch_quota = &fn_entry->prealloc_backward_branch_quota; | ||
| 3644 | fn_entry->analyzed_executable.fn_entry = fn_entry; | ||
| 3645 | fn_entry->ir_executable->fn_entry = fn_entry; | ||
| 3646 | fn_entry->is_noinline = is_noinline; | 3657 | fn_entry->is_noinline = is_noinline; |
| 3647 | 3658 | ||
| 3648 | return fn_entry; | 3659 | return fn_entry; |
| ... | @@ -4042,7 +4053,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { | ... | @@ -4042,7 +4053,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 4042 | case NodeTypeBoolLiteral: | 4053 | case NodeTypeBoolLiteral: |
| 4043 | case NodeTypeNullLiteral: | 4054 | case NodeTypeNullLiteral: |
| 4044 | case NodeTypeUndefinedLiteral: | 4055 | case NodeTypeUndefinedLiteral: |
| 4045 | case NodeTypeSymbol: | 4056 | case NodeTypeIdentifier: |
| 4046 | case NodeTypePrefixOpExpr: | 4057 | case NodeTypePrefixOpExpr: |
| 4047 | case NodeTypePointerType: | 4058 | case NodeTypePointerType: |
| 4048 | case NodeTypeIfBoolExpr: | 4059 | case NodeTypeIfBoolExpr: |
| ... | @@ -4238,7 +4249,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) { | ... | @@ -4238,7 +4249,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) { |
| 4238 | bool is_const = var_decl->is_const; | 4249 | bool is_const = var_decl->is_const; |
| 4239 | bool is_extern = var_decl->is_extern; | 4250 | bool is_extern = var_decl->is_extern; |
| 4240 | bool is_export = var_decl->is_export; | 4251 | bool is_export = var_decl->is_export; |
| 4241 | bool is_thread_local = var_decl->threadlocal_tok != nullptr; | 4252 | bool is_thread_local = var_decl->threadlocal_tok != 0; |
| 4242 | 4253 | ||
| 4243 | ZigType *explicit_type = nullptr; | 4254 | ZigType *explicit_type = nullptr; |
| 4244 | if (var_decl->type) { | 4255 | if (var_decl->type) { |
| ... | @@ -5116,8 +5127,11 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) { | ... | @@ -5116,8 +5127,11 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) { |
| 5116 | if (fn->analyzed_executable.source_node == nullptr) { | 5127 | if (fn->analyzed_executable.source_node == nullptr) { |
| 5117 | fn->analyzed_executable.source_node = fn->body_node; | 5128 | fn->analyzed_executable.source_node = fn->body_node; |
| 5118 | } | 5129 | } |
| 5119 | ZigType *block_return_type = ir_analyze(g, fn->ir_executable, | 5130 | size_t backward_branch_count = 0; |
| 5120 | &fn->analyzed_executable, fn_type_id->return_type, return_type_node, nullptr); | 5131 | size_t backward_branch_quota = max(fn->branch_quota, default_backward_branch_quota); |
| 5132 | ZigType *block_return_type = ir_analyze(g, fn->stage1_zir, &fn->analyzed_executable, | ||
| 5133 | &backward_branch_count, &backward_branch_quota, | ||
| 5134 | fn_type_id->return_type, return_type_node, nullptr, fn); | ||
| 5121 | fn->src_implicit_return_type = block_return_type; | 5135 | fn->src_implicit_return_type = block_return_type; |
| 5122 | 5136 | ||
| 5123 | if (type_is_invalid(block_return_type) || fn->analyzed_executable.first_err_trace_msg != nullptr) { | 5137 | if (type_is_invalid(block_return_type) || fn->analyzed_executable.first_err_trace_msg != nullptr) { |
| ... | @@ -5214,21 +5228,19 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { | ... | @@ -5214,21 +5228,19 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { |
| 5214 | ZigType *fn_type = fn_table_entry->type_entry; | 5228 | ZigType *fn_type = fn_table_entry->type_entry; |
| 5215 | assert(!fn_type->data.fn.is_generic); | 5229 | assert(!fn_type->data.fn.is_generic); |
| 5216 | 5230 | ||
| 5217 | if (!ir_gen_fn(g, fn_table_entry)) { | 5231 | if (!stage1_astgen_fn(g, fn_table_entry)) { |
| 5218 | fn_table_entry->anal_state = FnAnalStateInvalid; | 5232 | fn_table_entry->anal_state = FnAnalStateInvalid; |
| 5219 | return; | 5233 | return; |
| 5220 | } | 5234 | } |
| 5221 | 5235 | ||
| 5222 | if (fn_table_entry->ir_executable->first_err_trace_msg != nullptr) { | 5236 | if (fn_table_entry->stage1_zir->first_err_trace_msg != nullptr) { |
| 5223 | fn_table_entry->anal_state = FnAnalStateInvalid; | 5237 | fn_table_entry->anal_state = FnAnalStateInvalid; |
| 5224 | return; | 5238 | return; |
| 5225 | } | 5239 | } |
| 5226 | 5240 | ||
| 5227 | if (g->verbose_ir) { | 5241 | if (g->verbose_ir) { |
| 5228 | fprintf(stderr, "\n"); | ||
| 5229 | ast_render(stderr, fn_table_entry->body_node, 4); | ||
| 5230 | fprintf(stderr, "\nfn %s() { // (IR)\n", buf_ptr(&fn_table_entry->symbol_name)); | 5242 | fprintf(stderr, "\nfn %s() { // (IR)\n", buf_ptr(&fn_table_entry->symbol_name)); |
| 5231 | ir_print_src(g, stderr, fn_table_entry->ir_executable, 4); | 5243 | ir_print_src(g, stderr, fn_table_entry->stage1_zir, 4); |
| 5232 | fprintf(stderr, "}\n"); | 5244 | fprintf(stderr, "}\n"); |
| 5233 | } | 5245 | } |
| 5234 | 5246 | ||
| ... | @@ -5238,33 +5250,17 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { | ... | @@ -5238,33 +5250,17 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { |
| 5238 | ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Buf *source_code, | 5250 | ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Buf *source_code, |
| 5239 | SourceKind source_kind) | 5251 | SourceKind source_kind) |
| 5240 | { | 5252 | { |
| 5241 | if (g->verbose_tokenize) { | ||
| 5242 | fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(resolved_path)); | ||
| 5243 | fprintf(stderr, "----------------\n"); | ||
| 5244 | fprintf(stderr, "%s\n", buf_ptr(source_code)); | ||
| 5245 | |||
| 5246 | fprintf(stderr, "\nTokens:\n"); | ||
| 5247 | fprintf(stderr, "---------\n"); | ||
| 5248 | } | ||
| 5249 | |||
| 5250 | Tokenization tokenization = {0}; | 5253 | Tokenization tokenization = {0}; |
| 5251 | tokenize(source_code, &tokenization); | 5254 | tokenize(buf_ptr(source_code), &tokenization); |
| 5252 | 5255 | ||
| 5253 | if (tokenization.err) { | 5256 | if (tokenization.err) { |
| 5254 | ErrorMsg *err = err_msg_create_with_line(resolved_path, tokenization.err_line, tokenization.err_column, | 5257 | ErrorMsg *err = err_msg_create_with_offset(resolved_path, tokenization.err_byte_offset, |
| 5255 | source_code, tokenization.line_offsets, tokenization.err); | 5258 | buf_ptr(source_code), tokenization.err); |
| 5256 | 5259 | ||
| 5257 | print_err_msg(err, g->err_color); | 5260 | print_err_msg(err, g->err_color); |
| 5258 | exit(1); | 5261 | exit(1); |
| 5259 | } | 5262 | } |
| 5260 | 5263 | ||
| 5261 | if (g->verbose_tokenize) { | ||
| 5262 | print_tokens(source_code, tokenization.tokens); | ||
| 5263 | |||
| 5264 | fprintf(stderr, "\nAST:\n"); | ||
| 5265 | fprintf(stderr, "------\n"); | ||
| 5266 | } | ||
| 5267 | |||
| 5268 | Buf *src_dirname = buf_alloc(); | 5264 | Buf *src_dirname = buf_alloc(); |
| 5269 | Buf *src_basename = buf_alloc(); | 5265 | Buf *src_basename = buf_alloc(); |
| 5270 | os_path_split(resolved_path, src_dirname, src_basename); | 5266 | os_path_split(resolved_path, src_dirname, src_basename); |
| ... | @@ -5297,9 +5293,20 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu | ... | @@ -5297,9 +5293,20 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu |
| 5297 | RootStruct *root_struct = heap::c_allocator.create<RootStruct>(); | 5293 | RootStruct *root_struct = heap::c_allocator.create<RootStruct>(); |
| 5298 | root_struct->package = package; | 5294 | root_struct->package = package; |
| 5299 | root_struct->source_code = source_code; | 5295 | root_struct->source_code = source_code; |
| 5300 | root_struct->line_offsets = tokenization.line_offsets; | ||
| 5301 | root_struct->path = resolved_path; | 5296 | root_struct->path = resolved_path; |
| 5302 | root_struct->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname)); | 5297 | root_struct->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname)); |
| 5298 | |||
| 5299 | assert(tokenization.ids.length == tokenization.locs.length); | ||
| 5300 | size_t token_count = tokenization.ids.length; | ||
| 5301 | root_struct->token_count = token_count; | ||
| 5302 | root_struct->token_ids = g->pass1_arena->allocate<TokenId>(token_count); | ||
| 5303 | memcpy(root_struct->token_ids, tokenization.ids.items, token_count * sizeof(TokenId)); | ||
| 5304 | root_struct->token_locs = g->pass1_arena->allocate<TokenLoc>(token_count); | ||
| 5305 | memcpy(root_struct->token_locs, tokenization.locs.items, token_count * sizeof(TokenLoc)); | ||
| 5306 | |||
| 5307 | tokenization.ids.deinit(); | ||
| 5308 | tokenization.locs.deinit(); | ||
| 5309 | |||
| 5303 | ZigType *import_entry = get_root_container_type(g, buf_ptr(namespace_name), bare_name, root_struct); | 5310 | ZigType *import_entry = get_root_container_type(g, buf_ptr(namespace_name), bare_name, root_struct); |
| 5304 | if (source_kind == SourceKindRoot) { | 5311 | if (source_kind == SourceKindRoot) { |
| 5305 | assert(g->root_import == nullptr); | 5312 | assert(g->root_import == nullptr); |
| ... | @@ -5307,14 +5314,11 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu | ... | @@ -5307,14 +5314,11 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu |
| 5307 | } | 5314 | } |
| 5308 | g->import_table.put(resolved_path, import_entry); | 5315 | g->import_table.put(resolved_path, import_entry); |
| 5309 | 5316 | ||
| 5310 | AstNode *root_node = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color); | 5317 | AstNode *root_node = ast_parse(source_code, import_entry, g->err_color); |
| 5311 | assert(root_node != nullptr); | 5318 | assert(root_node != nullptr); |
| 5312 | assert(root_node->type == NodeTypeContainerDecl); | 5319 | assert(root_node->type == NodeTypeContainerDecl); |
| 5313 | import_entry->data.structure.decl_node = root_node; | 5320 | import_entry->data.structure.decl_node = root_node; |
| 5314 | import_entry->data.structure.decls_scope->base.source_node = root_node; | 5321 | import_entry->data.structure.decls_scope->base.source_node = root_node; |
| 5315 | if (g->verbose_ast) { | ||
| 5316 | ast_print(stderr, root_node, 0); | ||
| 5317 | } | ||
| 5318 | 5322 | ||
| 5319 | for (size_t decl_i = 0; decl_i < root_node->data.container_decl.decls.length; decl_i += 1) { | 5323 | for (size_t decl_i = 0; decl_i < root_node->data.container_decl.decls.length; decl_i += 1) { |
| 5320 | AstNode *top_level_decl = root_node->data.container_decl.decls.at(decl_i); | 5324 | AstNode *top_level_decl = root_node->data.container_decl.decls.at(decl_i); |
| ... | @@ -6254,9 +6258,12 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) { | ... | @@ -6254,9 +6258,12 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) { |
| 6254 | zig_unreachable(); | 6258 | zig_unreachable(); |
| 6255 | } | 6259 | } |
| 6256 | 6260 | ||
| 6257 | void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str) { | 6261 | void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str, bool move_str) { |
| 6258 | auto entry = g->string_literals_table.maybe_get(str); | 6262 | auto entry = g->string_literals_table.maybe_get(str); |
| 6259 | if (entry != nullptr) { | 6263 | if (entry != nullptr) { |
| 6264 | if (move_str) { | ||
| 6265 | buf_destroy(str); | ||
| 6266 | } | ||
| 6260 | memcpy(const_val, entry->value, sizeof(ZigValue)); | 6267 | memcpy(const_val, entry->value, sizeof(ZigValue)); |
| 6261 | return; | 6268 | return; |
| 6262 | } | 6269 | } |
| ... | @@ -6280,7 +6287,7 @@ void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str) { | ... | @@ -6280,7 +6287,7 @@ void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str) { |
| 6280 | 6287 | ||
| 6281 | ZigValue *create_const_str_lit(CodeGen *g, Buf *str) { | 6288 | ZigValue *create_const_str_lit(CodeGen *g, Buf *str) { |
| 6282 | ZigValue *const_val = g->pass1_arena->create<ZigValue>(); | 6289 | ZigValue *const_val = g->pass1_arena->create<ZigValue>(); |
| 6283 | init_const_str_lit(g, const_val, str); | 6290 | init_const_str_lit(g, const_val, str, false); |
| 6284 | return const_val; | 6291 | return const_val; |
| 6285 | } | 6292 | } |
| 6286 | 6293 | ||
| ... | @@ -8626,7 +8633,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS | ... | @@ -8626,7 +8633,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS |
| 8626 | ZigType *import = get_scope_import(scope); | 8633 | ZigType *import = get_scope_import(scope); |
| 8627 | di_file = import->data.structure.root_struct->di_file; | 8634 | di_file = import->data.structure.root_struct->di_file; |
| 8628 | di_scope = ZigLLVMFileToScope(di_file); | 8635 | di_scope = ZigLLVMFileToScope(di_file); |
| 8629 | line = decl_node->line + 1; | 8636 | line = node_line_onebased(decl_node); |
| 8630 | } else { | 8637 | } else { |
| 8631 | di_file = nullptr; | 8638 | di_file = nullptr; |
| 8632 | di_scope = ZigLLVMCompileUnitToScope(g->compile_unit); | 8639 | di_scope = ZigLLVMCompileUnitToScope(g->compile_unit); |
| ... | @@ -8830,7 +8837,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS | ... | @@ -8830,7 +8837,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS |
| 8830 | unsigned line; | 8837 | unsigned line; |
| 8831 | if (decl_node != nullptr) { | 8838 | if (decl_node != nullptr) { |
| 8832 | AstNode *field_node = field->decl_node; | 8839 | AstNode *field_node = field->decl_node; |
| 8833 | line = field_node->line + 1; | 8840 | line = node_line_onebased(field_node); |
| 8834 | } else { | 8841 | } else { |
| 8835 | line = 0; | 8842 | line = 0; |
| 8836 | } | 8843 | } |
| ... | @@ -8881,7 +8888,7 @@ static ZigLLVMDIType *make_empty_namespace_llvm_di_type(CodeGen *g, ZigType *imp | ... | @@ -8881,7 +8888,7 @@ static ZigLLVMDIType *make_empty_namespace_llvm_di_type(CodeGen *g, ZigType *imp |
| 8881 | return ZigLLVMCreateDebugStructType(g->dbuilder, | 8888 | return ZigLLVMCreateDebugStructType(g->dbuilder, |
| 8882 | ZigLLVMFileToScope(import->data.structure.root_struct->di_file), | 8889 | ZigLLVMFileToScope(import->data.structure.root_struct->di_file), |
| 8883 | name, | 8890 | name, |
| 8884 | import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), | 8891 | import->data.structure.root_struct->di_file, node_line_onebased(decl_node), |
| 8885 | debug_size_in_bits, | 8892 | debug_size_in_bits, |
| 8886 | debug_align_in_bits, | 8893 | debug_align_in_bits, |
| 8887 | ZigLLVM_DIFlags_Zero, | 8894 | ZigLLVM_DIFlags_Zero, |
| ... | @@ -8926,7 +8933,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu | ... | @@ -8926,7 +8933,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu |
| 8926 | uint64_t tag_debug_align_in_bits = 8*tag_int_type->abi_align; | 8933 | uint64_t tag_debug_align_in_bits = 8*tag_int_type->abi_align; |
| 8927 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, | 8934 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, |
| 8928 | ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&enum_type->name), | 8935 | ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&enum_type->name), |
| 8929 | import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), | 8936 | import->data.structure.root_struct->di_file, node_line_onebased(decl_node), |
| 8930 | tag_debug_size_in_bits, | 8937 | tag_debug_size_in_bits, |
| 8931 | tag_debug_align_in_bits, | 8938 | tag_debug_align_in_bits, |
| 8932 | di_enumerators, field_count, | 8939 | di_enumerators, field_count, |
| ... | @@ -8966,12 +8973,12 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta | ... | @@ -8966,12 +8973,12 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta |
| 8966 | 8973 | ||
| 8967 | if (union_type->data.unionation.resolve_status < ResolveStatusLLVMFwdDecl) { | 8974 | if (union_type->data.unionation.resolve_status < ResolveStatusLLVMFwdDecl) { |
| 8968 | union_type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&union_type->name)); | 8975 | union_type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&union_type->name)); |
| 8969 | size_t line = decl_node ? decl_node->line : 0; | 8976 | unsigned line = decl_node ? node_line_onebased(decl_node) : 0; |
| 8970 | unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); | 8977 | unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); |
| 8971 | union_type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, | 8978 | union_type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, |
| 8972 | dwarf_kind, buf_ptr(&union_type->name), | 8979 | dwarf_kind, buf_ptr(&union_type->name), |
| 8973 | ZigLLVMFileToScope(import->data.structure.root_struct->di_file), | 8980 | ZigLLVMFileToScope(import->data.structure.root_struct->di_file), |
| 8974 | import->data.structure.root_struct->di_file, (unsigned)(line + 1)); | 8981 | import->data.structure.root_struct->di_file, line); |
| 8975 | 8982 | ||
| 8976 | union_type->data.unionation.resolve_status = ResolveStatusLLVMFwdDecl; | 8983 | union_type->data.unionation.resolve_status = ResolveStatusLLVMFwdDecl; |
| 8977 | if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return; | 8984 | if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return; |
| ... | @@ -8992,7 +8999,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta | ... | @@ -8992,7 +8999,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta |
| 8992 | AstNode *field_node = union_field->decl_node; | 8999 | AstNode *field_node = union_field->decl_node; |
| 8993 | union_inner_di_types[union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, | 9000 | union_inner_di_types[union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 8994 | ZigLLVMTypeToScope(union_type->llvm_di_type), buf_ptr(union_field->enum_field->name), | 9001 | ZigLLVMTypeToScope(union_type->llvm_di_type), buf_ptr(union_field->enum_field->name), |
| 8995 | import->data.structure.root_struct->di_file, (unsigned)(field_node->line + 1), | 9002 | import->data.structure.root_struct->di_file, node_line_onebased(field_node), |
| 8996 | store_size_in_bits, | 9003 | store_size_in_bits, |
| 8997 | abi_align_in_bits, | 9004 | abi_align_in_bits, |
| 8998 | 0, | 9005 | 0, |
| ... | @@ -9022,7 +9029,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta | ... | @@ -9022,7 +9029,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta |
| 9022 | // create debug type for union | 9029 | // create debug type for union |
| 9023 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, | 9030 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, |
| 9024 | ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&union_type->name), | 9031 | ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&union_type->name), |
| 9025 | import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), | 9032 | import->data.structure.root_struct->di_file, node_line_onebased(decl_node), |
| 9026 | union_type->data.unionation.union_abi_size * 8, | 9033 | union_type->data.unionation.union_abi_size * 8, |
| 9027 | most_aligned_union_member->align * 8, | 9034 | most_aligned_union_member->align * 8, |
| 9028 | ZigLLVM_DIFlags_Zero, union_inner_di_types, | 9035 | ZigLLVM_DIFlags_Zero, union_inner_di_types, |
| ... | @@ -9057,7 +9064,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta | ... | @@ -9057,7 +9064,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta |
| 9057 | // create debug type for union | 9064 | // create debug type for union |
| 9058 | ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, | 9065 | ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, |
| 9059 | ZigLLVMTypeToScope(union_type->llvm_di_type), "AnonUnion", | 9066 | ZigLLVMTypeToScope(union_type->llvm_di_type), "AnonUnion", |
| 9060 | import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), | 9067 | import->data.structure.root_struct->di_file, node_line_onebased(decl_node), |
| 9061 | most_aligned_union_member->type_entry->size_in_bits, 8*most_aligned_union_member->align, | 9068 | most_aligned_union_member->type_entry->size_in_bits, 8*most_aligned_union_member->align, |
| 9062 | ZigLLVM_DIFlags_Zero, union_inner_di_types, gen_field_count, 0, ""); | 9069 | ZigLLVM_DIFlags_Zero, union_inner_di_types, gen_field_count, 0, ""); |
| 9063 | 9070 | ||
| ... | @@ -9068,7 +9075,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta | ... | @@ -9068,7 +9075,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta |
| 9068 | 9075 | ||
| 9069 | ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, | 9076 | ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 9070 | ZigLLVMTypeToScope(union_type->llvm_di_type), "payload", | 9077 | ZigLLVMTypeToScope(union_type->llvm_di_type), "payload", |
| 9071 | import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), | 9078 | import->data.structure.root_struct->di_file, node_line_onebased(decl_node), |
| 9072 | most_aligned_union_member->type_entry->size_in_bits, | 9079 | most_aligned_union_member->type_entry->size_in_bits, |
| 9073 | 8*most_aligned_union_member->align, | 9080 | 8*most_aligned_union_member->align, |
| 9074 | union_offset_in_bits, | 9081 | union_offset_in_bits, |
| ... | @@ -9079,7 +9086,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta | ... | @@ -9079,7 +9086,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta |
| 9079 | 9086 | ||
| 9080 | ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, | 9087 | ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 9081 | ZigLLVMTypeToScope(union_type->llvm_di_type), "tag", | 9088 | ZigLLVMTypeToScope(union_type->llvm_di_type), "tag", |
| 9082 | import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), | 9089 | import->data.structure.root_struct->di_file, node_line_onebased(decl_node), |
| 9083 | tag_debug_size_in_bits, | 9090 | tag_debug_size_in_bits, |
| 9084 | tag_debug_align_in_bits, | 9091 | tag_debug_align_in_bits, |
| 9085 | tag_offset_in_bits, | 9092 | tag_offset_in_bits, |
| ... | @@ -9094,7 +9101,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta | ... | @@ -9094,7 +9101,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta |
| 9094 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, | 9101 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, |
| 9095 | ZigLLVMFileToScope(import->data.structure.root_struct->di_file), | 9102 | ZigLLVMFileToScope(import->data.structure.root_struct->di_file), |
| 9096 | buf_ptr(&union_type->name), | 9103 | buf_ptr(&union_type->name), |
| 9097 | import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), | 9104 | import->data.structure.root_struct->di_file, node_line_onebased(decl_node), |
| 9098 | debug_size_in_bits, | 9105 | debug_size_in_bits, |
| 9099 | debug_align_in_bits, | 9106 | debug_align_in_bits, |
| 9100 | ZigLLVM_DIFlags_Zero, nullptr, di_root_members, 2, 0, nullptr, ""); | 9107 | ZigLLVM_DIFlags_Zero, nullptr, di_root_members, 2, 0, nullptr, ""); |
| ... | @@ -9774,9 +9781,9 @@ void src_assert_impl(bool ok, AstNode *source_node, char const *file, unsigned i | ... | @@ -9774,9 +9781,9 @@ void src_assert_impl(bool ok, AstNode *source_node, char const *file, unsigned i |
| 9774 | if (source_node == nullptr) { | 9781 | if (source_node == nullptr) { |
| 9775 | fprintf(stderr, "when analyzing (unknown source location) "); | 9782 | fprintf(stderr, "when analyzing (unknown source location) "); |
| 9776 | } else { | 9783 | } else { |
| 9777 | fprintf(stderr, "when analyzing %s:%u:%u ", | 9784 | RootStruct *root_struct = source_node->owner->data.structure.root_struct; |
| 9778 | buf_ptr(source_node->owner->data.structure.root_struct->path), | 9785 | fprintf(stderr, "when analyzing %s:%u:%u ", buf_ptr(root_struct->path), |
| 9779 | (unsigned)source_node->line + 1, (unsigned)source_node->column + 1); | 9786 | node_line_onebased(source_node), node_column_onebased(source_node)); |
| 9780 | } | 9787 | } |
| 9781 | fprintf(stderr, "in compiler source at %s:%u: ", file, line); | 9788 | fprintf(stderr, "in compiler source at %s:%u: ", file, line); |
| 9782 | const char *msg = "assertion failed. This is a bug in the Zig compiler."; | 9789 | const char *msg = "assertion failed. This is a bug in the Zig compiler."; |
| ... | @@ -9842,18 +9849,17 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str, | ... | @@ -9842,18 +9849,17 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str, |
| 9842 | return ErrorNone; | 9849 | return ErrorNone; |
| 9843 | } | 9850 | } |
| 9844 | 9851 | ||
| 9845 | 9852 | void AstNode::src() { | |
| 9846 | void IrExecutableSrc::src() { | 9853 | RootStruct *root_struct = this->owner->data.structure.root_struct; |
| 9847 | if (this->source_node != nullptr) { | 9854 | uint32_t line = root_struct->token_locs[this->main_token].line + 1; |
| 9848 | this->source_node->src(); | 9855 | uint32_t column = root_struct->token_locs[this->main_token].column + 1; |
| 9849 | } | 9856 | fprintf(stderr, "%s:%" PRIu32 ":%" PRIu32 "\n", |
| 9850 | if (this->parent_exec != nullptr) { | 9857 | buf_ptr(root_struct->path), |
| 9851 | this->parent_exec->src(); | 9858 | line, column); |
| 9852 | } | ||
| 9853 | } | 9859 | } |
| 9854 | 9860 | ||
| 9855 | void IrExecutableGen::src() { | 9861 | void Stage1Air::src() { |
| 9856 | IrExecutableGen *it; | 9862 | Stage1Air *it; |
| 9857 | for (it = this; it != nullptr && it->source_node != nullptr; it = it->parent_exec) { | 9863 | for (it = this; it != nullptr && it->source_node != nullptr; it = it->parent_exec) { |
| 9858 | it->source_node->src(); | 9864 | it->source_node->src(); |
| 9859 | } | 9865 | } |
src/stage1/analyze.hpp+4-2| ... | @@ -12,7 +12,9 @@ | ... | @@ -12,7 +12,9 @@ |
| 12 | 12 | ||
| 13 | void semantic_analyze(CodeGen *g); | 13 | void semantic_analyze(CodeGen *g); |
| 14 | ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg); | 14 | ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg); |
| 15 | ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg); | 15 | ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg); |
| 16 | ErrorMsg *add_token_error_offset(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg, | ||
| 17 | uint32_t bad_index); | ||
| 16 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg); | 18 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg); |
| 17 | ZigType *new_type_table_entry(ZigTypeId id); | 19 | ZigType *new_type_table_entry(ZigTypeId id); |
| 18 | ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn); | 20 | ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn); |
| ... | @@ -140,7 +142,7 @@ Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc | ... | @@ -140,7 +142,7 @@ Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc |
| 140 | Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent); | 142 | Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent); |
| 141 | ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent); | 143 | ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent); |
| 142 | 144 | ||
| 143 | void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str); | 145 | void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str, bool move_str); |
| 144 | ZigValue *create_const_str_lit(CodeGen *g, Buf *str); | 146 | ZigValue *create_const_str_lit(CodeGen *g, Buf *str); |
| 145 | 147 | ||
| 146 | void init_const_bigint(ZigValue *const_val, ZigType *type, const BigInt *bigint); | 148 | void init_const_bigint(ZigValue *const_val, ZigType *type, const BigInt *bigint); |
src/stage1/ast_render.cpp deleted-1241| ... | @@ -1,1241 +0,0 @@ | ||
| 1 | /* | ||
| 2 | * Copyright (c) 2016 Andrew Kelley | ||
| 3 | * | ||
| 4 | * This file is part of zig, which is MIT licensed. | ||
| 5 | * See http://opensource.org/licenses/MIT | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include "analyze.hpp" | ||
| 9 | #include "ast_render.hpp" | ||
| 10 | #include "os.hpp" | ||
| 11 | |||
| 12 | #include <stdio.h> | ||
| 13 | |||
| 14 | static const char *bin_op_str(BinOpType bin_op) { | ||
| 15 | switch (bin_op) { | ||
| 16 | case BinOpTypeInvalid: return "(invalid)"; | ||
| 17 | case BinOpTypeBoolOr: return "or"; | ||
| 18 | case BinOpTypeBoolAnd: return "and"; | ||
| 19 | case BinOpTypeCmpEq: return "=="; | ||
| 20 | case BinOpTypeCmpNotEq: return "!="; | ||
| 21 | case BinOpTypeCmpLessThan: return "<"; | ||
| 22 | case BinOpTypeCmpGreaterThan: return ">"; | ||
| 23 | case BinOpTypeCmpLessOrEq: return "<="; | ||
| 24 | case BinOpTypeCmpGreaterOrEq: return ">="; | ||
| 25 | case BinOpTypeBinOr: return "|"; | ||
| 26 | case BinOpTypeBinXor: return "^"; | ||
| 27 | case BinOpTypeBinAnd: return "&"; | ||
| 28 | case BinOpTypeBitShiftLeft: return "<<"; | ||
| 29 | case BinOpTypeBitShiftRight: return ">>"; | ||
| 30 | case BinOpTypeAdd: return "+"; | ||
| 31 | case BinOpTypeAddWrap: return "+%"; | ||
| 32 | case BinOpTypeSub: return "-"; | ||
| 33 | case BinOpTypeSubWrap: return "-%"; | ||
| 34 | case BinOpTypeMult: return "*"; | ||
| 35 | case BinOpTypeMultWrap: return "*%"; | ||
| 36 | case BinOpTypeDiv: return "/"; | ||
| 37 | case BinOpTypeMod: return "%"; | ||
| 38 | case BinOpTypeAssign: return "="; | ||
| 39 | case BinOpTypeAssignTimes: return "*="; | ||
| 40 | case BinOpTypeAssignTimesWrap: return "*%="; | ||
| 41 | case BinOpTypeAssignDiv: return "/="; | ||
| 42 | case BinOpTypeAssignMod: return "%="; | ||
| 43 | case BinOpTypeAssignPlus: return "+="; | ||
| 44 | case BinOpTypeAssignPlusWrap: return "+%="; | ||
| 45 | case BinOpTypeAssignMinus: return "-="; | ||
| 46 | case BinOpTypeAssignMinusWrap: return "-%="; | ||
| 47 | case BinOpTypeAssignBitShiftLeft: return "<<="; | ||
| 48 | case BinOpTypeAssignBitShiftRight: return ">>="; | ||
| 49 | case BinOpTypeAssignBitAnd: return "&="; | ||
| 50 | case BinOpTypeAssignBitXor: return "^="; | ||
| 51 | case BinOpTypeAssignBitOr: return "|="; | ||
| 52 | case BinOpTypeUnwrapOptional: return "orelse"; | ||
| 53 | case BinOpTypeArrayCat: return "++"; | ||
| 54 | case BinOpTypeArrayMult: return "**"; | ||
| 55 | case BinOpTypeErrorUnion: return "!"; | ||
| 56 | case BinOpTypeMergeErrorSets: return "||"; | ||
| 57 | } | ||
| 58 | zig_unreachable(); | ||
| 59 | } | ||
| 60 | |||
| 61 | static const char *prefix_op_str(PrefixOp prefix_op) { | ||
| 62 | switch (prefix_op) { | ||
| 63 | case PrefixOpInvalid: return "(invalid)"; | ||
| 64 | case PrefixOpNegation: return "-"; | ||
| 65 | case PrefixOpNegationWrap: return "-%"; | ||
| 66 | case PrefixOpBoolNot: return "!"; | ||
| 67 | case PrefixOpBinNot: return "~"; | ||
| 68 | case PrefixOpOptional: return "?"; | ||
| 69 | case PrefixOpAddrOf: return "&"; | ||
| 70 | } | ||
| 71 | zig_unreachable(); | ||
| 72 | } | ||
| 73 | |||
| 74 | static const char *visib_mod_string(VisibMod mod) { | ||
| 75 | switch (mod) { | ||
| 76 | case VisibModPub: return "pub "; | ||
| 77 | case VisibModPrivate: return ""; | ||
| 78 | } | ||
| 79 | zig_unreachable(); | ||
| 80 | } | ||
| 81 | |||
| 82 | static const char *return_string(ReturnKind kind) { | ||
| 83 | switch (kind) { | ||
| 84 | case ReturnKindUnconditional: return "return"; | ||
| 85 | case ReturnKindError: return "try"; | ||
| 86 | } | ||
| 87 | zig_unreachable(); | ||
| 88 | } | ||
| 89 | |||
| 90 | static const char *defer_string(ReturnKind kind) { | ||
| 91 | switch (kind) { | ||
| 92 | case ReturnKindUnconditional: return "defer"; | ||
| 93 | case ReturnKindError: return "errdefer"; | ||
| 94 | } | ||
| 95 | zig_unreachable(); | ||
| 96 | } | ||
| 97 | |||
| 98 | static const char *layout_string(ContainerLayout layout) { | ||
| 99 | switch (layout) { | ||
| 100 | case ContainerLayoutAuto: return ""; | ||
| 101 | case ContainerLayoutExtern: return "extern "; | ||
| 102 | case ContainerLayoutPacked: return "packed "; | ||
| 103 | } | ||
| 104 | zig_unreachable(); | ||
| 105 | } | ||
| 106 | |||
| 107 | static const char *extern_string(bool is_extern) { | ||
| 108 | return is_extern ? "extern " : ""; | ||
| 109 | } | ||
| 110 | |||
| 111 | static const char *export_string(bool is_export) { | ||
| 112 | return is_export ? "export " : ""; | ||
| 113 | } | ||
| 114 | |||
| 115 | //static const char *calling_convention_string(CallingConvention cc) { | ||
| 116 | // switch (cc) { | ||
| 117 | // case CallingConventionUnspecified: return ""; | ||
| 118 | // case CallingConventionC: return "extern "; | ||
| 119 | // case CallingConventionCold: return "coldcc "; | ||
| 120 | // case CallingConventionNaked: return "nakedcc "; | ||
| 121 | // case CallingConventionStdcall: return "stdcallcc "; | ||
| 122 | // } | ||
| 123 | // zig_unreachable(); | ||
| 124 | //} | ||
| 125 | |||
| 126 | static const char *inline_string(FnInline fn_inline) { | ||
| 127 | switch (fn_inline) { | ||
| 128 | case FnInlineAlways: return "inline "; | ||
| 129 | case FnInlineNever: return "noinline "; | ||
| 130 | case FnInlineAuto: return ""; | ||
| 131 | } | ||
| 132 | zig_unreachable(); | ||
| 133 | } | ||
| 134 | |||
| 135 | static const char *const_or_var_string(bool is_const) { | ||
| 136 | return is_const ? "const" : "var"; | ||
| 137 | } | ||
| 138 | |||
| 139 | static const char *thread_local_string(Token *tok) { | ||
| 140 | return (tok == nullptr) ? "" : "threadlocal "; | ||
| 141 | } | ||
| 142 | |||
| 143 | static const char *token_to_ptr_len_str(Token *tok) { | ||
| 144 | assert(tok != nullptr); | ||
| 145 | switch (tok->id) { | ||
| 146 | case TokenIdStar: | ||
| 147 | case TokenIdStarStar: | ||
| 148 | return "*"; | ||
| 149 | case TokenIdLBracket: | ||
| 150 | return "[*]"; | ||
| 151 | case TokenIdSymbol: | ||
| 152 | return "[*c]"; | ||
| 153 | default: | ||
| 154 | zig_unreachable(); | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | static const char *node_type_str(NodeType node_type) { | ||
| 159 | switch (node_type) { | ||
| 160 | case NodeTypeFnDef: | ||
| 161 | return "FnDef"; | ||
| 162 | case NodeTypeFnProto: | ||
| 163 | return "FnProto"; | ||
| 164 | case NodeTypeParamDecl: | ||
| 165 | return "ParamDecl"; | ||
| 166 | case NodeTypeBlock: | ||
| 167 | return "Block"; | ||
| 168 | case NodeTypeGroupedExpr: | ||
| 169 | return "Parens"; | ||
| 170 | case NodeTypeBinOpExpr: | ||
| 171 | return "BinOpExpr"; | ||
| 172 | case NodeTypeCatchExpr: | ||
| 173 | return "CatchExpr"; | ||
| 174 | case NodeTypeFnCallExpr: | ||
| 175 | return "FnCallExpr"; | ||
| 176 | case NodeTypeArrayAccessExpr: | ||
| 177 | return "ArrayAccessExpr"; | ||
| 178 | case NodeTypeSliceExpr: | ||
| 179 | return "SliceExpr"; | ||
| 180 | case NodeTypeReturnExpr: | ||
| 181 | return "ReturnExpr"; | ||
| 182 | case NodeTypeDefer: | ||
| 183 | return "Defer"; | ||
| 184 | case NodeTypeVariableDeclaration: | ||
| 185 | return "VariableDeclaration"; | ||
| 186 | case NodeTypeTestDecl: | ||
| 187 | return "TestDecl"; | ||
| 188 | case NodeTypeIntLiteral: | ||
| 189 | return "IntLiteral"; | ||
| 190 | case NodeTypeFloatLiteral: | ||
| 191 | return "FloatLiteral"; | ||
| 192 | case NodeTypeStringLiteral: | ||
| 193 | return "StringLiteral"; | ||
| 194 | case NodeTypeCharLiteral: | ||
| 195 | return "CharLiteral"; | ||
| 196 | case NodeTypeSymbol: | ||
| 197 | return "Symbol"; | ||
| 198 | case NodeTypePrefixOpExpr: | ||
| 199 | return "PrefixOpExpr"; | ||
| 200 | case NodeTypeUsingNamespace: | ||
| 201 | return "UsingNamespace"; | ||
| 202 | case NodeTypeBoolLiteral: | ||
| 203 | return "BoolLiteral"; | ||
| 204 | case NodeTypeNullLiteral: | ||
| 205 | return "NullLiteral"; | ||
| 206 | case NodeTypeUndefinedLiteral: | ||
| 207 | return "UndefinedLiteral"; | ||
| 208 | case NodeTypeIfBoolExpr: | ||
| 209 | return "IfBoolExpr"; | ||
| 210 | case NodeTypeWhileExpr: | ||
| 211 | return "WhileExpr"; | ||
| 212 | case NodeTypeForExpr: | ||
| 213 | return "ForExpr"; | ||
| 214 | case NodeTypeSwitchExpr: | ||
| 215 | return "SwitchExpr"; | ||
| 216 | case NodeTypeSwitchProng: | ||
| 217 | return "SwitchProng"; | ||
| 218 | case NodeTypeSwitchRange: | ||
| 219 | return "SwitchRange"; | ||
| 220 | case NodeTypeCompTime: | ||
| 221 | return "CompTime"; | ||
| 222 | case NodeTypeNoSuspend: | ||
| 223 | return "NoSuspend"; | ||
| 224 | case NodeTypeBreak: | ||
| 225 | return "Break"; | ||
| 226 | case NodeTypeContinue: | ||
| 227 | return "Continue"; | ||
| 228 | case NodeTypeUnreachable: | ||
| 229 | return "Unreachable"; | ||
| 230 | case NodeTypeAsmExpr: | ||
| 231 | return "AsmExpr"; | ||
| 232 | case NodeTypeFieldAccessExpr: | ||
| 233 | return "FieldAccessExpr"; | ||
| 234 | case NodeTypePtrDeref: | ||
| 235 | return "PtrDerefExpr"; | ||
| 236 | case NodeTypeUnwrapOptional: | ||
| 237 | return "UnwrapOptional"; | ||
| 238 | case NodeTypeContainerDecl: | ||
| 239 | return "ContainerDecl"; | ||
| 240 | case NodeTypeStructField: | ||
| 241 | return "StructField"; | ||
| 242 | case NodeTypeStructValueField: | ||
| 243 | return "StructValueField"; | ||
| 244 | case NodeTypeContainerInitExpr: | ||
| 245 | return "ContainerInitExpr"; | ||
| 246 | case NodeTypeArrayType: | ||
| 247 | return "ArrayType"; | ||
| 248 | case NodeTypeInferredArrayType: | ||
| 249 | return "InferredArrayType"; | ||
| 250 | case NodeTypeErrorType: | ||
| 251 | return "ErrorType"; | ||
| 252 | case NodeTypeIfErrorExpr: | ||
| 253 | return "IfErrorExpr"; | ||
| 254 | case NodeTypeIfOptional: | ||
| 255 | return "IfOptional"; | ||
| 256 | case NodeTypeErrorSetDecl: | ||
| 257 | return "ErrorSetDecl"; | ||
| 258 | case NodeTypeResume: | ||
| 259 | return "Resume"; | ||
| 260 | case NodeTypeAwaitExpr: | ||
| 261 | return "AwaitExpr"; | ||
| 262 | case NodeTypeSuspend: | ||
| 263 | return "Suspend"; | ||
| 264 | case NodeTypePointerType: | ||
| 265 | return "PointerType"; | ||
| 266 | case NodeTypeAnyFrameType: | ||
| 267 | return "AnyFrameType"; | ||
| 268 | case NodeTypeEnumLiteral: | ||
| 269 | return "EnumLiteral"; | ||
| 270 | case NodeTypeErrorSetField: | ||
| 271 | return "ErrorSetField"; | ||
| 272 | case NodeTypeAnyTypeField: | ||
| 273 | return "AnyTypeField"; | ||
| 274 | } | ||
| 275 | zig_unreachable(); | ||
| 276 | } | ||
| 277 | |||
| 278 | struct AstPrint { | ||
| 279 | int indent; | ||
| 280 | FILE *f; | ||
| 281 | }; | ||
| 282 | |||
| 283 | static void ast_print_visit(AstNode **node_ptr, void *context) { | ||
| 284 | AstNode *node = *node_ptr; | ||
| 285 | AstPrint *ap = (AstPrint *)context; | ||
| 286 | |||
| 287 | for (int i = 0; i < ap->indent; i += 1) { | ||
| 288 | fprintf(ap->f, " "); | ||
| 289 | } | ||
| 290 | |||
| 291 | fprintf(ap->f, "%s\n", node_type_str(node->type)); | ||
| 292 | |||
| 293 | AstPrint new_ap; | ||
| 294 | new_ap.indent = ap->indent + 2; | ||
| 295 | new_ap.f = ap->f; | ||
| 296 | |||
| 297 | ast_visit_node_children(node, ast_print_visit, &new_ap); | ||
| 298 | } | ||
| 299 | |||
| 300 | void ast_print(FILE *f, AstNode *node, int indent) { | ||
| 301 | AstPrint ap; | ||
| 302 | ap.indent = indent; | ||
| 303 | ap.f = f; | ||
| 304 | ast_visit_node_children(node, ast_print_visit, &ap); | ||
| 305 | } | ||
| 306 | |||
| 307 | |||
| 308 | struct AstRender { | ||
| 309 | int indent; | ||
| 310 | int indent_size; | ||
| 311 | FILE *f; | ||
| 312 | }; | ||
| 313 | |||
| 314 | static void print_indent(AstRender *ar) { | ||
| 315 | for (int i = 0; i < ar->indent; i += 1) { | ||
| 316 | fprintf(ar->f, " "); | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | static bool is_alpha_under(uint8_t c) { | ||
| 321 | return (c >= 'a' && c <= 'z') || | ||
| 322 | (c >= 'A' && c <= 'Z') || c == '_'; | ||
| 323 | } | ||
| 324 | |||
| 325 | static bool is_digit(uint8_t c) { | ||
| 326 | return (c >= '0' && c <= '9'); | ||
| 327 | } | ||
| 328 | |||
| 329 | static bool is_printable(uint8_t c) { | ||
| 330 | if (c == 0) { | ||
| 331 | return false; | ||
| 332 | } | ||
| 333 | static const uint8_t printables[] = | ||
| 334 | " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.~`!@#$%^&*()_-+=\\{}[];'\"?/<>,:"; | ||
| 335 | for (size_t i = 0; i < array_length(printables); i += 1) { | ||
| 336 | if (c == printables[i]) return true; | ||
| 337 | } | ||
| 338 | return false; | ||
| 339 | } | ||
| 340 | |||
| 341 | static void string_literal_escape(Buf *source, Buf *dest) { | ||
| 342 | buf_resize(dest, 0); | ||
| 343 | for (size_t i = 0; i < buf_len(source); i += 1) { | ||
| 344 | uint8_t c = *((uint8_t*)buf_ptr(source) + i); | ||
| 345 | if (c == '\'') { | ||
| 346 | buf_append_str(dest, "\\'"); | ||
| 347 | } else if (c == '"') { | ||
| 348 | buf_append_str(dest, "\\\""); | ||
| 349 | } else if (c == '\\') { | ||
| 350 | buf_append_str(dest, "\\\\"); | ||
| 351 | } else if (c == '\n') { | ||
| 352 | buf_append_str(dest, "\\n"); | ||
| 353 | } else if (c == '\r') { | ||
| 354 | buf_append_str(dest, "\\r"); | ||
| 355 | } else if (c == '\t') { | ||
| 356 | buf_append_str(dest, "\\t"); | ||
| 357 | } else if (is_printable(c)) { | ||
| 358 | buf_append_char(dest, c); | ||
| 359 | } else { | ||
| 360 | buf_appendf(dest, "\\x%02x", (int)c); | ||
| 361 | } | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | static bool is_valid_bare_symbol(Buf *symbol) { | ||
| 366 | if (buf_len(symbol) == 0) { | ||
| 367 | return false; | ||
| 368 | } | ||
| 369 | uint8_t first_char = *buf_ptr(symbol); | ||
| 370 | if (!is_alpha_under(first_char)) { | ||
| 371 | return false; | ||
| 372 | } | ||
| 373 | for (size_t i = 1; i < buf_len(symbol); i += 1) { | ||
| 374 | uint8_t c = *((uint8_t*)buf_ptr(symbol) + i); | ||
| 375 | if (!is_alpha_under(c) && !is_digit(c)) { | ||
| 376 | return false; | ||
| 377 | } | ||
| 378 | } | ||
| 379 | return true; | ||
| 380 | } | ||
| 381 | |||
| 382 | static void print_symbol(AstRender *ar, Buf *symbol) { | ||
| 383 | if (is_zig_keyword(symbol)) { | ||
| 384 | fprintf(ar->f, "@\"%s\"", buf_ptr(symbol)); | ||
| 385 | return; | ||
| 386 | } | ||
| 387 | if (is_valid_bare_symbol(symbol)) { | ||
| 388 | fprintf(ar->f, "%s", buf_ptr(symbol)); | ||
| 389 | return; | ||
| 390 | } | ||
| 391 | Buf escaped = BUF_INIT; | ||
| 392 | string_literal_escape(symbol, &escaped); | ||
| 393 | fprintf(ar->f, "@\"%s\"", buf_ptr(&escaped)); | ||
| 394 | } | ||
| 395 | |||
| 396 | static bool statement_terminates_without_semicolon(AstNode *node) { | ||
| 397 | switch (node->type) { | ||
| 398 | case NodeTypeIfBoolExpr: | ||
| 399 | if (node->data.if_bool_expr.else_node) | ||
| 400 | return statement_terminates_without_semicolon(node->data.if_bool_expr.else_node); | ||
| 401 | return node->data.if_bool_expr.then_block->type == NodeTypeBlock; | ||
| 402 | case NodeTypeIfErrorExpr: | ||
| 403 | if (node->data.if_err_expr.else_node) | ||
| 404 | return statement_terminates_without_semicolon(node->data.if_err_expr.else_node); | ||
| 405 | return node->data.if_err_expr.then_node->type == NodeTypeBlock; | ||
| 406 | case NodeTypeIfOptional: | ||
| 407 | if (node->data.test_expr.else_node) | ||
| 408 | return statement_terminates_without_semicolon(node->data.test_expr.else_node); | ||
| 409 | return node->data.test_expr.then_node->type == NodeTypeBlock; | ||
| 410 | case NodeTypeWhileExpr: | ||
| 411 | return node->data.while_expr.body->type == NodeTypeBlock; | ||
| 412 | case NodeTypeForExpr: | ||
| 413 | return node->data.for_expr.body->type == NodeTypeBlock; | ||
| 414 | case NodeTypeCompTime: | ||
| 415 | return node->data.comptime_expr.expr->type == NodeTypeBlock; | ||
| 416 | case NodeTypeDefer: | ||
| 417 | return node->data.defer.expr->type == NodeTypeBlock; | ||
| 418 | case NodeTypeSuspend: | ||
| 419 | return node->data.suspend.block != nullptr && node->data.suspend.block->type == NodeTypeBlock; | ||
| 420 | case NodeTypeSwitchExpr: | ||
| 421 | case NodeTypeBlock: | ||
| 422 | return true; | ||
| 423 | default: | ||
| 424 | return false; | ||
| 425 | } | ||
| 426 | } | ||
| 427 | |||
| 428 | static void render_node_extra(AstRender *ar, AstNode *node, bool grouped); | ||
| 429 | |||
| 430 | static void render_node_grouped(AstRender *ar, AstNode *node) { | ||
| 431 | return render_node_extra(ar, node, true); | ||
| 432 | } | ||
| 433 | |||
| 434 | static void render_node_ungrouped(AstRender *ar, AstNode *node) { | ||
| 435 | return render_node_extra(ar, node, false); | ||
| 436 | } | ||
| 437 | |||
| 438 | static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ||
| 439 | switch (node->type) { | ||
| 440 | case NodeTypeSwitchProng: | ||
| 441 | case NodeTypeSwitchRange: | ||
| 442 | case NodeTypeStructValueField: | ||
| 443 | zig_unreachable(); | ||
| 444 | case NodeTypeFnProto: | ||
| 445 | { | ||
| 446 | const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod); | ||
| 447 | const char *extern_str = extern_string(node->data.fn_proto.is_extern); | ||
| 448 | const char *export_str = export_string(node->data.fn_proto.is_export); | ||
| 449 | const char *inline_str = inline_string(node->data.fn_proto.fn_inline); | ||
| 450 | fprintf(ar->f, "%s%s%s%sfn ", pub_str, inline_str, export_str, extern_str); | ||
| 451 | if (node->data.fn_proto.name != nullptr) { | ||
| 452 | print_symbol(ar, node->data.fn_proto.name); | ||
| 453 | } | ||
| 454 | fprintf(ar->f, "("); | ||
| 455 | size_t arg_count = node->data.fn_proto.params.length; | ||
| 456 | for (size_t arg_i = 0; arg_i < arg_count; arg_i += 1) { | ||
| 457 | AstNode *param_decl = node->data.fn_proto.params.at(arg_i); | ||
| 458 | assert(param_decl->type == NodeTypeParamDecl); | ||
| 459 | if (param_decl->data.param_decl.name != nullptr) { | ||
| 460 | const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : ""; | ||
| 461 | const char *inline_str = param_decl->data.param_decl.is_comptime ? "comptime " : ""; | ||
| 462 | fprintf(ar->f, "%s%s", noalias_str, inline_str); | ||
| 463 | print_symbol(ar, param_decl->data.param_decl.name); | ||
| 464 | fprintf(ar->f, ": "); | ||
| 465 | } | ||
| 466 | if (param_decl->data.param_decl.is_var_args) { | ||
| 467 | fprintf(ar->f, "..."); | ||
| 468 | } else if (param_decl->data.param_decl.anytype_token != nullptr) { | ||
| 469 | fprintf(ar->f, "anytype"); | ||
| 470 | } else { | ||
| 471 | render_node_grouped(ar, param_decl->data.param_decl.type); | ||
| 472 | } | ||
| 473 | |||
| 474 | if (arg_i + 1 < arg_count) { | ||
| 475 | fprintf(ar->f, ", "); | ||
| 476 | } | ||
| 477 | } | ||
| 478 | if (node->data.fn_proto.is_var_args) { | ||
| 479 | fprintf(ar->f, ", ..."); | ||
| 480 | } | ||
| 481 | fprintf(ar->f, ")"); | ||
| 482 | if (node->data.fn_proto.align_expr) { | ||
| 483 | fprintf(ar->f, " align("); | ||
| 484 | render_node_grouped(ar, node->data.fn_proto.align_expr); | ||
| 485 | fprintf(ar->f, ")"); | ||
| 486 | } | ||
| 487 | if (node->data.fn_proto.section_expr) { | ||
| 488 | fprintf(ar->f, " section("); | ||
| 489 | render_node_grouped(ar, node->data.fn_proto.section_expr); | ||
| 490 | fprintf(ar->f, ")"); | ||
| 491 | } | ||
| 492 | if (node->data.fn_proto.callconv_expr) { | ||
| 493 | fprintf(ar->f, " callconv("); | ||
| 494 | render_node_grouped(ar, node->data.fn_proto.callconv_expr); | ||
| 495 | fprintf(ar->f, ")"); | ||
| 496 | } | ||
| 497 | |||
| 498 | AstNode *return_type_node = node->data.fn_proto.return_type; | ||
| 499 | assert(return_type_node != nullptr); | ||
| 500 | fprintf(ar->f, " "); | ||
| 501 | if (node->data.fn_proto.auto_err_set) { | ||
| 502 | fprintf(ar->f, "!"); | ||
| 503 | } | ||
| 504 | render_node_grouped(ar, return_type_node); | ||
| 505 | break; | ||
| 506 | } | ||
| 507 | case NodeTypeFnDef: | ||
| 508 | { | ||
| 509 | render_node_grouped(ar, node->data.fn_def.fn_proto); | ||
| 510 | fprintf(ar->f, " "); | ||
| 511 | render_node_grouped(ar, node->data.fn_def.body); | ||
| 512 | break; | ||
| 513 | } | ||
| 514 | case NodeTypeBlock: | ||
| 515 | if (node->data.block.name != nullptr) { | ||
| 516 | fprintf(ar->f, "%s: ", buf_ptr(node->data.block.name)); | ||
| 517 | } | ||
| 518 | if (node->data.block.statements.length == 0) { | ||
| 519 | fprintf(ar->f, "{}"); | ||
| 520 | break; | ||
| 521 | } | ||
| 522 | fprintf(ar->f, "{\n"); | ||
| 523 | ar->indent += ar->indent_size; | ||
| 524 | for (size_t i = 0; i < node->data.block.statements.length; i += 1) { | ||
| 525 | AstNode *statement = node->data.block.statements.at(i); | ||
| 526 | print_indent(ar); | ||
| 527 | render_node_grouped(ar, statement); | ||
| 528 | |||
| 529 | if (!statement_terminates_without_semicolon(statement)) | ||
| 530 | fprintf(ar->f, ";"); | ||
| 531 | |||
| 532 | fprintf(ar->f, "\n"); | ||
| 533 | } | ||
| 534 | ar->indent -= ar->indent_size; | ||
| 535 | print_indent(ar); | ||
| 536 | fprintf(ar->f, "}"); | ||
| 537 | break; | ||
| 538 | case NodeTypeGroupedExpr: | ||
| 539 | fprintf(ar->f, "("); | ||
| 540 | render_node_ungrouped(ar, node->data.grouped_expr); | ||
| 541 | fprintf(ar->f, ")"); | ||
| 542 | break; | ||
| 543 | case NodeTypeReturnExpr: | ||
| 544 | { | ||
| 545 | const char *return_str = return_string(node->data.return_expr.kind); | ||
| 546 | fprintf(ar->f, "%s", return_str); | ||
| 547 | if (node->data.return_expr.expr) { | ||
| 548 | fprintf(ar->f, " "); | ||
| 549 | render_node_grouped(ar, node->data.return_expr.expr); | ||
| 550 | } | ||
| 551 | break; | ||
| 552 | } | ||
| 553 | case NodeTypeBreak: | ||
| 554 | { | ||
| 555 | fprintf(ar->f, "break"); | ||
| 556 | if (node->data.break_expr.name != nullptr) { | ||
| 557 | fprintf(ar->f, " :%s", buf_ptr(node->data.break_expr.name)); | ||
| 558 | } | ||
| 559 | if (node->data.break_expr.expr) { | ||
| 560 | fprintf(ar->f, " "); | ||
| 561 | render_node_grouped(ar, node->data.break_expr.expr); | ||
| 562 | } | ||
| 563 | break; | ||
| 564 | } | ||
| 565 | case NodeTypeDefer: | ||
| 566 | { | ||
| 567 | const char *defer_str = defer_string(node->data.defer.kind); | ||
| 568 | fprintf(ar->f, "%s ", defer_str); | ||
| 569 | render_node_grouped(ar, node->data.defer.expr); | ||
| 570 | break; | ||
| 571 | } | ||
| 572 | case NodeTypeVariableDeclaration: | ||
| 573 | { | ||
| 574 | const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod); | ||
| 575 | const char *extern_str = extern_string(node->data.variable_declaration.is_extern); | ||
| 576 | const char *thread_local_str = thread_local_string(node->data.variable_declaration.threadlocal_tok); | ||
| 577 | const char *const_or_var = const_or_var_string(node->data.variable_declaration.is_const); | ||
| 578 | fprintf(ar->f, "%s%s%s%s ", pub_str, extern_str, thread_local_str, const_or_var); | ||
| 579 | print_symbol(ar, node->data.variable_declaration.symbol); | ||
| 580 | |||
| 581 | if (node->data.variable_declaration.type) { | ||
| 582 | fprintf(ar->f, ": "); | ||
| 583 | render_node_grouped(ar, node->data.variable_declaration.type); | ||
| 584 | } | ||
| 585 | if (node->data.variable_declaration.align_expr) { | ||
| 586 | fprintf(ar->f, "align("); | ||
| 587 | render_node_grouped(ar, node->data.variable_declaration.align_expr); | ||
| 588 | fprintf(ar->f, ") "); | ||
| 589 | } | ||
| 590 | if (node->data.variable_declaration.section_expr) { | ||
| 591 | fprintf(ar->f, "section("); | ||
| 592 | render_node_grouped(ar, node->data.variable_declaration.section_expr); | ||
| 593 | fprintf(ar->f, ") "); | ||
| 594 | } | ||
| 595 | if (node->data.variable_declaration.expr) { | ||
| 596 | fprintf(ar->f, " = "); | ||
| 597 | render_node_grouped(ar, node->data.variable_declaration.expr); | ||
| 598 | } | ||
| 599 | break; | ||
| 600 | } | ||
| 601 | case NodeTypeBinOpExpr: | ||
| 602 | if (!grouped) fprintf(ar->f, "("); | ||
| 603 | render_node_ungrouped(ar, node->data.bin_op_expr.op1); | ||
| 604 | fprintf(ar->f, " %s ", bin_op_str(node->data.bin_op_expr.bin_op)); | ||
| 605 | render_node_ungrouped(ar, node->data.bin_op_expr.op2); | ||
| 606 | if (!grouped) fprintf(ar->f, ")"); | ||
| 607 | break; | ||
| 608 | case NodeTypeFloatLiteral: | ||
| 609 | { | ||
| 610 | Buf rendered_buf = BUF_INIT; | ||
| 611 | buf_resize(&rendered_buf, 0); | ||
| 612 | bigfloat_append_buf(&rendered_buf, node->data.float_literal.bigfloat); | ||
| 613 | fprintf(ar->f, "%s", buf_ptr(&rendered_buf)); | ||
| 614 | } | ||
| 615 | break; | ||
| 616 | case NodeTypeIntLiteral: | ||
| 617 | { | ||
| 618 | Buf rendered_buf = BUF_INIT; | ||
| 619 | buf_resize(&rendered_buf, 0); | ||
| 620 | bigint_append_buf(&rendered_buf, node->data.int_literal.bigint, 10); | ||
| 621 | fprintf(ar->f, "%s", buf_ptr(&rendered_buf)); | ||
| 622 | } | ||
| 623 | break; | ||
| 624 | case NodeTypeStringLiteral: | ||
| 625 | { | ||
| 626 | Buf tmp_buf = BUF_INIT; | ||
| 627 | string_literal_escape(node->data.string_literal.buf, &tmp_buf); | ||
| 628 | fprintf(ar->f, "\"%s\"", buf_ptr(&tmp_buf)); | ||
| 629 | } | ||
| 630 | break; | ||
| 631 | case NodeTypeCharLiteral: | ||
| 632 | { | ||
| 633 | uint8_t c = node->data.char_literal.value; | ||
| 634 | if (c == '\'') { | ||
| 635 | fprintf(ar->f, "'\\''"); | ||
| 636 | } else if (c == '\"') { | ||
| 637 | fprintf(ar->f, "'\\\"'"); | ||
| 638 | } else if (c == '\\') { | ||
| 639 | fprintf(ar->f, "'\\\\'"); | ||
| 640 | } else if (c == '\n') { | ||
| 641 | fprintf(ar->f, "'\\n'"); | ||
| 642 | } else if (c == '\r') { | ||
| 643 | fprintf(ar->f, "'\\r'"); | ||
| 644 | } else if (c == '\t') { | ||
| 645 | fprintf(ar->f, "'\\t'"); | ||
| 646 | } else if (is_printable(c)) { | ||
| 647 | fprintf(ar->f, "'%c'", c); | ||
| 648 | } else { | ||
| 649 | fprintf(ar->f, "'\\x%02x'", (int)c); | ||
| 650 | } | ||
| 651 | break; | ||
| 652 | } | ||
| 653 | case NodeTypeSymbol: | ||
| 654 | print_symbol(ar, node->data.symbol_expr.symbol); | ||
| 655 | break; | ||
| 656 | case NodeTypePrefixOpExpr: | ||
| 657 | { | ||
| 658 | if (!grouped) fprintf(ar->f, "("); | ||
| 659 | PrefixOp op = node->data.prefix_op_expr.prefix_op; | ||
| 660 | fprintf(ar->f, "%s", prefix_op_str(op)); | ||
| 661 | |||
| 662 | AstNode *child_node = node->data.prefix_op_expr.primary_expr; | ||
| 663 | bool new_grouped = child_node->type == NodeTypePrefixOpExpr || child_node->type == NodeTypePointerType; | ||
| 664 | render_node_extra(ar, child_node, new_grouped); | ||
| 665 | if (!grouped) fprintf(ar->f, ")"); | ||
| 666 | break; | ||
| 667 | } | ||
| 668 | case NodeTypePointerType: | ||
| 669 | { | ||
| 670 | if (!grouped) fprintf(ar->f, "("); | ||
| 671 | const char *ptr_len_str = token_to_ptr_len_str(node->data.pointer_type.star_token); | ||
| 672 | fprintf(ar->f, "%s", ptr_len_str); | ||
| 673 | if (node->data.pointer_type.align_expr != nullptr) { | ||
| 674 | fprintf(ar->f, "align("); | ||
| 675 | render_node_grouped(ar, node->data.pointer_type.align_expr); | ||
| 676 | if (node->data.pointer_type.bit_offset_start != nullptr) { | ||
| 677 | assert(node->data.pointer_type.host_int_bytes != nullptr); | ||
| 678 | |||
| 679 | Buf offset_start_buf = BUF_INIT; | ||
| 680 | buf_resize(&offset_start_buf, 0); | ||
| 681 | bigint_append_buf(&offset_start_buf, node->data.pointer_type.bit_offset_start, 10); | ||
| 682 | |||
| 683 | Buf offset_end_buf = BUF_INIT; | ||
| 684 | buf_resize(&offset_end_buf, 0); | ||
| 685 | bigint_append_buf(&offset_end_buf, node->data.pointer_type.host_int_bytes, 10); | ||
| 686 | |||
| 687 | fprintf(ar->f, ":%s:%s ", buf_ptr(&offset_start_buf), buf_ptr(&offset_end_buf)); | ||
| 688 | } | ||
| 689 | fprintf(ar->f, ") "); | ||
| 690 | } | ||
| 691 | if (node->data.pointer_type.is_const) { | ||
| 692 | fprintf(ar->f, "const "); | ||
| 693 | } | ||
| 694 | if (node->data.pointer_type.is_volatile) { | ||
| 695 | fprintf(ar->f, "volatile "); | ||
| 696 | } | ||
| 697 | |||
| 698 | render_node_ungrouped(ar, node->data.pointer_type.op_expr); | ||
| 699 | if (!grouped) fprintf(ar->f, ")"); | ||
| 700 | break; | ||
| 701 | } | ||
| 702 | case NodeTypeFnCallExpr: | ||
| 703 | { | ||
| 704 | switch (node->data.fn_call_expr.modifier) { | ||
| 705 | case CallModifierNone: | ||
| 706 | break; | ||
| 707 | case CallModifierNoSuspend: | ||
| 708 | fprintf(ar->f, "nosuspend "); | ||
| 709 | break; | ||
| 710 | case CallModifierAsync: | ||
| 711 | fprintf(ar->f, "async "); | ||
| 712 | break; | ||
| 713 | case CallModifierNeverTail: | ||
| 714 | fprintf(ar->f, "notail "); | ||
| 715 | break; | ||
| 716 | case CallModifierNeverInline: | ||
| 717 | fprintf(ar->f, "noinline "); | ||
| 718 | break; | ||
| 719 | case CallModifierAlwaysTail: | ||
| 720 | fprintf(ar->f, "tail "); | ||
| 721 | break; | ||
| 722 | case CallModifierAlwaysInline: | ||
| 723 | fprintf(ar->f, "inline "); | ||
| 724 | break; | ||
| 725 | case CallModifierCompileTime: | ||
| 726 | fprintf(ar->f, "comptime "); | ||
| 727 | break; | ||
| 728 | case CallModifierBuiltin: | ||
| 729 | fprintf(ar->f, "@"); | ||
| 730 | break; | ||
| 731 | } | ||
| 732 | AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; | ||
| 733 | bool grouped = (fn_ref_node->type != NodeTypePrefixOpExpr && fn_ref_node->type != NodeTypePointerType); | ||
| 734 | render_node_extra(ar, fn_ref_node, grouped); | ||
| 735 | fprintf(ar->f, "("); | ||
| 736 | for (size_t i = 0; i < node->data.fn_call_expr.params.length; i += 1) { | ||
| 737 | AstNode *param = node->data.fn_call_expr.params.at(i); | ||
| 738 | if (i != 0) { | ||
| 739 | fprintf(ar->f, ", "); | ||
| 740 | } | ||
| 741 | render_node_grouped(ar, param); | ||
| 742 | } | ||
| 743 | fprintf(ar->f, ")"); | ||
| 744 | break; | ||
| 745 | } | ||
| 746 | case NodeTypeArrayAccessExpr: | ||
| 747 | render_node_ungrouped(ar, node->data.array_access_expr.array_ref_expr); | ||
| 748 | fprintf(ar->f, "["); | ||
| 749 | render_node_grouped(ar, node->data.array_access_expr.subscript); | ||
| 750 | fprintf(ar->f, "]"); | ||
| 751 | break; | ||
| 752 | case NodeTypeFieldAccessExpr: | ||
| 753 | { | ||
| 754 | AstNode *lhs = node->data.field_access_expr.struct_expr; | ||
| 755 | Buf *rhs = node->data.field_access_expr.field_name; | ||
| 756 | if (lhs->type == NodeTypeErrorType) { | ||
| 757 | fprintf(ar->f, "error"); | ||
| 758 | } else { | ||
| 759 | render_node_ungrouped(ar, lhs); | ||
| 760 | } | ||
| 761 | fprintf(ar->f, "."); | ||
| 762 | print_symbol(ar, rhs); | ||
| 763 | break; | ||
| 764 | } | ||
| 765 | case NodeTypePtrDeref: | ||
| 766 | { | ||
| 767 | AstNode *lhs = node->data.ptr_deref_expr.target; | ||
| 768 | render_node_ungrouped(ar, lhs); | ||
| 769 | fprintf(ar->f, ".*"); | ||
| 770 | break; | ||
| 771 | } | ||
| 772 | case NodeTypeUnwrapOptional: | ||
| 773 | { | ||
| 774 | AstNode *lhs = node->data.unwrap_optional.expr; | ||
| 775 | render_node_ungrouped(ar, lhs); | ||
| 776 | fprintf(ar->f, ".?"); | ||
| 777 | break; | ||
| 778 | } | ||
| 779 | case NodeTypeUndefinedLiteral: | ||
| 780 | fprintf(ar->f, "undefined"); | ||
| 781 | break; | ||
| 782 | case NodeTypeContainerDecl: | ||
| 783 | { | ||
| 784 | if (!node->data.container_decl.is_root) { | ||
| 785 | const char *layout_str = layout_string(node->data.container_decl.layout); | ||
| 786 | const char *container_str = container_string(node->data.container_decl.kind); | ||
| 787 | fprintf(ar->f, "%s%s", layout_str, container_str); | ||
| 788 | if (node->data.container_decl.auto_enum) { | ||
| 789 | fprintf(ar->f, "(enum"); | ||
| 790 | } | ||
| 791 | if (node->data.container_decl.init_arg_expr != nullptr) { | ||
| 792 | fprintf(ar->f, "("); | ||
| 793 | render_node_grouped(ar, node->data.container_decl.init_arg_expr); | ||
| 794 | fprintf(ar->f, ")"); | ||
| 795 | } | ||
| 796 | if (node->data.container_decl.auto_enum) { | ||
| 797 | fprintf(ar->f, ")"); | ||
| 798 | } | ||
| 799 | |||
| 800 | fprintf(ar->f, " {\n"); | ||
| 801 | ar->indent += ar->indent_size; | ||
| 802 | } | ||
| 803 | for (size_t field_i = 0; field_i < node->data.container_decl.fields.length; field_i += 1) { | ||
| 804 | AstNode *field_node = node->data.container_decl.fields.at(field_i); | ||
| 805 | assert(field_node->type == NodeTypeStructField); | ||
| 806 | print_indent(ar); | ||
| 807 | print_symbol(ar, field_node->data.struct_field.name); | ||
| 808 | if (field_node->data.struct_field.type != nullptr) { | ||
| 809 | fprintf(ar->f, ": "); | ||
| 810 | render_node_grouped(ar, field_node->data.struct_field.type); | ||
| 811 | } | ||
| 812 | if (field_node->data.struct_field.value != nullptr) { | ||
| 813 | fprintf(ar->f, " = "); | ||
| 814 | render_node_grouped(ar, field_node->data.struct_field.value); | ||
| 815 | } | ||
| 816 | fprintf(ar->f, ",\n"); | ||
| 817 | } | ||
| 818 | |||
| 819 | for (size_t decl_i = 0; decl_i < node->data.container_decl.decls.length; decl_i += 1) { | ||
| 820 | AstNode *decls_node = node->data.container_decl.decls.at(decl_i); | ||
| 821 | render_node_grouped(ar, decls_node); | ||
| 822 | |||
| 823 | if (decls_node->type == NodeTypeUsingNamespace || | ||
| 824 | decls_node->type == NodeTypeVariableDeclaration || | ||
| 825 | decls_node->type == NodeTypeFnProto) | ||
| 826 | { | ||
| 827 | fprintf(ar->f, ";"); | ||
| 828 | } | ||
| 829 | fprintf(ar->f, "\n"); | ||
| 830 | } | ||
| 831 | |||
| 832 | if (!node->data.container_decl.is_root) { | ||
| 833 | ar->indent -= ar->indent_size; | ||
| 834 | print_indent(ar); | ||
| 835 | fprintf(ar->f, "}"); | ||
| 836 | } | ||
| 837 | break; | ||
| 838 | } | ||
| 839 | case NodeTypeContainerInitExpr: | ||
| 840 | if (node->data.container_init_expr.type != nullptr) { | ||
| 841 | render_node_ungrouped(ar, node->data.container_init_expr.type); | ||
| 842 | } | ||
| 843 | if (node->data.container_init_expr.kind == ContainerInitKindStruct) { | ||
| 844 | fprintf(ar->f, "{\n"); | ||
| 845 | ar->indent += ar->indent_size; | ||
| 846 | } else { | ||
| 847 | fprintf(ar->f, "{"); | ||
| 848 | } | ||
| 849 | for (size_t i = 0; i < node->data.container_init_expr.entries.length; i += 1) { | ||
| 850 | AstNode *entry = node->data.container_init_expr.entries.at(i); | ||
| 851 | if (entry->type == NodeTypeStructValueField) { | ||
| 852 | Buf *name = entry->data.struct_val_field.name; | ||
| 853 | AstNode *expr = entry->data.struct_val_field.expr; | ||
| 854 | print_indent(ar); | ||
| 855 | fprintf(ar->f, ".%s = ", buf_ptr(name)); | ||
| 856 | render_node_grouped(ar, expr); | ||
| 857 | fprintf(ar->f, ",\n"); | ||
| 858 | } else { | ||
| 859 | if (i != 0) | ||
| 860 | fprintf(ar->f, ", "); | ||
| 861 | render_node_grouped(ar, entry); | ||
| 862 | } | ||
| 863 | } | ||
| 864 | if (node->data.container_init_expr.kind == ContainerInitKindStruct) { | ||
| 865 | ar->indent -= ar->indent_size; | ||
| 866 | } | ||
| 867 | print_indent(ar); | ||
| 868 | fprintf(ar->f, "}"); | ||
| 869 | break; | ||
| 870 | case NodeTypeArrayType: | ||
| 871 | { | ||
| 872 | fprintf(ar->f, "["); | ||
| 873 | if (node->data.array_type.size) { | ||
| 874 | render_node_grouped(ar, node->data.array_type.size); | ||
| 875 | } | ||
| 876 | fprintf(ar->f, "]"); | ||
| 877 | if (node->data.array_type.is_const) { | ||
| 878 | fprintf(ar->f, "const "); | ||
| 879 | } | ||
| 880 | render_node_ungrouped(ar, node->data.array_type.child_type); | ||
| 881 | break; | ||
| 882 | } | ||
| 883 | case NodeTypeInferredArrayType: | ||
| 884 | { | ||
| 885 | fprintf(ar->f, "[_]"); | ||
| 886 | render_node_ungrouped(ar, node->data.inferred_array_type.child_type); | ||
| 887 | break; | ||
| 888 | } | ||
| 889 | case NodeTypeAnyFrameType: { | ||
| 890 | fprintf(ar->f, "anyframe"); | ||
| 891 | if (node->data.anyframe_type.payload_type != nullptr) { | ||
| 892 | fprintf(ar->f, "->"); | ||
| 893 | render_node_grouped(ar, node->data.anyframe_type.payload_type); | ||
| 894 | } | ||
| 895 | break; | ||
| 896 | } | ||
| 897 | case NodeTypeErrorType: | ||
| 898 | fprintf(ar->f, "anyerror"); | ||
| 899 | break; | ||
| 900 | case NodeTypeAsmExpr: | ||
| 901 | { | ||
| 902 | AstNodeAsmExpr *asm_expr = &node->data.asm_expr; | ||
| 903 | const char *volatile_str = (asm_expr->volatile_token != nullptr) ? " volatile" : ""; | ||
| 904 | fprintf(ar->f, "asm%s (", volatile_str); | ||
| 905 | render_node_ungrouped(ar, asm_expr->asm_template); | ||
| 906 | fprintf(ar->f, ")"); | ||
| 907 | print_indent(ar); | ||
| 908 | fprintf(ar->f, ": "); | ||
| 909 | for (size_t i = 0; i < asm_expr->output_list.length; i += 1) { | ||
| 910 | AsmOutput *asm_output = asm_expr->output_list.at(i); | ||
| 911 | |||
| 912 | if (i != 0) { | ||
| 913 | fprintf(ar->f, ",\n"); | ||
| 914 | print_indent(ar); | ||
| 915 | } | ||
| 916 | |||
| 917 | fprintf(ar->f, "[%s] \"%s\" (", | ||
| 918 | buf_ptr(asm_output->asm_symbolic_name), | ||
| 919 | buf_ptr(asm_output->constraint)); | ||
| 920 | if (asm_output->return_type) { | ||
| 921 | fprintf(ar->f, "-> "); | ||
| 922 | render_node_grouped(ar, asm_output->return_type); | ||
| 923 | } else { | ||
| 924 | fprintf(ar->f, "%s", buf_ptr(asm_output->variable_name)); | ||
| 925 | } | ||
| 926 | fprintf(ar->f, ")"); | ||
| 927 | } | ||
| 928 | fprintf(ar->f, "\n"); | ||
| 929 | print_indent(ar); | ||
| 930 | fprintf(ar->f, ": "); | ||
| 931 | for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { | ||
| 932 | AsmInput *asm_input = asm_expr->input_list.at(i); | ||
| 933 | |||
| 934 | if (i != 0) { | ||
| 935 | fprintf(ar->f, ",\n"); | ||
| 936 | print_indent(ar); | ||
| 937 | } | ||
| 938 | |||
| 939 | fprintf(ar->f, "[%s] \"%s\" (", | ||
| 940 | buf_ptr(asm_input->asm_symbolic_name), | ||
| 941 | buf_ptr(asm_input->constraint)); | ||
| 942 | render_node_grouped(ar, asm_input->expr); | ||
| 943 | fprintf(ar->f, ")"); | ||
| 944 | } | ||
| 945 | fprintf(ar->f, "\n"); | ||
| 946 | print_indent(ar); | ||
| 947 | fprintf(ar->f, ": "); | ||
| 948 | for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1) { | ||
| 949 | Buf *reg_name = asm_expr->clobber_list.at(i); | ||
| 950 | if (i != 0) fprintf(ar->f, ", "); | ||
| 951 | fprintf(ar->f, "\"%s\"", buf_ptr(reg_name)); | ||
| 952 | } | ||
| 953 | fprintf(ar->f, ")"); | ||
| 954 | break; | ||
| 955 | } | ||
| 956 | case NodeTypeWhileExpr: | ||
| 957 | { | ||
| 958 | if (node->data.while_expr.name != nullptr) { | ||
| 959 | fprintf(ar->f, "%s: ", buf_ptr(node->data.while_expr.name)); | ||
| 960 | } | ||
| 961 | const char *inline_str = node->data.while_expr.is_inline ? "inline " : ""; | ||
| 962 | fprintf(ar->f, "%swhile (", inline_str); | ||
| 963 | render_node_grouped(ar, node->data.while_expr.condition); | ||
| 964 | fprintf(ar->f, ") "); | ||
| 965 | if (node->data.while_expr.var_symbol) { | ||
| 966 | fprintf(ar->f, "|%s| ", buf_ptr(node->data.while_expr.var_symbol)); | ||
| 967 | } | ||
| 968 | if (node->data.while_expr.continue_expr) { | ||
| 969 | fprintf(ar->f, ": ("); | ||
| 970 | render_node_grouped(ar, node->data.while_expr.continue_expr); | ||
| 971 | fprintf(ar->f, ") "); | ||
| 972 | } | ||
| 973 | render_node_grouped(ar, node->data.while_expr.body); | ||
| 974 | if (node->data.while_expr.else_node) { | ||
| 975 | fprintf(ar->f, " else "); | ||
| 976 | if (node->data.while_expr.err_symbol) { | ||
| 977 | fprintf(ar->f, "|%s| ", buf_ptr(node->data.while_expr.err_symbol)); | ||
| 978 | } | ||
| 979 | render_node_grouped(ar, node->data.while_expr.else_node); | ||
| 980 | } | ||
| 981 | break; | ||
| 982 | } | ||
| 983 | case NodeTypeBoolLiteral: | ||
| 984 | { | ||
| 985 | const char *bool_str = node->data.bool_literal.value ? "true" : "false"; | ||
| 986 | fprintf(ar->f, "%s", bool_str); | ||
| 987 | break; | ||
| 988 | } | ||
| 989 | case NodeTypeIfBoolExpr: | ||
| 990 | { | ||
| 991 | fprintf(ar->f, "if ("); | ||
| 992 | render_node_grouped(ar, node->data.if_bool_expr.condition); | ||
| 993 | fprintf(ar->f, ") "); | ||
| 994 | render_node_grouped(ar, node->data.if_bool_expr.then_block); | ||
| 995 | if (node->data.if_bool_expr.else_node) { | ||
| 996 | fprintf(ar->f, " else "); | ||
| 997 | render_node_grouped(ar, node->data.if_bool_expr.else_node); | ||
| 998 | } | ||
| 999 | break; | ||
| 1000 | } | ||
| 1001 | case NodeTypeNullLiteral: | ||
| 1002 | { | ||
| 1003 | fprintf(ar->f, "null"); | ||
| 1004 | break; | ||
| 1005 | } | ||
| 1006 | case NodeTypeIfErrorExpr: | ||
| 1007 | { | ||
| 1008 | fprintf(ar->f, "if ("); | ||
| 1009 | render_node_grouped(ar, node->data.if_err_expr.target_node); | ||
| 1010 | fprintf(ar->f, ") "); | ||
| 1011 | if (node->data.if_err_expr.var_symbol) { | ||
| 1012 | const char *ptr_str = node->data.if_err_expr.var_is_ptr ? "*" : ""; | ||
| 1013 | const char *var_name = buf_ptr(node->data.if_err_expr.var_symbol); | ||
| 1014 | fprintf(ar->f, "|%s%s| ", ptr_str, var_name); | ||
| 1015 | } | ||
| 1016 | render_node_grouped(ar, node->data.if_err_expr.then_node); | ||
| 1017 | if (node->data.if_err_expr.else_node) { | ||
| 1018 | fprintf(ar->f, " else "); | ||
| 1019 | if (node->data.if_err_expr.err_symbol) { | ||
| 1020 | fprintf(ar->f, "|%s| ", buf_ptr(node->data.if_err_expr.err_symbol)); | ||
| 1021 | } | ||
| 1022 | render_node_grouped(ar, node->data.if_err_expr.else_node); | ||
| 1023 | } | ||
| 1024 | break; | ||
| 1025 | } | ||
| 1026 | case NodeTypeIfOptional: | ||
| 1027 | { | ||
| 1028 | fprintf(ar->f, "if ("); | ||
| 1029 | render_node_grouped(ar, node->data.test_expr.target_node); | ||
| 1030 | fprintf(ar->f, ") "); | ||
| 1031 | if (node->data.test_expr.var_symbol) { | ||
| 1032 | const char *ptr_str = node->data.test_expr.var_is_ptr ? "*" : ""; | ||
| 1033 | const char *var_name = buf_ptr(node->data.test_expr.var_symbol); | ||
| 1034 | fprintf(ar->f, "|%s%s| ", ptr_str, var_name); | ||
| 1035 | } | ||
| 1036 | render_node_grouped(ar, node->data.test_expr.then_node); | ||
| 1037 | if (node->data.test_expr.else_node) { | ||
| 1038 | fprintf(ar->f, " else "); | ||
| 1039 | render_node_grouped(ar, node->data.test_expr.else_node); | ||
| 1040 | } | ||
| 1041 | break; | ||
| 1042 | } | ||
| 1043 | case NodeTypeSwitchExpr: | ||
| 1044 | { | ||
| 1045 | AstNodeSwitchExpr *switch_expr = &node->data.switch_expr; | ||
| 1046 | fprintf(ar->f, "switch ("); | ||
| 1047 | render_node_grouped(ar, switch_expr->expr); | ||
| 1048 | fprintf(ar->f, ") {\n"); | ||
| 1049 | ar->indent += ar->indent_size; | ||
| 1050 | |||
| 1051 | for (size_t prong_i = 0; prong_i < switch_expr->prongs.length; prong_i += 1) { | ||
| 1052 | AstNode *prong_node = switch_expr->prongs.at(prong_i); | ||
| 1053 | AstNodeSwitchProng *switch_prong = &prong_node->data.switch_prong; | ||
| 1054 | print_indent(ar); | ||
| 1055 | for (size_t item_i = 0; item_i < switch_prong->items.length; item_i += 1) { | ||
| 1056 | AstNode *item_node = switch_prong->items.at(item_i); | ||
| 1057 | if (item_i != 0) | ||
| 1058 | fprintf(ar->f, ", "); | ||
| 1059 | if (item_node->type == NodeTypeSwitchRange) { | ||
| 1060 | AstNode *start_node = item_node->data.switch_range.start; | ||
| 1061 | AstNode *end_node = item_node->data.switch_range.end; | ||
| 1062 | render_node_grouped(ar, start_node); | ||
| 1063 | fprintf(ar->f, "..."); | ||
| 1064 | render_node_grouped(ar, end_node); | ||
| 1065 | } else { | ||
| 1066 | render_node_grouped(ar, item_node); | ||
| 1067 | } | ||
| 1068 | } | ||
| 1069 | const char *else_str = (switch_prong->items.length == 0) ? "else" : ""; | ||
| 1070 | fprintf(ar->f, "%s => ", else_str); | ||
| 1071 | if (switch_prong->var_symbol) { | ||
| 1072 | const char *star_str = switch_prong->var_is_ptr ? "*" : ""; | ||
| 1073 | Buf *var_name = switch_prong->var_symbol->data.symbol_expr.symbol; | ||
| 1074 | fprintf(ar->f, "|%s%s| ", star_str, buf_ptr(var_name)); | ||
| 1075 | } | ||
| 1076 | render_node_grouped(ar, switch_prong->expr); | ||
| 1077 | fprintf(ar->f, ",\n"); | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | ar->indent -= ar->indent_size; | ||
| 1081 | print_indent(ar); | ||
| 1082 | fprintf(ar->f, "}"); | ||
| 1083 | break; | ||
| 1084 | } | ||
| 1085 | case NodeTypeCompTime: | ||
| 1086 | { | ||
| 1087 | fprintf(ar->f, "comptime "); | ||
| 1088 | render_node_grouped(ar, node->data.comptime_expr.expr); | ||
| 1089 | break; | ||
| 1090 | } | ||
| 1091 | case NodeTypeNoSuspend: | ||
| 1092 | { | ||
| 1093 | fprintf(ar->f, "nosuspend "); | ||
| 1094 | render_node_grouped(ar, node->data.nosuspend_expr.expr); | ||
| 1095 | break; | ||
| 1096 | } | ||
| 1097 | case NodeTypeForExpr: | ||
| 1098 | { | ||
| 1099 | if (node->data.for_expr.name != nullptr) { | ||
| 1100 | fprintf(ar->f, "%s: ", buf_ptr(node->data.for_expr.name)); | ||
| 1101 | } | ||
| 1102 | const char *inline_str = node->data.for_expr.is_inline ? "inline " : ""; | ||
| 1103 | fprintf(ar->f, "%sfor (", inline_str); | ||
| 1104 | render_node_grouped(ar, node->data.for_expr.array_expr); | ||
| 1105 | fprintf(ar->f, ") "); | ||
| 1106 | if (node->data.for_expr.elem_node) { | ||
| 1107 | fprintf(ar->f, "|"); | ||
| 1108 | if (node->data.for_expr.elem_is_ptr) | ||
| 1109 | fprintf(ar->f, "*"); | ||
| 1110 | render_node_grouped(ar, node->data.for_expr.elem_node); | ||
| 1111 | if (node->data.for_expr.index_node) { | ||
| 1112 | fprintf(ar->f, ", "); | ||
| 1113 | render_node_grouped(ar, node->data.for_expr.index_node); | ||
| 1114 | } | ||
| 1115 | fprintf(ar->f, "| "); | ||
| 1116 | } | ||
| 1117 | render_node_grouped(ar, node->data.for_expr.body); | ||
| 1118 | if (node->data.for_expr.else_node) { | ||
| 1119 | fprintf(ar->f, " else"); | ||
| 1120 | render_node_grouped(ar, node->data.for_expr.else_node); | ||
| 1121 | } | ||
| 1122 | break; | ||
| 1123 | } | ||
| 1124 | case NodeTypeContinue: | ||
| 1125 | { | ||
| 1126 | fprintf(ar->f, "continue"); | ||
| 1127 | if (node->data.continue_expr.name != nullptr) { | ||
| 1128 | fprintf(ar->f, " :%s", buf_ptr(node->data.continue_expr.name)); | ||
| 1129 | } | ||
| 1130 | break; | ||
| 1131 | } | ||
| 1132 | case NodeTypeUnreachable: | ||
| 1133 | { | ||
| 1134 | fprintf(ar->f, "unreachable"); | ||
| 1135 | break; | ||
| 1136 | } | ||
| 1137 | case NodeTypeSliceExpr: | ||
| 1138 | { | ||
| 1139 | render_node_ungrouped(ar, node->data.slice_expr.array_ref_expr); | ||
| 1140 | fprintf(ar->f, "["); | ||
| 1141 | render_node_grouped(ar, node->data.slice_expr.start); | ||
| 1142 | fprintf(ar->f, ".."); | ||
| 1143 | if (node->data.slice_expr.end) | ||
| 1144 | render_node_grouped(ar, node->data.slice_expr.end); | ||
| 1145 | fprintf(ar->f, "]"); | ||
| 1146 | break; | ||
| 1147 | } | ||
| 1148 | case NodeTypeCatchExpr: | ||
| 1149 | { | ||
| 1150 | render_node_ungrouped(ar, node->data.unwrap_err_expr.op1); | ||
| 1151 | fprintf(ar->f, " catch "); | ||
| 1152 | if (node->data.unwrap_err_expr.symbol) { | ||
| 1153 | Buf *var_name = node->data.unwrap_err_expr.symbol->data.symbol_expr.symbol; | ||
| 1154 | fprintf(ar->f, "|%s| ", buf_ptr(var_name)); | ||
| 1155 | } | ||
| 1156 | render_node_ungrouped(ar, node->data.unwrap_err_expr.op2); | ||
| 1157 | break; | ||
| 1158 | } | ||
| 1159 | case NodeTypeErrorSetDecl: | ||
| 1160 | { | ||
| 1161 | fprintf(ar->f, "error {\n"); | ||
| 1162 | ar->indent += ar->indent_size; | ||
| 1163 | |||
| 1164 | for (size_t i = 0; i < node->data.err_set_decl.decls.length; i += 1) { | ||
| 1165 | AstNode *field_node = node->data.err_set_decl.decls.at(i); | ||
| 1166 | switch (field_node->type) { | ||
| 1167 | case NodeTypeSymbol: | ||
| 1168 | print_indent(ar); | ||
| 1169 | print_symbol(ar, field_node->data.symbol_expr.symbol); | ||
| 1170 | fprintf(ar->f, ",\n"); | ||
| 1171 | break; | ||
| 1172 | case NodeTypeErrorSetField: | ||
| 1173 | print_indent(ar); | ||
| 1174 | print_symbol(ar, field_node->data.err_set_field.field_name->data.symbol_expr.symbol); | ||
| 1175 | fprintf(ar->f, ",\n"); | ||
| 1176 | break; | ||
| 1177 | default: | ||
| 1178 | zig_unreachable(); | ||
| 1179 | } | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | ar->indent -= ar->indent_size; | ||
| 1183 | print_indent(ar); | ||
| 1184 | fprintf(ar->f, "}"); | ||
| 1185 | break; | ||
| 1186 | } | ||
| 1187 | case NodeTypeResume: | ||
| 1188 | { | ||
| 1189 | fprintf(ar->f, "resume "); | ||
| 1190 | render_node_grouped(ar, node->data.resume_expr.expr); | ||
| 1191 | break; | ||
| 1192 | } | ||
| 1193 | case NodeTypeAwaitExpr: | ||
| 1194 | { | ||
| 1195 | fprintf(ar->f, "await "); | ||
| 1196 | render_node_grouped(ar, node->data.await_expr.expr); | ||
| 1197 | break; | ||
| 1198 | } | ||
| 1199 | case NodeTypeSuspend: | ||
| 1200 | { | ||
| 1201 | if (node->data.suspend.block != nullptr) { | ||
| 1202 | fprintf(ar->f, "suspend "); | ||
| 1203 | render_node_grouped(ar, node->data.suspend.block); | ||
| 1204 | } else { | ||
| 1205 | fprintf(ar->f, "suspend\n"); | ||
| 1206 | } | ||
| 1207 | break; | ||
| 1208 | } | ||
| 1209 | case NodeTypeEnumLiteral: | ||
| 1210 | { | ||
| 1211 | fprintf(ar->f, ".%s", buf_ptr(&node->data.enum_literal.identifier->data.str_lit.str)); | ||
| 1212 | break; | ||
| 1213 | } | ||
| 1214 | case NodeTypeAnyTypeField: { | ||
| 1215 | fprintf(ar->f, "anytype"); | ||
| 1216 | break; | ||
| 1217 | } | ||
| 1218 | case NodeTypeParamDecl: | ||
| 1219 | case NodeTypeTestDecl: | ||
| 1220 | case NodeTypeStructField: | ||
| 1221 | case NodeTypeUsingNamespace: | ||
| 1222 | case NodeTypeErrorSetField: | ||
| 1223 | zig_panic("TODO more ast rendering"); | ||
| 1224 | } | ||
| 1225 | } | ||
| 1226 | |||
| 1227 | |||
| 1228 | void ast_render(FILE *f, AstNode *node, int indent_size) { | ||
| 1229 | AstRender ar = {0}; | ||
| 1230 | ar.f = f; | ||
| 1231 | ar.indent_size = indent_size; | ||
| 1232 | ar.indent = 0; | ||
| 1233 | |||
| 1234 | render_node_grouped(&ar, node); | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | void AstNode::src() { | ||
| 1238 | fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize "\n", | ||
| 1239 | buf_ptr(this->owner->data.structure.root_struct->path), | ||
| 1240 | this->line + 1, this->column + 1); | ||
| 1241 | } | ||
src/stage1/ast_render.hpp deleted-20| ... | @@ -1,20 +0,0 @@ | ||
| 1 | /* | ||
| 2 | * Copyright (c) 2015 Andrew Kelley | ||
| 3 | * | ||
| 4 | * This file is part of zig, which is MIT licensed. | ||
| 5 | * See http://opensource.org/licenses/MIT | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef ZIG_AST_RENDER_HPP | ||
| 9 | #define ZIG_AST_RENDER_HPP | ||
| 10 | |||
| 11 | #include "all_types.hpp" | ||
| 12 | #include "parser.hpp" | ||
| 13 | |||
| 14 | #include <stdio.h> | ||
| 15 | |||
| 16 | void ast_print(FILE *f, AstNode *node, int indent); | ||
| 17 | |||
| 18 | void ast_render(FILE *f, AstNode *node, int indent_size); | ||
| 19 | |||
| 20 | #endif | ||
src/stage1/astgen.cpp created+8119| ... | @@ -0,0 +1,8119 @@ | ||
| 1 | /* | ||
| 2 | * Copyright (c) 2021 Andrew Kelley | ||
| 3 | * | ||
| 4 | * This file is part of zig, which is MIT licensed. | ||
| 5 | * See http://opensource.org/licenses/MIT | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include "astgen.hpp" | ||
| 9 | #include "analyze.hpp" | ||
| 10 | #include "util.hpp" | ||
| 11 | #include "os.hpp" | ||
| 12 | #include "parser.hpp" | ||
| 13 | |||
| 14 | struct Stage1AstGen { | ||
| 15 | CodeGen *codegen; | ||
| 16 | Stage1Zir *exec; | ||
| 17 | Stage1ZirBasicBlock *current_basic_block; | ||
| 18 | AstNode *main_block_node; | ||
| 19 | size_t next_debug_id; | ||
| 20 | ZigFn *fn; | ||
| 21 | bool in_c_import_scope; | ||
| 22 | }; | ||
| 23 | |||
| 24 | static IrInstSrc *astgen_node(Stage1AstGen *ag, AstNode *node, Scope *scope); | ||
| 25 | static IrInstSrc *astgen_node_extra(Stage1AstGen *ag, AstNode *node, Scope *scope, LVal lval, | ||
| 26 | ResultLoc *result_loc); | ||
| 27 | |||
| 28 | static IrInstSrc *ir_lval_wrap(Stage1AstGen *ag, Scope *scope, IrInstSrc *value, LVal lval, | ||
| 29 | ResultLoc *result_loc); | ||
| 30 | static IrInstSrc *ir_expr_wrap(Stage1AstGen *ag, Scope *scope, IrInstSrc *inst, | ||
| 31 | ResultLoc *result_loc); | ||
| 32 | static IrInstSrc *astgen_union_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 33 | IrInstSrc *union_type, IrInstSrc *field_name, AstNode *expr_node, | ||
| 34 | LVal lval, ResultLoc *parent_result_loc); | ||
| 35 | static ResultLocCast *ir_build_cast_result_loc(Stage1AstGen *ag, IrInstSrc *dest_type, | ||
| 36 | ResultLoc *parent_result_loc); | ||
| 37 | static ZigVar *ir_create_var(Stage1AstGen *ag, AstNode *node, Scope *scope, Buf *name, | ||
| 38 | bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime); | ||
| 39 | static void build_decl_var_and_init(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 40 | ZigVar *var, IrInstSrc *init, const char *name_hint, IrInstSrc *is_comptime); | ||
| 41 | |||
| 42 | static void ir_assert_impl(bool ok, IrInst *source_instruction, char const *file, unsigned int line) { | ||
| 43 | if (ok) return; | ||
| 44 | src_assert_impl(ok, source_instruction->source_node, file, line); | ||
| 45 | } | ||
| 46 | |||
| 47 | static ErrorMsg *exec_add_error_node(CodeGen *codegen, Stage1Zir *exec, AstNode *source_node, Buf *msg) { | ||
| 48 | ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); | ||
| 49 | invalidate_exec(exec, err_msg); | ||
| 50 | return err_msg; | ||
| 51 | } | ||
| 52 | |||
| 53 | |||
| 54 | #define ir_assert(OK, SOURCE_INSTRUCTION) ir_assert_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__) | ||
| 55 | |||
| 56 | |||
| 57 | static bool instr_is_unreachable(IrInstSrc *instruction) { | ||
| 58 | return instruction->is_noreturn; | ||
| 59 | } | ||
| 60 | |||
| 61 | void destroy_instruction_src(IrInstSrc *inst) { | ||
| 62 | switch (inst->id) { | ||
| 63 | case IrInstSrcIdInvalid: | ||
| 64 | zig_unreachable(); | ||
| 65 | case IrInstSrcIdReturn: | ||
| 66 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcReturn *>(inst)); | ||
| 67 | case IrInstSrcIdConst: | ||
| 68 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcConst *>(inst)); | ||
| 69 | case IrInstSrcIdBinOp: | ||
| 70 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBinOp *>(inst)); | ||
| 71 | case IrInstSrcIdMergeErrSets: | ||
| 72 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcMergeErrSets *>(inst)); | ||
| 73 | case IrInstSrcIdDeclVar: | ||
| 74 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcDeclVar *>(inst)); | ||
| 75 | case IrInstSrcIdCall: | ||
| 76 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCall *>(inst)); | ||
| 77 | case IrInstSrcIdCallExtra: | ||
| 78 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCallExtra *>(inst)); | ||
| 79 | case IrInstSrcIdAsyncCallExtra: | ||
| 80 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAsyncCallExtra *>(inst)); | ||
| 81 | case IrInstSrcIdUnOp: | ||
| 82 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcUnOp *>(inst)); | ||
| 83 | case IrInstSrcIdCondBr: | ||
| 84 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCondBr *>(inst)); | ||
| 85 | case IrInstSrcIdBr: | ||
| 86 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBr *>(inst)); | ||
| 87 | case IrInstSrcIdPhi: | ||
| 88 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPhi *>(inst)); | ||
| 89 | case IrInstSrcIdContainerInitList: | ||
| 90 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcContainerInitList *>(inst)); | ||
| 91 | case IrInstSrcIdContainerInitFields: | ||
| 92 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcContainerInitFields *>(inst)); | ||
| 93 | case IrInstSrcIdUnreachable: | ||
| 94 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcUnreachable *>(inst)); | ||
| 95 | case IrInstSrcIdElemPtr: | ||
| 96 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcElemPtr *>(inst)); | ||
| 97 | case IrInstSrcIdVarPtr: | ||
| 98 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcVarPtr *>(inst)); | ||
| 99 | case IrInstSrcIdLoadPtr: | ||
| 100 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcLoadPtr *>(inst)); | ||
| 101 | case IrInstSrcIdStorePtr: | ||
| 102 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcStorePtr *>(inst)); | ||
| 103 | case IrInstSrcIdTypeOf: | ||
| 104 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTypeOf *>(inst)); | ||
| 105 | case IrInstSrcIdFieldPtr: | ||
| 106 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFieldPtr *>(inst)); | ||
| 107 | case IrInstSrcIdSetCold: | ||
| 108 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSetCold *>(inst)); | ||
| 109 | case IrInstSrcIdSetRuntimeSafety: | ||
| 110 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSetRuntimeSafety *>(inst)); | ||
| 111 | case IrInstSrcIdSetFloatMode: | ||
| 112 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSetFloatMode *>(inst)); | ||
| 113 | case IrInstSrcIdArrayType: | ||
| 114 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcArrayType *>(inst)); | ||
| 115 | case IrInstSrcIdSliceType: | ||
| 116 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSliceType *>(inst)); | ||
| 117 | case IrInstSrcIdAnyFrameType: | ||
| 118 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAnyFrameType *>(inst)); | ||
| 119 | case IrInstSrcIdAsm: | ||
| 120 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAsm *>(inst)); | ||
| 121 | case IrInstSrcIdSizeOf: | ||
| 122 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSizeOf *>(inst)); | ||
| 123 | case IrInstSrcIdTestNonNull: | ||
| 124 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTestNonNull *>(inst)); | ||
| 125 | case IrInstSrcIdOptionalUnwrapPtr: | ||
| 126 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcOptionalUnwrapPtr *>(inst)); | ||
| 127 | case IrInstSrcIdPopCount: | ||
| 128 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPopCount *>(inst)); | ||
| 129 | case IrInstSrcIdClz: | ||
| 130 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcClz *>(inst)); | ||
| 131 | case IrInstSrcIdCtz: | ||
| 132 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCtz *>(inst)); | ||
| 133 | case IrInstSrcIdBswap: | ||
| 134 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBswap *>(inst)); | ||
| 135 | case IrInstSrcIdBitReverse: | ||
| 136 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBitReverse *>(inst)); | ||
| 137 | case IrInstSrcIdSwitchBr: | ||
| 138 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSwitchBr *>(inst)); | ||
| 139 | case IrInstSrcIdSwitchVar: | ||
| 140 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSwitchVar *>(inst)); | ||
| 141 | case IrInstSrcIdSwitchElseVar: | ||
| 142 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSwitchElseVar *>(inst)); | ||
| 143 | case IrInstSrcIdSwitchTarget: | ||
| 144 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSwitchTarget *>(inst)); | ||
| 145 | case IrInstSrcIdImport: | ||
| 146 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcImport *>(inst)); | ||
| 147 | case IrInstSrcIdRef: | ||
| 148 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcRef *>(inst)); | ||
| 149 | case IrInstSrcIdCompileErr: | ||
| 150 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCompileErr *>(inst)); | ||
| 151 | case IrInstSrcIdCompileLog: | ||
| 152 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCompileLog *>(inst)); | ||
| 153 | case IrInstSrcIdErrName: | ||
| 154 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcErrName *>(inst)); | ||
| 155 | case IrInstSrcIdCImport: | ||
| 156 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCImport *>(inst)); | ||
| 157 | case IrInstSrcIdCInclude: | ||
| 158 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCInclude *>(inst)); | ||
| 159 | case IrInstSrcIdCDefine: | ||
| 160 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCDefine *>(inst)); | ||
| 161 | case IrInstSrcIdCUndef: | ||
| 162 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCUndef *>(inst)); | ||
| 163 | case IrInstSrcIdEmbedFile: | ||
| 164 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcEmbedFile *>(inst)); | ||
| 165 | case IrInstSrcIdCmpxchg: | ||
| 166 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCmpxchg *>(inst)); | ||
| 167 | case IrInstSrcIdFence: | ||
| 168 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFence *>(inst)); | ||
| 169 | case IrInstSrcIdReduce: | ||
| 170 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcReduce *>(inst)); | ||
| 171 | case IrInstSrcIdTruncate: | ||
| 172 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTruncate *>(inst)); | ||
| 173 | case IrInstSrcIdIntCast: | ||
| 174 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcIntCast *>(inst)); | ||
| 175 | case IrInstSrcIdFloatCast: | ||
| 176 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFloatCast *>(inst)); | ||
| 177 | case IrInstSrcIdErrSetCast: | ||
| 178 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcErrSetCast *>(inst)); | ||
| 179 | case IrInstSrcIdIntToFloat: | ||
| 180 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcIntToFloat *>(inst)); | ||
| 181 | case IrInstSrcIdFloatToInt: | ||
| 182 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFloatToInt *>(inst)); | ||
| 183 | case IrInstSrcIdBoolToInt: | ||
| 184 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBoolToInt *>(inst)); | ||
| 185 | case IrInstSrcIdVectorType: | ||
| 186 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcVectorType *>(inst)); | ||
| 187 | case IrInstSrcIdShuffleVector: | ||
| 188 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcShuffleVector *>(inst)); | ||
| 189 | case IrInstSrcIdSplat: | ||
| 190 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSplat *>(inst)); | ||
| 191 | case IrInstSrcIdBoolNot: | ||
| 192 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBoolNot *>(inst)); | ||
| 193 | case IrInstSrcIdMemset: | ||
| 194 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcMemset *>(inst)); | ||
| 195 | case IrInstSrcIdMemcpy: | ||
| 196 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcMemcpy *>(inst)); | ||
| 197 | case IrInstSrcIdSlice: | ||
| 198 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSlice *>(inst)); | ||
| 199 | case IrInstSrcIdBreakpoint: | ||
| 200 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBreakpoint *>(inst)); | ||
| 201 | case IrInstSrcIdReturnAddress: | ||
| 202 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcReturnAddress *>(inst)); | ||
| 203 | case IrInstSrcIdFrameAddress: | ||
| 204 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFrameAddress *>(inst)); | ||
| 205 | case IrInstSrcIdFrameHandle: | ||
| 206 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFrameHandle *>(inst)); | ||
| 207 | case IrInstSrcIdFrameType: | ||
| 208 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFrameType *>(inst)); | ||
| 209 | case IrInstSrcIdFrameSize: | ||
| 210 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFrameSize *>(inst)); | ||
| 211 | case IrInstSrcIdAlignOf: | ||
| 212 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAlignOf *>(inst)); | ||
| 213 | case IrInstSrcIdOverflowOp: | ||
| 214 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcOverflowOp *>(inst)); | ||
| 215 | case IrInstSrcIdTestErr: | ||
| 216 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTestErr *>(inst)); | ||
| 217 | case IrInstSrcIdUnwrapErrCode: | ||
| 218 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcUnwrapErrCode *>(inst)); | ||
| 219 | case IrInstSrcIdUnwrapErrPayload: | ||
| 220 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcUnwrapErrPayload *>(inst)); | ||
| 221 | case IrInstSrcIdFnProto: | ||
| 222 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFnProto *>(inst)); | ||
| 223 | case IrInstSrcIdTestComptime: | ||
| 224 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTestComptime *>(inst)); | ||
| 225 | case IrInstSrcIdPtrCast: | ||
| 226 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPtrCast *>(inst)); | ||
| 227 | case IrInstSrcIdBitCast: | ||
| 228 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBitCast *>(inst)); | ||
| 229 | case IrInstSrcIdPtrToInt: | ||
| 230 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPtrToInt *>(inst)); | ||
| 231 | case IrInstSrcIdIntToPtr: | ||
| 232 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcIntToPtr *>(inst)); | ||
| 233 | case IrInstSrcIdIntToEnum: | ||
| 234 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcIntToEnum *>(inst)); | ||
| 235 | case IrInstSrcIdIntToErr: | ||
| 236 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcIntToErr *>(inst)); | ||
| 237 | case IrInstSrcIdErrToInt: | ||
| 238 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcErrToInt *>(inst)); | ||
| 239 | case IrInstSrcIdCheckSwitchProngsUnderNo: | ||
| 240 | case IrInstSrcIdCheckSwitchProngsUnderYes: | ||
| 241 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCheckSwitchProngs *>(inst)); | ||
| 242 | case IrInstSrcIdCheckStatementIsVoid: | ||
| 243 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCheckStatementIsVoid *>(inst)); | ||
| 244 | case IrInstSrcIdTypeName: | ||
| 245 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTypeName *>(inst)); | ||
| 246 | case IrInstSrcIdTagName: | ||
| 247 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTagName *>(inst)); | ||
| 248 | case IrInstSrcIdPtrType: | ||
| 249 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPtrType *>(inst)); | ||
| 250 | case IrInstSrcIdPtrTypeSimple: | ||
| 251 | case IrInstSrcIdPtrTypeSimpleConst: | ||
| 252 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPtrTypeSimple *>(inst)); | ||
| 253 | case IrInstSrcIdDeclRef: | ||
| 254 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcDeclRef *>(inst)); | ||
| 255 | case IrInstSrcIdPanic: | ||
| 256 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPanic *>(inst)); | ||
| 257 | case IrInstSrcIdFieldParentPtr: | ||
| 258 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFieldParentPtr *>(inst)); | ||
| 259 | case IrInstSrcIdByteOffsetOf: | ||
| 260 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcByteOffsetOf *>(inst)); | ||
| 261 | case IrInstSrcIdBitOffsetOf: | ||
| 262 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBitOffsetOf *>(inst)); | ||
| 263 | case IrInstSrcIdTypeInfo: | ||
| 264 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTypeInfo *>(inst)); | ||
| 265 | case IrInstSrcIdType: | ||
| 266 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcType *>(inst)); | ||
| 267 | case IrInstSrcIdHasField: | ||
| 268 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcHasField *>(inst)); | ||
| 269 | case IrInstSrcIdSetEvalBranchQuota: | ||
| 270 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSetEvalBranchQuota *>(inst)); | ||
| 271 | case IrInstSrcIdAlignCast: | ||
| 272 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAlignCast *>(inst)); | ||
| 273 | case IrInstSrcIdImplicitCast: | ||
| 274 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcImplicitCast *>(inst)); | ||
| 275 | case IrInstSrcIdResolveResult: | ||
| 276 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcResolveResult *>(inst)); | ||
| 277 | case IrInstSrcIdResetResult: | ||
| 278 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcResetResult *>(inst)); | ||
| 279 | case IrInstSrcIdSetAlignStack: | ||
| 280 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSetAlignStack *>(inst)); | ||
| 281 | case IrInstSrcIdArgTypeAllowVarFalse: | ||
| 282 | case IrInstSrcIdArgTypeAllowVarTrue: | ||
| 283 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcArgType *>(inst)); | ||
| 284 | case IrInstSrcIdExport: | ||
| 285 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcExport *>(inst)); | ||
| 286 | case IrInstSrcIdExtern: | ||
| 287 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcExtern *>(inst)); | ||
| 288 | case IrInstSrcIdErrorReturnTrace: | ||
| 289 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcErrorReturnTrace *>(inst)); | ||
| 290 | case IrInstSrcIdErrorUnion: | ||
| 291 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcErrorUnion *>(inst)); | ||
| 292 | case IrInstSrcIdAtomicRmw: | ||
| 293 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAtomicRmw *>(inst)); | ||
| 294 | case IrInstSrcIdSaveErrRetAddr: | ||
| 295 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSaveErrRetAddr *>(inst)); | ||
| 296 | case IrInstSrcIdAddImplicitReturnType: | ||
| 297 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAddImplicitReturnType *>(inst)); | ||
| 298 | case IrInstSrcIdFloatOp: | ||
| 299 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFloatOp *>(inst)); | ||
| 300 | case IrInstSrcIdMulAdd: | ||
| 301 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcMulAdd *>(inst)); | ||
| 302 | case IrInstSrcIdAtomicLoad: | ||
| 303 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAtomicLoad *>(inst)); | ||
| 304 | case IrInstSrcIdAtomicStore: | ||
| 305 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAtomicStore *>(inst)); | ||
| 306 | case IrInstSrcIdEnumToInt: | ||
| 307 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcEnumToInt *>(inst)); | ||
| 308 | case IrInstSrcIdCheckRuntimeScope: | ||
| 309 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCheckRuntimeScope *>(inst)); | ||
| 310 | case IrInstSrcIdHasDecl: | ||
| 311 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcHasDecl *>(inst)); | ||
| 312 | case IrInstSrcIdUndeclaredIdent: | ||
| 313 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcUndeclaredIdent *>(inst)); | ||
| 314 | case IrInstSrcIdAlloca: | ||
| 315 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAlloca *>(inst)); | ||
| 316 | case IrInstSrcIdEndExpr: | ||
| 317 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcEndExpr *>(inst)); | ||
| 318 | case IrInstSrcIdUnionInitNamedField: | ||
| 319 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcUnionInitNamedField *>(inst)); | ||
| 320 | case IrInstSrcIdSuspendBegin: | ||
| 321 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSuspendBegin *>(inst)); | ||
| 322 | case IrInstSrcIdSuspendFinish: | ||
| 323 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSuspendFinish *>(inst)); | ||
| 324 | case IrInstSrcIdResume: | ||
| 325 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcResume *>(inst)); | ||
| 326 | case IrInstSrcIdAwait: | ||
| 327 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAwait *>(inst)); | ||
| 328 | case IrInstSrcIdSpillBegin: | ||
| 329 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSpillBegin *>(inst)); | ||
| 330 | case IrInstSrcIdSpillEnd: | ||
| 331 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSpillEnd *>(inst)); | ||
| 332 | case IrInstSrcIdCallArgs: | ||
| 333 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCallArgs *>(inst)); | ||
| 334 | case IrInstSrcIdWasmMemorySize: | ||
| 335 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemorySize *>(inst)); | ||
| 336 | case IrInstSrcIdWasmMemoryGrow: | ||
| 337 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemoryGrow *>(inst)); | ||
| 338 | case IrInstSrcIdSrc: | ||
| 339 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSrc *>(inst)); | ||
| 340 | } | ||
| 341 | zig_unreachable(); | ||
| 342 | } | ||
| 343 | |||
| 344 | |||
| 345 | bool ir_should_inline(Stage1Zir *exec, Scope *scope) { | ||
| 346 | if (exec->is_inline) | ||
| 347 | return true; | ||
| 348 | |||
| 349 | while (scope != nullptr) { | ||
| 350 | if (scope->id == ScopeIdCompTime) | ||
| 351 | return true; | ||
| 352 | if (scope->id == ScopeIdTypeOf) | ||
| 353 | return false; | ||
| 354 | if (scope->id == ScopeIdFnDef) | ||
| 355 | break; | ||
| 356 | scope = scope->parent; | ||
| 357 | } | ||
| 358 | return false; | ||
| 359 | } | ||
| 360 | |||
| 361 | static void ir_instruction_append(Stage1ZirBasicBlock *basic_block, IrInstSrc *instruction) { | ||
| 362 | assert(basic_block); | ||
| 363 | assert(instruction); | ||
| 364 | basic_block->instruction_list.append(instruction); | ||
| 365 | } | ||
| 366 | |||
| 367 | static size_t irb_next_debug_id(Stage1AstGen *ag) { | ||
| 368 | size_t result = ag->next_debug_id; | ||
| 369 | ag->next_debug_id += 1; | ||
| 370 | return result; | ||
| 371 | } | ||
| 372 | |||
| 373 | static void ir_ref_bb(Stage1ZirBasicBlock *bb) { | ||
| 374 | bb->ref_count += 1; | ||
| 375 | } | ||
| 376 | |||
| 377 | static void ir_ref_instruction(IrInstSrc *instruction, Stage1ZirBasicBlock *cur_bb) { | ||
| 378 | assert(instruction->id != IrInstSrcIdInvalid); | ||
| 379 | instruction->base.ref_count += 1; | ||
| 380 | if (instruction->owner_bb != cur_bb && !instr_is_unreachable(instruction) | ||
| 381 | && instruction->id != IrInstSrcIdConst) | ||
| 382 | { | ||
| 383 | ir_ref_bb(instruction->owner_bb); | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 | static Stage1ZirBasicBlock *ir_create_basic_block(Stage1AstGen *ag, Scope *scope, const char *name_hint) { | ||
| 388 | Stage1ZirBasicBlock *result = heap::c_allocator.create<Stage1ZirBasicBlock>(); | ||
| 389 | result->scope = scope; | ||
| 390 | result->name_hint = name_hint; | ||
| 391 | result->debug_id = irb_next_debug_id(ag); | ||
| 392 | result->index = UINT32_MAX; // set later | ||
| 393 | return result; | ||
| 394 | } | ||
| 395 | |||
| 396 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcDeclVar *) { | ||
| 397 | return IrInstSrcIdDeclVar; | ||
| 398 | } | ||
| 399 | |||
| 400 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBr *) { | ||
| 401 | return IrInstSrcIdBr; | ||
| 402 | } | ||
| 403 | |||
| 404 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCondBr *) { | ||
| 405 | return IrInstSrcIdCondBr; | ||
| 406 | } | ||
| 407 | |||
| 408 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchBr *) { | ||
| 409 | return IrInstSrcIdSwitchBr; | ||
| 410 | } | ||
| 411 | |||
| 412 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchVar *) { | ||
| 413 | return IrInstSrcIdSwitchVar; | ||
| 414 | } | ||
| 415 | |||
| 416 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchElseVar *) { | ||
| 417 | return IrInstSrcIdSwitchElseVar; | ||
| 418 | } | ||
| 419 | |||
| 420 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchTarget *) { | ||
| 421 | return IrInstSrcIdSwitchTarget; | ||
| 422 | } | ||
| 423 | |||
| 424 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcPhi *) { | ||
| 425 | return IrInstSrcIdPhi; | ||
| 426 | } | ||
| 427 | |||
| 428 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnOp *) { | ||
| 429 | return IrInstSrcIdUnOp; | ||
| 430 | } | ||
| 431 | |||
| 432 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBinOp *) { | ||
| 433 | return IrInstSrcIdBinOp; | ||
| 434 | } | ||
| 435 | |||
| 436 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcMergeErrSets *) { | ||
| 437 | return IrInstSrcIdMergeErrSets; | ||
| 438 | } | ||
| 439 | |||
| 440 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcLoadPtr *) { | ||
| 441 | return IrInstSrcIdLoadPtr; | ||
| 442 | } | ||
| 443 | |||
| 444 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcStorePtr *) { | ||
| 445 | return IrInstSrcIdStorePtr; | ||
| 446 | } | ||
| 447 | |||
| 448 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFieldPtr *) { | ||
| 449 | return IrInstSrcIdFieldPtr; | ||
| 450 | } | ||
| 451 | |||
| 452 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcElemPtr *) { | ||
| 453 | return IrInstSrcIdElemPtr; | ||
| 454 | } | ||
| 455 | |||
| 456 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcVarPtr *) { | ||
| 457 | return IrInstSrcIdVarPtr; | ||
| 458 | } | ||
| 459 | |||
| 460 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCall *) { | ||
| 461 | return IrInstSrcIdCall; | ||
| 462 | } | ||
| 463 | |||
| 464 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCallArgs *) { | ||
| 465 | return IrInstSrcIdCallArgs; | ||
| 466 | } | ||
| 467 | |||
| 468 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCallExtra *) { | ||
| 469 | return IrInstSrcIdCallExtra; | ||
| 470 | } | ||
| 471 | |||
| 472 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAsyncCallExtra *) { | ||
| 473 | return IrInstSrcIdAsyncCallExtra; | ||
| 474 | } | ||
| 475 | |||
| 476 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcConst *) { | ||
| 477 | return IrInstSrcIdConst; | ||
| 478 | } | ||
| 479 | |||
| 480 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcReturn *) { | ||
| 481 | return IrInstSrcIdReturn; | ||
| 482 | } | ||
| 483 | |||
| 484 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcContainerInitList *) { | ||
| 485 | return IrInstSrcIdContainerInitList; | ||
| 486 | } | ||
| 487 | |||
| 488 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcContainerInitFields *) { | ||
| 489 | return IrInstSrcIdContainerInitFields; | ||
| 490 | } | ||
| 491 | |||
| 492 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnreachable *) { | ||
| 493 | return IrInstSrcIdUnreachable; | ||
| 494 | } | ||
| 495 | |||
| 496 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeOf *) { | ||
| 497 | return IrInstSrcIdTypeOf; | ||
| 498 | } | ||
| 499 | |||
| 500 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetCold *) { | ||
| 501 | return IrInstSrcIdSetCold; | ||
| 502 | } | ||
| 503 | |||
| 504 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetRuntimeSafety *) { | ||
| 505 | return IrInstSrcIdSetRuntimeSafety; | ||
| 506 | } | ||
| 507 | |||
| 508 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetFloatMode *) { | ||
| 509 | return IrInstSrcIdSetFloatMode; | ||
| 510 | } | ||
| 511 | |||
| 512 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcArrayType *) { | ||
| 513 | return IrInstSrcIdArrayType; | ||
| 514 | } | ||
| 515 | |||
| 516 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAnyFrameType *) { | ||
| 517 | return IrInstSrcIdAnyFrameType; | ||
| 518 | } | ||
| 519 | |||
| 520 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSliceType *) { | ||
| 521 | return IrInstSrcIdSliceType; | ||
| 522 | } | ||
| 523 | |||
| 524 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAsm *) { | ||
| 525 | return IrInstSrcIdAsm; | ||
| 526 | } | ||
| 527 | |||
| 528 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSizeOf *) { | ||
| 529 | return IrInstSrcIdSizeOf; | ||
| 530 | } | ||
| 531 | |||
| 532 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestNonNull *) { | ||
| 533 | return IrInstSrcIdTestNonNull; | ||
| 534 | } | ||
| 535 | |||
| 536 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcOptionalUnwrapPtr *) { | ||
| 537 | return IrInstSrcIdOptionalUnwrapPtr; | ||
| 538 | } | ||
| 539 | |||
| 540 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcClz *) { | ||
| 541 | return IrInstSrcIdClz; | ||
| 542 | } | ||
| 543 | |||
| 544 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCtz *) { | ||
| 545 | return IrInstSrcIdCtz; | ||
| 546 | } | ||
| 547 | |||
| 548 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcPopCount *) { | ||
| 549 | return IrInstSrcIdPopCount; | ||
| 550 | } | ||
| 551 | |||
| 552 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBswap *) { | ||
| 553 | return IrInstSrcIdBswap; | ||
| 554 | } | ||
| 555 | |||
| 556 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitReverse *) { | ||
| 557 | return IrInstSrcIdBitReverse; | ||
| 558 | } | ||
| 559 | |||
| 560 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcImport *) { | ||
| 561 | return IrInstSrcIdImport; | ||
| 562 | } | ||
| 563 | |||
| 564 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCImport *) { | ||
| 565 | return IrInstSrcIdCImport; | ||
| 566 | } | ||
| 567 | |||
| 568 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCInclude *) { | ||
| 569 | return IrInstSrcIdCInclude; | ||
| 570 | } | ||
| 571 | |||
| 572 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCDefine *) { | ||
| 573 | return IrInstSrcIdCDefine; | ||
| 574 | } | ||
| 575 | |||
| 576 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCUndef *) { | ||
| 577 | return IrInstSrcIdCUndef; | ||
| 578 | } | ||
| 579 | |||
| 580 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcRef *) { | ||
| 581 | return IrInstSrcIdRef; | ||
| 582 | } | ||
| 583 | |||
| 584 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCompileErr *) { | ||
| 585 | return IrInstSrcIdCompileErr; | ||
| 586 | } | ||
| 587 | |||
| 588 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCompileLog *) { | ||
| 589 | return IrInstSrcIdCompileLog; | ||
| 590 | } | ||
| 591 | |||
| 592 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrName *) { | ||
| 593 | return IrInstSrcIdErrName; | ||
| 594 | } | ||
| 595 | |||
| 596 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcEmbedFile *) { | ||
| 597 | return IrInstSrcIdEmbedFile; | ||
| 598 | } | ||
| 599 | |||
| 600 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCmpxchg *) { | ||
| 601 | return IrInstSrcIdCmpxchg; | ||
| 602 | } | ||
| 603 | |||
| 604 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFence *) { | ||
| 605 | return IrInstSrcIdFence; | ||
| 606 | } | ||
| 607 | |||
| 608 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcReduce *) { | ||
| 609 | return IrInstSrcIdReduce; | ||
| 610 | } | ||
| 611 | |||
| 612 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTruncate *) { | ||
| 613 | return IrInstSrcIdTruncate; | ||
| 614 | } | ||
| 615 | |||
| 616 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntCast *) { | ||
| 617 | return IrInstSrcIdIntCast; | ||
| 618 | } | ||
| 619 | |||
| 620 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatCast *) { | ||
| 621 | return IrInstSrcIdFloatCast; | ||
| 622 | } | ||
| 623 | |||
| 624 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToFloat *) { | ||
| 625 | return IrInstSrcIdIntToFloat; | ||
| 626 | } | ||
| 627 | |||
| 628 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatToInt *) { | ||
| 629 | return IrInstSrcIdFloatToInt; | ||
| 630 | } | ||
| 631 | |||
| 632 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolToInt *) { | ||
| 633 | return IrInstSrcIdBoolToInt; | ||
| 634 | } | ||
| 635 | |||
| 636 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcVectorType *) { | ||
| 637 | return IrInstSrcIdVectorType; | ||
| 638 | } | ||
| 639 | |||
| 640 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcShuffleVector *) { | ||
| 641 | return IrInstSrcIdShuffleVector; | ||
| 642 | } | ||
| 643 | |||
| 644 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSplat *) { | ||
| 645 | return IrInstSrcIdSplat; | ||
| 646 | } | ||
| 647 | |||
| 648 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolNot *) { | ||
| 649 | return IrInstSrcIdBoolNot; | ||
| 650 | } | ||
| 651 | |||
| 652 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemset *) { | ||
| 653 | return IrInstSrcIdMemset; | ||
| 654 | } | ||
| 655 | |||
| 656 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemcpy *) { | ||
| 657 | return IrInstSrcIdMemcpy; | ||
| 658 | } | ||
| 659 | |||
| 660 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSlice *) { | ||
| 661 | return IrInstSrcIdSlice; | ||
| 662 | } | ||
| 663 | |||
| 664 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBreakpoint *) { | ||
| 665 | return IrInstSrcIdBreakpoint; | ||
| 666 | } | ||
| 667 | |||
| 668 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcReturnAddress *) { | ||
| 669 | return IrInstSrcIdReturnAddress; | ||
| 670 | } | ||
| 671 | |||
| 672 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameAddress *) { | ||
| 673 | return IrInstSrcIdFrameAddress; | ||
| 674 | } | ||
| 675 | |||
| 676 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameHandle *) { | ||
| 677 | return IrInstSrcIdFrameHandle; | ||
| 678 | } | ||
| 679 | |||
| 680 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameType *) { | ||
| 681 | return IrInstSrcIdFrameType; | ||
| 682 | } | ||
| 683 | |||
| 684 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameSize *) { | ||
| 685 | return IrInstSrcIdFrameSize; | ||
| 686 | } | ||
| 687 | |||
| 688 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlignOf *) { | ||
| 689 | return IrInstSrcIdAlignOf; | ||
| 690 | } | ||
| 691 | |||
| 692 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcOverflowOp *) { | ||
| 693 | return IrInstSrcIdOverflowOp; | ||
| 694 | } | ||
| 695 | |||
| 696 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestErr *) { | ||
| 697 | return IrInstSrcIdTestErr; | ||
| 698 | } | ||
| 699 | |||
| 700 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcMulAdd *) { | ||
| 701 | return IrInstSrcIdMulAdd; | ||
| 702 | } | ||
| 703 | |||
| 704 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatOp *) { | ||
| 705 | return IrInstSrcIdFloatOp; | ||
| 706 | } | ||
| 707 | |||
| 708 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnwrapErrCode *) { | ||
| 709 | return IrInstSrcIdUnwrapErrCode; | ||
| 710 | } | ||
| 711 | |||
| 712 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnwrapErrPayload *) { | ||
| 713 | return IrInstSrcIdUnwrapErrPayload; | ||
| 714 | } | ||
| 715 | |||
| 716 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFnProto *) { | ||
| 717 | return IrInstSrcIdFnProto; | ||
| 718 | } | ||
| 719 | |||
| 720 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestComptime *) { | ||
| 721 | return IrInstSrcIdTestComptime; | ||
| 722 | } | ||
| 723 | |||
| 724 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrCast *) { | ||
| 725 | return IrInstSrcIdPtrCast; | ||
| 726 | } | ||
| 727 | |||
| 728 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitCast *) { | ||
| 729 | return IrInstSrcIdBitCast; | ||
| 730 | } | ||
| 731 | |||
| 732 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToPtr *) { | ||
| 733 | return IrInstSrcIdIntToPtr; | ||
| 734 | } | ||
| 735 | |||
| 736 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrToInt *) { | ||
| 737 | return IrInstSrcIdPtrToInt; | ||
| 738 | } | ||
| 739 | |||
| 740 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToEnum *) { | ||
| 741 | return IrInstSrcIdIntToEnum; | ||
| 742 | } | ||
| 743 | |||
| 744 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcEnumToInt *) { | ||
| 745 | return IrInstSrcIdEnumToInt; | ||
| 746 | } | ||
| 747 | |||
| 748 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToErr *) { | ||
| 749 | return IrInstSrcIdIntToErr; | ||
| 750 | } | ||
| 751 | |||
| 752 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrToInt *) { | ||
| 753 | return IrInstSrcIdErrToInt; | ||
| 754 | } | ||
| 755 | |||
| 756 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckStatementIsVoid *) { | ||
| 757 | return IrInstSrcIdCheckStatementIsVoid; | ||
| 758 | } | ||
| 759 | |||
| 760 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeName *) { | ||
| 761 | return IrInstSrcIdTypeName; | ||
| 762 | } | ||
| 763 | |||
| 764 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcDeclRef *) { | ||
| 765 | return IrInstSrcIdDeclRef; | ||
| 766 | } | ||
| 767 | |||
| 768 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcPanic *) { | ||
| 769 | return IrInstSrcIdPanic; | ||
| 770 | } | ||
| 771 | |||
| 772 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTagName *) { | ||
| 773 | return IrInstSrcIdTagName; | ||
| 774 | } | ||
| 775 | |||
| 776 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFieldParentPtr *) { | ||
| 777 | return IrInstSrcIdFieldParentPtr; | ||
| 778 | } | ||
| 779 | |||
| 780 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcByteOffsetOf *) { | ||
| 781 | return IrInstSrcIdByteOffsetOf; | ||
| 782 | } | ||
| 783 | |||
| 784 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitOffsetOf *) { | ||
| 785 | return IrInstSrcIdBitOffsetOf; | ||
| 786 | } | ||
| 787 | |||
| 788 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeInfo *) { | ||
| 789 | return IrInstSrcIdTypeInfo; | ||
| 790 | } | ||
| 791 | |||
| 792 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcType *) { | ||
| 793 | return IrInstSrcIdType; | ||
| 794 | } | ||
| 795 | |||
| 796 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcHasField *) { | ||
| 797 | return IrInstSrcIdHasField; | ||
| 798 | } | ||
| 799 | |||
| 800 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetEvalBranchQuota *) { | ||
| 801 | return IrInstSrcIdSetEvalBranchQuota; | ||
| 802 | } | ||
| 803 | |||
| 804 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrType *) { | ||
| 805 | return IrInstSrcIdPtrType; | ||
| 806 | } | ||
| 807 | |||
| 808 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlignCast *) { | ||
| 809 | return IrInstSrcIdAlignCast; | ||
| 810 | } | ||
| 811 | |||
| 812 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcImplicitCast *) { | ||
| 813 | return IrInstSrcIdImplicitCast; | ||
| 814 | } | ||
| 815 | |||
| 816 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcResolveResult *) { | ||
| 817 | return IrInstSrcIdResolveResult; | ||
| 818 | } | ||
| 819 | |||
| 820 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcResetResult *) { | ||
| 821 | return IrInstSrcIdResetResult; | ||
| 822 | } | ||
| 823 | |||
| 824 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetAlignStack *) { | ||
| 825 | return IrInstSrcIdSetAlignStack; | ||
| 826 | } | ||
| 827 | |||
| 828 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcExport *) { | ||
| 829 | return IrInstSrcIdExport; | ||
| 830 | } | ||
| 831 | |||
| 832 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcExtern *) { | ||
| 833 | return IrInstSrcIdExtern; | ||
| 834 | } | ||
| 835 | |||
| 836 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrorReturnTrace *) { | ||
| 837 | return IrInstSrcIdErrorReturnTrace; | ||
| 838 | } | ||
| 839 | |||
| 840 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrorUnion *) { | ||
| 841 | return IrInstSrcIdErrorUnion; | ||
| 842 | } | ||
| 843 | |||
| 844 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicRmw *) { | ||
| 845 | return IrInstSrcIdAtomicRmw; | ||
| 846 | } | ||
| 847 | |||
| 848 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicLoad *) { | ||
| 849 | return IrInstSrcIdAtomicLoad; | ||
| 850 | } | ||
| 851 | |||
| 852 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicStore *) { | ||
| 853 | return IrInstSrcIdAtomicStore; | ||
| 854 | } | ||
| 855 | |||
| 856 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSaveErrRetAddr *) { | ||
| 857 | return IrInstSrcIdSaveErrRetAddr; | ||
| 858 | } | ||
| 859 | |||
| 860 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAddImplicitReturnType *) { | ||
| 861 | return IrInstSrcIdAddImplicitReturnType; | ||
| 862 | } | ||
| 863 | |||
| 864 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrSetCast *) { | ||
| 865 | return IrInstSrcIdErrSetCast; | ||
| 866 | } | ||
| 867 | |||
| 868 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckRuntimeScope *) { | ||
| 869 | return IrInstSrcIdCheckRuntimeScope; | ||
| 870 | } | ||
| 871 | |||
| 872 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcHasDecl *) { | ||
| 873 | return IrInstSrcIdHasDecl; | ||
| 874 | } | ||
| 875 | |||
| 876 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcUndeclaredIdent *) { | ||
| 877 | return IrInstSrcIdUndeclaredIdent; | ||
| 878 | } | ||
| 879 | |||
| 880 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlloca *) { | ||
| 881 | return IrInstSrcIdAlloca; | ||
| 882 | } | ||
| 883 | |||
| 884 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcEndExpr *) { | ||
| 885 | return IrInstSrcIdEndExpr; | ||
| 886 | } | ||
| 887 | |||
| 888 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnionInitNamedField *) { | ||
| 889 | return IrInstSrcIdUnionInitNamedField; | ||
| 890 | } | ||
| 891 | |||
| 892 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSuspendBegin *) { | ||
| 893 | return IrInstSrcIdSuspendBegin; | ||
| 894 | } | ||
| 895 | |||
| 896 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSuspendFinish *) { | ||
| 897 | return IrInstSrcIdSuspendFinish; | ||
| 898 | } | ||
| 899 | |||
| 900 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAwait *) { | ||
| 901 | return IrInstSrcIdAwait; | ||
| 902 | } | ||
| 903 | |||
| 904 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcResume *) { | ||
| 905 | return IrInstSrcIdResume; | ||
| 906 | } | ||
| 907 | |||
| 908 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSpillBegin *) { | ||
| 909 | return IrInstSrcIdSpillBegin; | ||
| 910 | } | ||
| 911 | |||
| 912 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSpillEnd *) { | ||
| 913 | return IrInstSrcIdSpillEnd; | ||
| 914 | } | ||
| 915 | |||
| 916 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemorySize *) { | ||
| 917 | return IrInstSrcIdWasmMemorySize; | ||
| 918 | } | ||
| 919 | |||
| 920 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemoryGrow *) { | ||
| 921 | return IrInstSrcIdWasmMemoryGrow; | ||
| 922 | } | ||
| 923 | |||
| 924 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSrc *) { | ||
| 925 | return IrInstSrcIdSrc; | ||
| 926 | } | ||
| 927 | |||
| 928 | template<typename T> | ||
| 929 | static T *ir_create_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | ||
| 930 | T *special_instruction = heap::c_allocator.create<T>(); | ||
| 931 | special_instruction->base.id = ir_inst_id(special_instruction); | ||
| 932 | special_instruction->base.base.scope = scope; | ||
| 933 | special_instruction->base.base.source_node = source_node; | ||
| 934 | special_instruction->base.base.debug_id = irb_next_debug_id(ag); | ||
| 935 | special_instruction->base.owner_bb = ag->current_basic_block; | ||
| 936 | return special_instruction; | ||
| 937 | } | ||
| 938 | |||
| 939 | template<typename T> | ||
| 940 | static T *ir_build_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | ||
| 941 | T *special_instruction = ir_create_instruction<T>(ag, scope, source_node); | ||
| 942 | ir_instruction_append(ag->current_basic_block, &special_instruction->base); | ||
| 943 | return special_instruction; | ||
| 944 | } | ||
| 945 | |||
| 946 | static IrInstSrc *ir_build_cond_br(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *condition, | ||
| 947 | Stage1ZirBasicBlock *then_block, Stage1ZirBasicBlock *else_block, IrInstSrc *is_comptime) | ||
| 948 | { | ||
| 949 | IrInstSrcCondBr *inst = ir_build_instruction<IrInstSrcCondBr>(ag, scope, source_node); | ||
| 950 | inst->base.is_noreturn = true; | ||
| 951 | inst->condition = condition; | ||
| 952 | inst->then_block = then_block; | ||
| 953 | inst->else_block = else_block; | ||
| 954 | inst->is_comptime = is_comptime; | ||
| 955 | |||
| 956 | ir_ref_instruction(condition, ag->current_basic_block); | ||
| 957 | ir_ref_bb(then_block); | ||
| 958 | ir_ref_bb(else_block); | ||
| 959 | if (is_comptime != nullptr) ir_ref_instruction(is_comptime, ag->current_basic_block); | ||
| 960 | |||
| 961 | return &inst->base; | ||
| 962 | } | ||
| 963 | |||
| 964 | static IrInstSrc *ir_build_return_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *operand) { | ||
| 965 | IrInstSrcReturn *inst = ir_build_instruction<IrInstSrcReturn>(ag, scope, source_node); | ||
| 966 | inst->base.is_noreturn = true; | ||
| 967 | inst->operand = operand; | ||
| 968 | |||
| 969 | if (operand != nullptr) ir_ref_instruction(operand, ag->current_basic_block); | ||
| 970 | |||
| 971 | return &inst->base; | ||
| 972 | } | ||
| 973 | |||
| 974 | static IrInstSrc *ir_build_const_void(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | ||
| 975 | IrInstSrcConst *const_instruction = ir_create_instruction<IrInstSrcConst>(ag, scope, source_node); | ||
| 976 | ir_instruction_append(ag->current_basic_block, &const_instruction->base); | ||
| 977 | const_instruction->value = ag->codegen->intern.for_void(); | ||
| 978 | return &const_instruction->base; | ||
| 979 | } | ||
| 980 | |||
| 981 | static IrInstSrc *ir_build_const_undefined(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | ||
| 982 | IrInstSrcConst *const_instruction = ir_create_instruction<IrInstSrcConst>(ag, scope, source_node); | ||
| 983 | ir_instruction_append(ag->current_basic_block, &const_instruction->base); | ||
| 984 | const_instruction->value = ag->codegen->intern.for_undefined(); | ||
| 985 | const_instruction->value->special = ConstValSpecialUndef; | ||
| 986 | return &const_instruction->base; | ||
| 987 | } | ||
| 988 | |||
| 989 | static IrInstSrc *ir_build_const_uint(Stage1AstGen *ag, Scope *scope, AstNode *source_node, uint64_t value) { | ||
| 990 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(ag, scope, source_node); | ||
| 991 | const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>(); | ||
| 992 | const_instruction->value->type = ag->codegen->builtin_types.entry_num_lit_int; | ||
| 993 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 994 | bigint_init_unsigned(&const_instruction->value->data.x_bigint, value); | ||
| 995 | return &const_instruction->base; | ||
| 996 | } | ||
| 997 | |||
| 998 | static IrInstSrc *ir_build_const_bigint(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 999 | BigInt bigint) | ||
| 1000 | { | ||
| 1001 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(ag, scope, source_node); | ||
| 1002 | const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>(); | ||
| 1003 | const_instruction->value->type = ag->codegen->builtin_types.entry_num_lit_int; | ||
| 1004 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 1005 | const_instruction->value->data.x_bigint = bigint; | ||
| 1006 | return &const_instruction->base; | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | static IrInstSrc *ir_build_const_bigfloat(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1010 | BigFloat bigfloat) | ||
| 1011 | { | ||
| 1012 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(ag, scope, source_node); | ||
| 1013 | const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>(); | ||
| 1014 | const_instruction->value->type = ag->codegen->builtin_types.entry_num_lit_float; | ||
| 1015 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 1016 | const_instruction->value->data.x_bigfloat = bigfloat; | ||
| 1017 | return &const_instruction->base; | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | static IrInstSrc *ir_build_const_null(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | ||
| 1021 | IrInstSrcConst *const_instruction = ir_create_instruction<IrInstSrcConst>(ag, scope, source_node); | ||
| 1022 | ir_instruction_append(ag->current_basic_block, &const_instruction->base); | ||
| 1023 | const_instruction->value = ag->codegen->intern.for_null(); | ||
| 1024 | return &const_instruction->base; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | static IrInstSrc *ir_build_const_usize(Stage1AstGen *ag, Scope *scope, AstNode *source_node, uint64_t value) { | ||
| 1028 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(ag, scope, source_node); | ||
| 1029 | const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>(); | ||
| 1030 | const_instruction->value->type = ag->codegen->builtin_types.entry_usize; | ||
| 1031 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 1032 | bigint_init_unsigned(&const_instruction->value->data.x_bigint, value); | ||
| 1033 | return &const_instruction->base; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | static IrInstSrc *ir_create_const_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1037 | ZigType *type_entry) | ||
| 1038 | { | ||
| 1039 | IrInstSrcConst *const_instruction = ir_create_instruction<IrInstSrcConst>(ag, scope, source_node); | ||
| 1040 | const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>(); | ||
| 1041 | const_instruction->value->type = ag->codegen->builtin_types.entry_type; | ||
| 1042 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 1043 | const_instruction->value->data.x_type = type_entry; | ||
| 1044 | return &const_instruction->base; | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | static IrInstSrc *ir_build_const_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1048 | ZigType *type_entry) | ||
| 1049 | { | ||
| 1050 | IrInstSrc *instruction = ir_create_const_type(ag, scope, source_node, type_entry); | ||
| 1051 | ir_instruction_append(ag->current_basic_block, instruction); | ||
| 1052 | return instruction; | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | static IrInstSrc *ir_build_const_import(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigType *import) { | ||
| 1056 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(ag, scope, source_node); | ||
| 1057 | const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>(); | ||
| 1058 | const_instruction->value->type = ag->codegen->builtin_types.entry_type; | ||
| 1059 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 1060 | const_instruction->value->data.x_type = import; | ||
| 1061 | return &const_instruction->base; | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | static IrInstSrc *ir_build_const_bool(Stage1AstGen *ag, Scope *scope, AstNode *source_node, bool value) { | ||
| 1065 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(ag, scope, source_node); | ||
| 1066 | const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>(); | ||
| 1067 | const_instruction->value->type = ag->codegen->builtin_types.entry_bool; | ||
| 1068 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 1069 | const_instruction->value->data.x_bool = value; | ||
| 1070 | return &const_instruction->base; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | static IrInstSrc *ir_build_const_enum_literal(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Buf *name) { | ||
| 1074 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(ag, scope, source_node); | ||
| 1075 | const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>(); | ||
| 1076 | const_instruction->value->type = ag->codegen->builtin_types.entry_enum_literal; | ||
| 1077 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 1078 | const_instruction->value->data.x_enum_literal = name; | ||
| 1079 | return &const_instruction->base; | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | // Consumes `str`. | ||
| 1083 | static IrInstSrc *ir_create_const_str_lit(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Buf *str) { | ||
| 1084 | IrInstSrcConst *const_instruction = ir_create_instruction<IrInstSrcConst>(ag, scope, source_node); | ||
| 1085 | const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>(); | ||
| 1086 | init_const_str_lit(ag->codegen, const_instruction->value, str, true); | ||
| 1087 | |||
| 1088 | return &const_instruction->base; | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | // Consumes `str`. | ||
| 1092 | static IrInstSrc *ir_build_const_str_lit(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Buf *str) { | ||
| 1093 | IrInstSrc *instruction = ir_create_const_str_lit(ag, scope, source_node, str); | ||
| 1094 | ir_instruction_append(ag->current_basic_block, instruction); | ||
| 1095 | return instruction; | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | static IrInstSrc *ir_build_bin_op(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrBinOp op_id, | ||
| 1099 | IrInstSrc *op1, IrInstSrc *op2, bool safety_check_on) | ||
| 1100 | { | ||
| 1101 | IrInstSrcBinOp *inst = ir_build_instruction<IrInstSrcBinOp>(ag, scope, source_node); | ||
| 1102 | inst->op_id = op_id; | ||
| 1103 | inst->op1 = op1; | ||
| 1104 | inst->op2 = op2; | ||
| 1105 | inst->safety_check_on = safety_check_on; | ||
| 1106 | |||
| 1107 | ir_ref_instruction(op1, ag->current_basic_block); | ||
| 1108 | ir_ref_instruction(op2, ag->current_basic_block); | ||
| 1109 | |||
| 1110 | return &inst->base; | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | static IrInstSrc *ir_build_merge_err_sets(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1114 | IrInstSrc *op1, IrInstSrc *op2, Buf *type_name) | ||
| 1115 | { | ||
| 1116 | IrInstSrcMergeErrSets *inst = ir_build_instruction<IrInstSrcMergeErrSets>(ag, scope, source_node); | ||
| 1117 | inst->op1 = op1; | ||
| 1118 | inst->op2 = op2; | ||
| 1119 | inst->type_name = type_name; | ||
| 1120 | |||
| 1121 | ir_ref_instruction(op1, ag->current_basic_block); | ||
| 1122 | ir_ref_instruction(op2, ag->current_basic_block); | ||
| 1123 | |||
| 1124 | return &inst->base; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | static IrInstSrc *ir_build_var_ptr_x(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigVar *var, | ||
| 1128 | ScopeFnDef *crossed_fndef_scope) | ||
| 1129 | { | ||
| 1130 | IrInstSrcVarPtr *instruction = ir_build_instruction<IrInstSrcVarPtr>(ag, scope, source_node); | ||
| 1131 | instruction->var = var; | ||
| 1132 | instruction->crossed_fndef_scope = crossed_fndef_scope; | ||
| 1133 | |||
| 1134 | var->ref_count += 1; | ||
| 1135 | |||
| 1136 | return &instruction->base; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | static IrInstSrc *ir_build_var_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigVar *var) { | ||
| 1140 | return ir_build_var_ptr_x(ag, scope, source_node, var, nullptr); | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | static IrInstSrc *ir_build_elem_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1144 | IrInstSrc *array_ptr, IrInstSrc *elem_index, bool safety_check_on, PtrLen ptr_len, | ||
| 1145 | AstNode *init_array_type_source_node) | ||
| 1146 | { | ||
| 1147 | IrInstSrcElemPtr *instruction = ir_build_instruction<IrInstSrcElemPtr>(ag, scope, source_node); | ||
| 1148 | instruction->array_ptr = array_ptr; | ||
| 1149 | instruction->elem_index = elem_index; | ||
| 1150 | instruction->safety_check_on = safety_check_on; | ||
| 1151 | instruction->ptr_len = ptr_len; | ||
| 1152 | instruction->init_array_type_source_node = init_array_type_source_node; | ||
| 1153 | |||
| 1154 | ir_ref_instruction(array_ptr, ag->current_basic_block); | ||
| 1155 | ir_ref_instruction(elem_index, ag->current_basic_block); | ||
| 1156 | |||
| 1157 | return &instruction->base; | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | static IrInstSrc *ir_build_field_ptr_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1161 | IrInstSrc *container_ptr, IrInstSrc *field_name_expr, bool initializing) | ||
| 1162 | { | ||
| 1163 | IrInstSrcFieldPtr *instruction = ir_build_instruction<IrInstSrcFieldPtr>(ag, scope, source_node); | ||
| 1164 | instruction->container_ptr = container_ptr; | ||
| 1165 | instruction->field_name_buffer = nullptr; | ||
| 1166 | instruction->field_name_expr = field_name_expr; | ||
| 1167 | instruction->initializing = initializing; | ||
| 1168 | |||
| 1169 | ir_ref_instruction(container_ptr, ag->current_basic_block); | ||
| 1170 | ir_ref_instruction(field_name_expr, ag->current_basic_block); | ||
| 1171 | |||
| 1172 | return &instruction->base; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | static IrInstSrc *ir_build_field_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1176 | IrInstSrc *container_ptr, Buf *field_name, bool initializing) | ||
| 1177 | { | ||
| 1178 | IrInstSrcFieldPtr *instruction = ir_build_instruction<IrInstSrcFieldPtr>(ag, scope, source_node); | ||
| 1179 | instruction->container_ptr = container_ptr; | ||
| 1180 | instruction->field_name_buffer = field_name; | ||
| 1181 | instruction->field_name_expr = nullptr; | ||
| 1182 | instruction->initializing = initializing; | ||
| 1183 | |||
| 1184 | ir_ref_instruction(container_ptr, ag->current_basic_block); | ||
| 1185 | |||
| 1186 | return &instruction->base; | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | static IrInstSrc *ir_build_has_field(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1190 | IrInstSrc *container_type, IrInstSrc *field_name) | ||
| 1191 | { | ||
| 1192 | IrInstSrcHasField *instruction = ir_build_instruction<IrInstSrcHasField>(ag, scope, source_node); | ||
| 1193 | instruction->container_type = container_type; | ||
| 1194 | instruction->field_name = field_name; | ||
| 1195 | |||
| 1196 | ir_ref_instruction(container_type, ag->current_basic_block); | ||
| 1197 | ir_ref_instruction(field_name, ag->current_basic_block); | ||
| 1198 | |||
| 1199 | return &instruction->base; | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | static IrInstSrc *ir_build_call_extra(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1203 | IrInstSrc *options, IrInstSrc *fn_ref, IrInstSrc *args, ResultLoc *result_loc) | ||
| 1204 | { | ||
| 1205 | IrInstSrcCallExtra *call_instruction = ir_build_instruction<IrInstSrcCallExtra>(ag, scope, source_node); | ||
| 1206 | call_instruction->options = options; | ||
| 1207 | call_instruction->fn_ref = fn_ref; | ||
| 1208 | call_instruction->args = args; | ||
| 1209 | call_instruction->result_loc = result_loc; | ||
| 1210 | |||
| 1211 | ir_ref_instruction(options, ag->current_basic_block); | ||
| 1212 | ir_ref_instruction(fn_ref, ag->current_basic_block); | ||
| 1213 | ir_ref_instruction(args, ag->current_basic_block); | ||
| 1214 | |||
| 1215 | return &call_instruction->base; | ||
| 1216 | } | ||
| 1217 | |||
| 1218 | static IrInstSrc *ir_build_async_call_extra(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1219 | CallModifier modifier, IrInstSrc *fn_ref, IrInstSrc *ret_ptr, IrInstSrc *new_stack, IrInstSrc *args, ResultLoc *result_loc) | ||
| 1220 | { | ||
| 1221 | IrInstSrcAsyncCallExtra *call_instruction = ir_build_instruction<IrInstSrcAsyncCallExtra>(ag, scope, source_node); | ||
| 1222 | call_instruction->modifier = modifier; | ||
| 1223 | call_instruction->fn_ref = fn_ref; | ||
| 1224 | call_instruction->ret_ptr = ret_ptr; | ||
| 1225 | call_instruction->new_stack = new_stack; | ||
| 1226 | call_instruction->args = args; | ||
| 1227 | call_instruction->result_loc = result_loc; | ||
| 1228 | |||
| 1229 | ir_ref_instruction(fn_ref, ag->current_basic_block); | ||
| 1230 | if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, ag->current_basic_block); | ||
| 1231 | ir_ref_instruction(new_stack, ag->current_basic_block); | ||
| 1232 | ir_ref_instruction(args, ag->current_basic_block); | ||
| 1233 | |||
| 1234 | return &call_instruction->base; | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | static IrInstSrc *ir_build_call_args(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1238 | IrInstSrc *options, IrInstSrc *fn_ref, IrInstSrc **args_ptr, size_t args_len, | ||
| 1239 | ResultLoc *result_loc) | ||
| 1240 | { | ||
| 1241 | IrInstSrcCallArgs *call_instruction = ir_build_instruction<IrInstSrcCallArgs>(ag, scope, source_node); | ||
| 1242 | call_instruction->options = options; | ||
| 1243 | call_instruction->fn_ref = fn_ref; | ||
| 1244 | call_instruction->args_ptr = args_ptr; | ||
| 1245 | call_instruction->args_len = args_len; | ||
| 1246 | call_instruction->result_loc = result_loc; | ||
| 1247 | |||
| 1248 | ir_ref_instruction(options, ag->current_basic_block); | ||
| 1249 | ir_ref_instruction(fn_ref, ag->current_basic_block); | ||
| 1250 | for (size_t i = 0; i < args_len; i += 1) | ||
| 1251 | ir_ref_instruction(args_ptr[i], ag->current_basic_block); | ||
| 1252 | |||
| 1253 | return &call_instruction->base; | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | static IrInstSrc *ir_build_call_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1257 | ZigFn *fn_entry, IrInstSrc *fn_ref, size_t arg_count, IrInstSrc **args, | ||
| 1258 | IrInstSrc *ret_ptr, CallModifier modifier, bool is_async_call_builtin, | ||
| 1259 | IrInstSrc *new_stack, ResultLoc *result_loc) | ||
| 1260 | { | ||
| 1261 | IrInstSrcCall *call_instruction = ir_build_instruction<IrInstSrcCall>(ag, scope, source_node); | ||
| 1262 | call_instruction->fn_entry = fn_entry; | ||
| 1263 | call_instruction->fn_ref = fn_ref; | ||
| 1264 | call_instruction->args = args; | ||
| 1265 | call_instruction->arg_count = arg_count; | ||
| 1266 | call_instruction->modifier = modifier; | ||
| 1267 | call_instruction->is_async_call_builtin = is_async_call_builtin; | ||
| 1268 | call_instruction->new_stack = new_stack; | ||
| 1269 | call_instruction->result_loc = result_loc; | ||
| 1270 | call_instruction->ret_ptr = ret_ptr; | ||
| 1271 | |||
| 1272 | if (fn_ref != nullptr) ir_ref_instruction(fn_ref, ag->current_basic_block); | ||
| 1273 | for (size_t i = 0; i < arg_count; i += 1) | ||
| 1274 | ir_ref_instruction(args[i], ag->current_basic_block); | ||
| 1275 | if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, ag->current_basic_block); | ||
| 1276 | if (new_stack != nullptr) ir_ref_instruction(new_stack, ag->current_basic_block); | ||
| 1277 | |||
| 1278 | return &call_instruction->base; | ||
| 1279 | } | ||
| 1280 | |||
| 1281 | static IrInstSrc *ir_build_phi(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1282 | size_t incoming_count, Stage1ZirBasicBlock **incoming_blocks, IrInstSrc **incoming_values, | ||
| 1283 | ResultLocPeerParent *peer_parent) | ||
| 1284 | { | ||
| 1285 | assert(incoming_count != 0); | ||
| 1286 | assert(incoming_count != SIZE_MAX); | ||
| 1287 | |||
| 1288 | IrInstSrcPhi *phi_instruction = ir_build_instruction<IrInstSrcPhi>(ag, scope, source_node); | ||
| 1289 | phi_instruction->incoming_count = incoming_count; | ||
| 1290 | phi_instruction->incoming_blocks = incoming_blocks; | ||
| 1291 | phi_instruction->incoming_values = incoming_values; | ||
| 1292 | phi_instruction->peer_parent = peer_parent; | ||
| 1293 | |||
| 1294 | for (size_t i = 0; i < incoming_count; i += 1) { | ||
| 1295 | ir_ref_bb(incoming_blocks[i]); | ||
| 1296 | ir_ref_instruction(incoming_values[i], ag->current_basic_block); | ||
| 1297 | } | ||
| 1298 | |||
| 1299 | return &phi_instruction->base; | ||
| 1300 | } | ||
| 1301 | |||
| 1302 | static IrInstSrc *ir_build_br(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1303 | Stage1ZirBasicBlock *dest_block, IrInstSrc *is_comptime) | ||
| 1304 | { | ||
| 1305 | IrInstSrcBr *inst = ir_build_instruction<IrInstSrcBr>(ag, scope, source_node); | ||
| 1306 | inst->base.is_noreturn = true; | ||
| 1307 | inst->dest_block = dest_block; | ||
| 1308 | inst->is_comptime = is_comptime; | ||
| 1309 | |||
| 1310 | ir_ref_bb(dest_block); | ||
| 1311 | if (is_comptime) ir_ref_instruction(is_comptime, ag->current_basic_block); | ||
| 1312 | |||
| 1313 | return &inst->base; | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | static IrInstSrc *ir_build_ptr_type_simple(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1317 | IrInstSrc *child_type, bool is_const) | ||
| 1318 | { | ||
| 1319 | IrInstSrcPtrTypeSimple *inst = heap::c_allocator.create<IrInstSrcPtrTypeSimple>(); | ||
| 1320 | inst->base.id = is_const ? IrInstSrcIdPtrTypeSimpleConst : IrInstSrcIdPtrTypeSimple; | ||
| 1321 | inst->base.base.scope = scope; | ||
| 1322 | inst->base.base.source_node = source_node; | ||
| 1323 | inst->base.base.debug_id = irb_next_debug_id(ag); | ||
| 1324 | inst->base.owner_bb = ag->current_basic_block; | ||
| 1325 | ir_instruction_append(ag->current_basic_block, &inst->base); | ||
| 1326 | |||
| 1327 | inst->child_type = child_type; | ||
| 1328 | |||
| 1329 | ir_ref_instruction(child_type, ag->current_basic_block); | ||
| 1330 | |||
| 1331 | return &inst->base; | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | static IrInstSrc *ir_build_ptr_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1335 | IrInstSrc *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, | ||
| 1336 | IrInstSrc *sentinel, IrInstSrc *align_value, | ||
| 1337 | uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero) | ||
| 1338 | { | ||
| 1339 | if (!is_volatile && ptr_len == PtrLenSingle && sentinel == nullptr && align_value == nullptr && | ||
| 1340 | bit_offset_start == 0 && host_int_bytes == 0 && is_allow_zero == 0) | ||
| 1341 | { | ||
| 1342 | return ir_build_ptr_type_simple(ag, scope, source_node, child_type, is_const); | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | IrInstSrcPtrType *inst = ir_build_instruction<IrInstSrcPtrType>(ag, scope, source_node); | ||
| 1346 | inst->sentinel = sentinel; | ||
| 1347 | inst->align_value = align_value; | ||
| 1348 | inst->child_type = child_type; | ||
| 1349 | inst->is_const = is_const; | ||
| 1350 | inst->is_volatile = is_volatile; | ||
| 1351 | inst->ptr_len = ptr_len; | ||
| 1352 | inst->bit_offset_start = bit_offset_start; | ||
| 1353 | inst->host_int_bytes = host_int_bytes; | ||
| 1354 | inst->is_allow_zero = is_allow_zero; | ||
| 1355 | |||
| 1356 | if (sentinel) ir_ref_instruction(sentinel, ag->current_basic_block); | ||
| 1357 | if (align_value) ir_ref_instruction(align_value, ag->current_basic_block); | ||
| 1358 | ir_ref_instruction(child_type, ag->current_basic_block); | ||
| 1359 | |||
| 1360 | return &inst->base; | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | static IrInstSrc *ir_build_un_op_lval(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrUnOp op_id, | ||
| 1364 | IrInstSrc *value, LVal lval, ResultLoc *result_loc) | ||
| 1365 | { | ||
| 1366 | IrInstSrcUnOp *instruction = ir_build_instruction<IrInstSrcUnOp>(ag, scope, source_node); | ||
| 1367 | instruction->op_id = op_id; | ||
| 1368 | instruction->value = value; | ||
| 1369 | instruction->lval = lval; | ||
| 1370 | instruction->result_loc = result_loc; | ||
| 1371 | |||
| 1372 | ir_ref_instruction(value, ag->current_basic_block); | ||
| 1373 | |||
| 1374 | return &instruction->base; | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | static IrInstSrc *ir_build_un_op(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrUnOp op_id, | ||
| 1378 | IrInstSrc *value) | ||
| 1379 | { | ||
| 1380 | return ir_build_un_op_lval(ag, scope, source_node, op_id, value, LValNone, nullptr); | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | static IrInstSrc *ir_build_container_init_list(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1384 | size_t item_count, IrInstSrc **elem_result_loc_list, IrInstSrc *result_loc, | ||
| 1385 | AstNode *init_array_type_source_node) | ||
| 1386 | { | ||
| 1387 | IrInstSrcContainerInitList *container_init_list_instruction = | ||
| 1388 | ir_build_instruction<IrInstSrcContainerInitList>(ag, scope, source_node); | ||
| 1389 | container_init_list_instruction->item_count = item_count; | ||
| 1390 | container_init_list_instruction->elem_result_loc_list = elem_result_loc_list; | ||
| 1391 | container_init_list_instruction->result_loc = result_loc; | ||
| 1392 | container_init_list_instruction->init_array_type_source_node = init_array_type_source_node; | ||
| 1393 | |||
| 1394 | for (size_t i = 0; i < item_count; i += 1) { | ||
| 1395 | ir_ref_instruction(elem_result_loc_list[i], ag->current_basic_block); | ||
| 1396 | } | ||
| 1397 | if (result_loc != nullptr) ir_ref_instruction(result_loc, ag->current_basic_block); | ||
| 1398 | |||
| 1399 | return &container_init_list_instruction->base; | ||
| 1400 | } | ||
| 1401 | |||
| 1402 | static IrInstSrc *ir_build_container_init_fields(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1403 | size_t field_count, IrInstSrcContainerInitFieldsField *fields, IrInstSrc *result_loc) | ||
| 1404 | { | ||
| 1405 | IrInstSrcContainerInitFields *container_init_fields_instruction = | ||
| 1406 | ir_build_instruction<IrInstSrcContainerInitFields>(ag, scope, source_node); | ||
| 1407 | container_init_fields_instruction->field_count = field_count; | ||
| 1408 | container_init_fields_instruction->fields = fields; | ||
| 1409 | container_init_fields_instruction->result_loc = result_loc; | ||
| 1410 | |||
| 1411 | for (size_t i = 0; i < field_count; i += 1) { | ||
| 1412 | ir_ref_instruction(fields[i].result_loc, ag->current_basic_block); | ||
| 1413 | } | ||
| 1414 | if (result_loc != nullptr) ir_ref_instruction(result_loc, ag->current_basic_block); | ||
| 1415 | |||
| 1416 | return &container_init_fields_instruction->base; | ||
| 1417 | } | ||
| 1418 | |||
| 1419 | static IrInstSrc *ir_build_unreachable(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | ||
| 1420 | IrInstSrcUnreachable *inst = ir_build_instruction<IrInstSrcUnreachable>(ag, scope, source_node); | ||
| 1421 | inst->base.is_noreturn = true; | ||
| 1422 | return &inst->base; | ||
| 1423 | } | ||
| 1424 | |||
| 1425 | static IrInstSrcStorePtr *ir_build_store_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1426 | IrInstSrc *ptr, IrInstSrc *value) | ||
| 1427 | { | ||
| 1428 | IrInstSrcStorePtr *instruction = ir_build_instruction<IrInstSrcStorePtr>(ag, scope, source_node); | ||
| 1429 | instruction->ptr = ptr; | ||
| 1430 | instruction->value = value; | ||
| 1431 | |||
| 1432 | ir_ref_instruction(ptr, ag->current_basic_block); | ||
| 1433 | ir_ref_instruction(value, ag->current_basic_block); | ||
| 1434 | |||
| 1435 | return instruction; | ||
| 1436 | } | ||
| 1437 | |||
| 1438 | static IrInstSrc *ir_build_var_decl_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1439 | ZigVar *var, IrInstSrc *align_value, IrInstSrc *ptr) | ||
| 1440 | { | ||
| 1441 | IrInstSrcDeclVar *inst = ir_build_instruction<IrInstSrcDeclVar>(ag, scope, source_node); | ||
| 1442 | inst->var = var; | ||
| 1443 | inst->align_value = align_value; | ||
| 1444 | inst->ptr = ptr; | ||
| 1445 | |||
| 1446 | if (align_value != nullptr) ir_ref_instruction(align_value, ag->current_basic_block); | ||
| 1447 | ir_ref_instruction(ptr, ag->current_basic_block); | ||
| 1448 | |||
| 1449 | return &inst->base; | ||
| 1450 | } | ||
| 1451 | |||
| 1452 | static IrInstSrc *ir_build_export(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1453 | IrInstSrc *target, IrInstSrc *options) | ||
| 1454 | { | ||
| 1455 | IrInstSrcExport *export_instruction = ir_build_instruction<IrInstSrcExport>( | ||
| 1456 | ag, scope, source_node); | ||
| 1457 | export_instruction->target = target; | ||
| 1458 | export_instruction->options = options; | ||
| 1459 | |||
| 1460 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 1461 | ir_ref_instruction(options, ag->current_basic_block); | ||
| 1462 | |||
| 1463 | return &export_instruction->base; | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | static IrInstSrc *ir_build_extern(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1467 | IrInstSrc *type, IrInstSrc *options) | ||
| 1468 | { | ||
| 1469 | IrInstSrcExtern *extern_instruction = ir_build_instruction<IrInstSrcExtern>( | ||
| 1470 | ag, scope, source_node); | ||
| 1471 | extern_instruction->type = type; | ||
| 1472 | extern_instruction->options = options; | ||
| 1473 | |||
| 1474 | ir_ref_instruction(type, ag->current_basic_block); | ||
| 1475 | ir_ref_instruction(options, ag->current_basic_block); | ||
| 1476 | |||
| 1477 | return &extern_instruction->base; | ||
| 1478 | } | ||
| 1479 | |||
| 1480 | static IrInstSrc *ir_build_load_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *ptr) { | ||
| 1481 | IrInstSrcLoadPtr *instruction = ir_build_instruction<IrInstSrcLoadPtr>(ag, scope, source_node); | ||
| 1482 | instruction->ptr = ptr; | ||
| 1483 | |||
| 1484 | ir_ref_instruction(ptr, ag->current_basic_block); | ||
| 1485 | |||
| 1486 | return &instruction->base; | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | static IrInstSrc *ir_build_typeof_n(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1490 | IrInstSrc **values, size_t value_count) | ||
| 1491 | { | ||
| 1492 | assert(value_count >= 2); | ||
| 1493 | |||
| 1494 | IrInstSrcTypeOf *instruction = ir_build_instruction<IrInstSrcTypeOf>(ag, scope, source_node); | ||
| 1495 | instruction->value.list = values; | ||
| 1496 | instruction->value_count = value_count; | ||
| 1497 | |||
| 1498 | for (size_t i = 0; i < value_count; i++) | ||
| 1499 | ir_ref_instruction(values[i], ag->current_basic_block); | ||
| 1500 | |||
| 1501 | return &instruction->base; | ||
| 1502 | } | ||
| 1503 | |||
| 1504 | static IrInstSrc *ir_build_typeof_1(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *value) { | ||
| 1505 | IrInstSrcTypeOf *instruction = ir_build_instruction<IrInstSrcTypeOf>(ag, scope, source_node); | ||
| 1506 | instruction->value.scalar = value; | ||
| 1507 | |||
| 1508 | ir_ref_instruction(value, ag->current_basic_block); | ||
| 1509 | |||
| 1510 | return &instruction->base; | ||
| 1511 | } | ||
| 1512 | |||
| 1513 | static IrInstSrc *ir_build_set_cold(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *is_cold) { | ||
| 1514 | IrInstSrcSetCold *instruction = ir_build_instruction<IrInstSrcSetCold>(ag, scope, source_node); | ||
| 1515 | instruction->is_cold = is_cold; | ||
| 1516 | |||
| 1517 | ir_ref_instruction(is_cold, ag->current_basic_block); | ||
| 1518 | |||
| 1519 | return &instruction->base; | ||
| 1520 | } | ||
| 1521 | |||
| 1522 | static IrInstSrc *ir_build_set_runtime_safety(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1523 | IrInstSrc *safety_on) | ||
| 1524 | { | ||
| 1525 | IrInstSrcSetRuntimeSafety *inst = ir_build_instruction<IrInstSrcSetRuntimeSafety>(ag, scope, source_node); | ||
| 1526 | inst->safety_on = safety_on; | ||
| 1527 | |||
| 1528 | ir_ref_instruction(safety_on, ag->current_basic_block); | ||
| 1529 | |||
| 1530 | return &inst->base; | ||
| 1531 | } | ||
| 1532 | |||
| 1533 | static IrInstSrc *ir_build_set_float_mode(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1534 | IrInstSrc *mode_value) | ||
| 1535 | { | ||
| 1536 | IrInstSrcSetFloatMode *instruction = ir_build_instruction<IrInstSrcSetFloatMode>(ag, scope, source_node); | ||
| 1537 | instruction->mode_value = mode_value; | ||
| 1538 | |||
| 1539 | ir_ref_instruction(mode_value, ag->current_basic_block); | ||
| 1540 | |||
| 1541 | return &instruction->base; | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | static IrInstSrc *ir_build_array_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *size, | ||
| 1545 | IrInstSrc *sentinel, IrInstSrc *child_type) | ||
| 1546 | { | ||
| 1547 | IrInstSrcArrayType *instruction = ir_build_instruction<IrInstSrcArrayType>(ag, scope, source_node); | ||
| 1548 | instruction->size = size; | ||
| 1549 | instruction->sentinel = sentinel; | ||
| 1550 | instruction->child_type = child_type; | ||
| 1551 | |||
| 1552 | ir_ref_instruction(size, ag->current_basic_block); | ||
| 1553 | if (sentinel != nullptr) ir_ref_instruction(sentinel, ag->current_basic_block); | ||
| 1554 | ir_ref_instruction(child_type, ag->current_basic_block); | ||
| 1555 | |||
| 1556 | return &instruction->base; | ||
| 1557 | } | ||
| 1558 | |||
| 1559 | static IrInstSrc *ir_build_anyframe_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1560 | IrInstSrc *payload_type) | ||
| 1561 | { | ||
| 1562 | IrInstSrcAnyFrameType *instruction = ir_build_instruction<IrInstSrcAnyFrameType>(ag, scope, source_node); | ||
| 1563 | instruction->payload_type = payload_type; | ||
| 1564 | |||
| 1565 | if (payload_type != nullptr) ir_ref_instruction(payload_type, ag->current_basic_block); | ||
| 1566 | |||
| 1567 | return &instruction->base; | ||
| 1568 | } | ||
| 1569 | |||
| 1570 | static IrInstSrc *ir_build_slice_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1571 | IrInstSrc *child_type, bool is_const, bool is_volatile, | ||
| 1572 | IrInstSrc *sentinel, IrInstSrc *align_value, bool is_allow_zero) | ||
| 1573 | { | ||
| 1574 | IrInstSrcSliceType *instruction = ir_build_instruction<IrInstSrcSliceType>(ag, scope, source_node); | ||
| 1575 | instruction->is_const = is_const; | ||
| 1576 | instruction->is_volatile = is_volatile; | ||
| 1577 | instruction->child_type = child_type; | ||
| 1578 | instruction->sentinel = sentinel; | ||
| 1579 | instruction->align_value = align_value; | ||
| 1580 | instruction->is_allow_zero = is_allow_zero; | ||
| 1581 | |||
| 1582 | if (sentinel != nullptr) ir_ref_instruction(sentinel, ag->current_basic_block); | ||
| 1583 | if (align_value != nullptr) ir_ref_instruction(align_value, ag->current_basic_block); | ||
| 1584 | ir_ref_instruction(child_type, ag->current_basic_block); | ||
| 1585 | |||
| 1586 | return &instruction->base; | ||
| 1587 | } | ||
| 1588 | |||
| 1589 | static IrInstSrc *ir_build_asm_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1590 | IrInstSrc *asm_template, IrInstSrc **input_list, IrInstSrc **output_types, | ||
| 1591 | ZigVar **output_vars, size_t return_count, bool has_side_effects, bool is_global) | ||
| 1592 | { | ||
| 1593 | IrInstSrcAsm *instruction = ir_build_instruction<IrInstSrcAsm>(ag, scope, source_node); | ||
| 1594 | instruction->asm_template = asm_template; | ||
| 1595 | instruction->input_list = input_list; | ||
| 1596 | instruction->output_types = output_types; | ||
| 1597 | instruction->output_vars = output_vars; | ||
| 1598 | instruction->return_count = return_count; | ||
| 1599 | instruction->has_side_effects = has_side_effects; | ||
| 1600 | instruction->is_global = is_global; | ||
| 1601 | |||
| 1602 | assert(source_node->type == NodeTypeAsmExpr); | ||
| 1603 | for (size_t i = 0; i < source_node->data.asm_expr.output_list.length; i += 1) { | ||
| 1604 | IrInstSrc *output_type = output_types[i]; | ||
| 1605 | if (output_type) ir_ref_instruction(output_type, ag->current_basic_block); | ||
| 1606 | } | ||
| 1607 | |||
| 1608 | for (size_t i = 0; i < source_node->data.asm_expr.input_list.length; i += 1) { | ||
| 1609 | IrInstSrc *input_value = input_list[i]; | ||
| 1610 | ir_ref_instruction(input_value, ag->current_basic_block); | ||
| 1611 | } | ||
| 1612 | |||
| 1613 | return &instruction->base; | ||
| 1614 | } | ||
| 1615 | |||
| 1616 | static IrInstSrc *ir_build_size_of(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type_value, | ||
| 1617 | bool bit_size) | ||
| 1618 | { | ||
| 1619 | IrInstSrcSizeOf *instruction = ir_build_instruction<IrInstSrcSizeOf>(ag, scope, source_node); | ||
| 1620 | instruction->type_value = type_value; | ||
| 1621 | instruction->bit_size = bit_size; | ||
| 1622 | |||
| 1623 | ir_ref_instruction(type_value, ag->current_basic_block); | ||
| 1624 | |||
| 1625 | return &instruction->base; | ||
| 1626 | } | ||
| 1627 | |||
| 1628 | static IrInstSrc *ir_build_test_non_null_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1629 | IrInstSrc *value) | ||
| 1630 | { | ||
| 1631 | IrInstSrcTestNonNull *instruction = ir_build_instruction<IrInstSrcTestNonNull>(ag, scope, source_node); | ||
| 1632 | instruction->value = value; | ||
| 1633 | |||
| 1634 | ir_ref_instruction(value, ag->current_basic_block); | ||
| 1635 | |||
| 1636 | return &instruction->base; | ||
| 1637 | } | ||
| 1638 | |||
| 1639 | static IrInstSrc *ir_build_optional_unwrap_ptr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1640 | IrInstSrc *base_ptr, bool safety_check_on) | ||
| 1641 | { | ||
| 1642 | IrInstSrcOptionalUnwrapPtr *instruction = ir_build_instruction<IrInstSrcOptionalUnwrapPtr>(ag, scope, source_node); | ||
| 1643 | instruction->base_ptr = base_ptr; | ||
| 1644 | instruction->safety_check_on = safety_check_on; | ||
| 1645 | |||
| 1646 | ir_ref_instruction(base_ptr, ag->current_basic_block); | ||
| 1647 | |||
| 1648 | return &instruction->base; | ||
| 1649 | } | ||
| 1650 | |||
| 1651 | static IrInstSrc *ir_build_clz(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type, | ||
| 1652 | IrInstSrc *op) | ||
| 1653 | { | ||
| 1654 | IrInstSrcClz *instruction = ir_build_instruction<IrInstSrcClz>(ag, scope, source_node); | ||
| 1655 | instruction->type = type; | ||
| 1656 | instruction->op = op; | ||
| 1657 | |||
| 1658 | ir_ref_instruction(type, ag->current_basic_block); | ||
| 1659 | ir_ref_instruction(op, ag->current_basic_block); | ||
| 1660 | |||
| 1661 | return &instruction->base; | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | static IrInstSrc *ir_build_ctz(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type, | ||
| 1665 | IrInstSrc *op) | ||
| 1666 | { | ||
| 1667 | IrInstSrcCtz *instruction = ir_build_instruction<IrInstSrcCtz>(ag, scope, source_node); | ||
| 1668 | instruction->type = type; | ||
| 1669 | instruction->op = op; | ||
| 1670 | |||
| 1671 | ir_ref_instruction(type, ag->current_basic_block); | ||
| 1672 | ir_ref_instruction(op, ag->current_basic_block); | ||
| 1673 | |||
| 1674 | return &instruction->base; | ||
| 1675 | } | ||
| 1676 | |||
| 1677 | static IrInstSrc *ir_build_pop_count(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type, | ||
| 1678 | IrInstSrc *op) | ||
| 1679 | { | ||
| 1680 | IrInstSrcPopCount *instruction = ir_build_instruction<IrInstSrcPopCount>(ag, scope, source_node); | ||
| 1681 | instruction->type = type; | ||
| 1682 | instruction->op = op; | ||
| 1683 | |||
| 1684 | ir_ref_instruction(type, ag->current_basic_block); | ||
| 1685 | ir_ref_instruction(op, ag->current_basic_block); | ||
| 1686 | |||
| 1687 | return &instruction->base; | ||
| 1688 | } | ||
| 1689 | |||
| 1690 | static IrInstSrc *ir_build_bswap(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type, | ||
| 1691 | IrInstSrc *op) | ||
| 1692 | { | ||
| 1693 | IrInstSrcBswap *instruction = ir_build_instruction<IrInstSrcBswap>(ag, scope, source_node); | ||
| 1694 | instruction->type = type; | ||
| 1695 | instruction->op = op; | ||
| 1696 | |||
| 1697 | ir_ref_instruction(type, ag->current_basic_block); | ||
| 1698 | ir_ref_instruction(op, ag->current_basic_block); | ||
| 1699 | |||
| 1700 | return &instruction->base; | ||
| 1701 | } | ||
| 1702 | |||
| 1703 | static IrInstSrc *ir_build_bit_reverse(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type, | ||
| 1704 | IrInstSrc *op) | ||
| 1705 | { | ||
| 1706 | IrInstSrcBitReverse *instruction = ir_build_instruction<IrInstSrcBitReverse>(ag, scope, source_node); | ||
| 1707 | instruction->type = type; | ||
| 1708 | instruction->op = op; | ||
| 1709 | |||
| 1710 | ir_ref_instruction(type, ag->current_basic_block); | ||
| 1711 | ir_ref_instruction(op, ag->current_basic_block); | ||
| 1712 | |||
| 1713 | return &instruction->base; | ||
| 1714 | } | ||
| 1715 | |||
| 1716 | static IrInstSrcSwitchBr *ir_build_switch_br_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1717 | IrInstSrc *target_value, Stage1ZirBasicBlock *else_block, size_t case_count, IrInstSrcSwitchBrCase *cases, | ||
| 1718 | IrInstSrc *is_comptime, IrInstSrc *switch_prongs_void) | ||
| 1719 | { | ||
| 1720 | IrInstSrcSwitchBr *instruction = ir_build_instruction<IrInstSrcSwitchBr>(ag, scope, source_node); | ||
| 1721 | instruction->base.is_noreturn = true; | ||
| 1722 | instruction->target_value = target_value; | ||
| 1723 | instruction->else_block = else_block; | ||
| 1724 | instruction->case_count = case_count; | ||
| 1725 | instruction->cases = cases; | ||
| 1726 | instruction->is_comptime = is_comptime; | ||
| 1727 | instruction->switch_prongs_void = switch_prongs_void; | ||
| 1728 | |||
| 1729 | ir_ref_instruction(target_value, ag->current_basic_block); | ||
| 1730 | ir_ref_instruction(is_comptime, ag->current_basic_block); | ||
| 1731 | ir_ref_bb(else_block); | ||
| 1732 | ir_ref_instruction(switch_prongs_void, ag->current_basic_block); | ||
| 1733 | |||
| 1734 | for (size_t i = 0; i < case_count; i += 1) { | ||
| 1735 | ir_ref_instruction(cases[i].value, ag->current_basic_block); | ||
| 1736 | ir_ref_bb(cases[i].block); | ||
| 1737 | } | ||
| 1738 | |||
| 1739 | return instruction; | ||
| 1740 | } | ||
| 1741 | |||
| 1742 | static IrInstSrc *ir_build_switch_target(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1743 | IrInstSrc *target_value_ptr) | ||
| 1744 | { | ||
| 1745 | IrInstSrcSwitchTarget *instruction = ir_build_instruction<IrInstSrcSwitchTarget>(ag, scope, source_node); | ||
| 1746 | instruction->target_value_ptr = target_value_ptr; | ||
| 1747 | |||
| 1748 | ir_ref_instruction(target_value_ptr, ag->current_basic_block); | ||
| 1749 | |||
| 1750 | return &instruction->base; | ||
| 1751 | } | ||
| 1752 | |||
| 1753 | static IrInstSrc *ir_build_switch_var(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1754 | IrInstSrc *target_value_ptr, IrInstSrc **prongs_ptr, size_t prongs_len) | ||
| 1755 | { | ||
| 1756 | IrInstSrcSwitchVar *instruction = ir_build_instruction<IrInstSrcSwitchVar>(ag, scope, source_node); | ||
| 1757 | instruction->target_value_ptr = target_value_ptr; | ||
| 1758 | instruction->prongs_ptr = prongs_ptr; | ||
| 1759 | instruction->prongs_len = prongs_len; | ||
| 1760 | |||
| 1761 | ir_ref_instruction(target_value_ptr, ag->current_basic_block); | ||
| 1762 | for (size_t i = 0; i < prongs_len; i += 1) { | ||
| 1763 | ir_ref_instruction(prongs_ptr[i], ag->current_basic_block); | ||
| 1764 | } | ||
| 1765 | |||
| 1766 | return &instruction->base; | ||
| 1767 | } | ||
| 1768 | |||
| 1769 | // For this instruction the switch_br must be set later. | ||
| 1770 | static IrInstSrcSwitchElseVar *ir_build_switch_else_var(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1771 | IrInstSrc *target_value_ptr) | ||
| 1772 | { | ||
| 1773 | IrInstSrcSwitchElseVar *instruction = ir_build_instruction<IrInstSrcSwitchElseVar>(ag, scope, source_node); | ||
| 1774 | instruction->target_value_ptr = target_value_ptr; | ||
| 1775 | |||
| 1776 | ir_ref_instruction(target_value_ptr, ag->current_basic_block); | ||
| 1777 | |||
| 1778 | return instruction; | ||
| 1779 | } | ||
| 1780 | |||
| 1781 | static IrInstSrc *ir_build_import(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *name) { | ||
| 1782 | IrInstSrcImport *instruction = ir_build_instruction<IrInstSrcImport>(ag, scope, source_node); | ||
| 1783 | instruction->name = name; | ||
| 1784 | |||
| 1785 | ir_ref_instruction(name, ag->current_basic_block); | ||
| 1786 | |||
| 1787 | return &instruction->base; | ||
| 1788 | } | ||
| 1789 | |||
| 1790 | static IrInstSrc *ir_build_ref_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *value) { | ||
| 1791 | IrInstSrcRef *instruction = ir_build_instruction<IrInstSrcRef>(ag, scope, source_node); | ||
| 1792 | instruction->value = value; | ||
| 1793 | |||
| 1794 | ir_ref_instruction(value, ag->current_basic_block); | ||
| 1795 | |||
| 1796 | return &instruction->base; | ||
| 1797 | } | ||
| 1798 | |||
| 1799 | static IrInstSrc *ir_build_compile_err(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *msg) { | ||
| 1800 | IrInstSrcCompileErr *instruction = ir_build_instruction<IrInstSrcCompileErr>(ag, scope, source_node); | ||
| 1801 | instruction->msg = msg; | ||
| 1802 | |||
| 1803 | ir_ref_instruction(msg, ag->current_basic_block); | ||
| 1804 | |||
| 1805 | return &instruction->base; | ||
| 1806 | } | ||
| 1807 | |||
| 1808 | static IrInstSrc *ir_build_compile_log(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1809 | size_t msg_count, IrInstSrc **msg_list) | ||
| 1810 | { | ||
| 1811 | IrInstSrcCompileLog *instruction = ir_build_instruction<IrInstSrcCompileLog>(ag, scope, source_node); | ||
| 1812 | instruction->msg_count = msg_count; | ||
| 1813 | instruction->msg_list = msg_list; | ||
| 1814 | |||
| 1815 | for (size_t i = 0; i < msg_count; i += 1) { | ||
| 1816 | ir_ref_instruction(msg_list[i], ag->current_basic_block); | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | return &instruction->base; | ||
| 1820 | } | ||
| 1821 | |||
| 1822 | static IrInstSrc *ir_build_err_name(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *value) { | ||
| 1823 | IrInstSrcErrName *instruction = ir_build_instruction<IrInstSrcErrName>(ag, scope, source_node); | ||
| 1824 | instruction->value = value; | ||
| 1825 | |||
| 1826 | ir_ref_instruction(value, ag->current_basic_block); | ||
| 1827 | |||
| 1828 | return &instruction->base; | ||
| 1829 | } | ||
| 1830 | |||
| 1831 | static IrInstSrc *ir_build_c_import(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | ||
| 1832 | IrInstSrcCImport *instruction = ir_build_instruction<IrInstSrcCImport>(ag, scope, source_node); | ||
| 1833 | return &instruction->base; | ||
| 1834 | } | ||
| 1835 | |||
| 1836 | static IrInstSrc *ir_build_c_include(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *name) { | ||
| 1837 | IrInstSrcCInclude *instruction = ir_build_instruction<IrInstSrcCInclude>(ag, scope, source_node); | ||
| 1838 | instruction->name = name; | ||
| 1839 | |||
| 1840 | ir_ref_instruction(name, ag->current_basic_block); | ||
| 1841 | |||
| 1842 | return &instruction->base; | ||
| 1843 | } | ||
| 1844 | |||
| 1845 | static IrInstSrc *ir_build_c_define(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *name, IrInstSrc *value) { | ||
| 1846 | IrInstSrcCDefine *instruction = ir_build_instruction<IrInstSrcCDefine>(ag, scope, source_node); | ||
| 1847 | instruction->name = name; | ||
| 1848 | instruction->value = value; | ||
| 1849 | |||
| 1850 | ir_ref_instruction(name, ag->current_basic_block); | ||
| 1851 | ir_ref_instruction(value, ag->current_basic_block); | ||
| 1852 | |||
| 1853 | return &instruction->base; | ||
| 1854 | } | ||
| 1855 | |||
| 1856 | static IrInstSrc *ir_build_c_undef(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *name) { | ||
| 1857 | IrInstSrcCUndef *instruction = ir_build_instruction<IrInstSrcCUndef>(ag, scope, source_node); | ||
| 1858 | instruction->name = name; | ||
| 1859 | |||
| 1860 | ir_ref_instruction(name, ag->current_basic_block); | ||
| 1861 | |||
| 1862 | return &instruction->base; | ||
| 1863 | } | ||
| 1864 | |||
| 1865 | static IrInstSrc *ir_build_embed_file(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *name) { | ||
| 1866 | IrInstSrcEmbedFile *instruction = ir_build_instruction<IrInstSrcEmbedFile>(ag, scope, source_node); | ||
| 1867 | instruction->name = name; | ||
| 1868 | |||
| 1869 | ir_ref_instruction(name, ag->current_basic_block); | ||
| 1870 | |||
| 1871 | return &instruction->base; | ||
| 1872 | } | ||
| 1873 | |||
| 1874 | static IrInstSrc *ir_build_cmpxchg_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1875 | IrInstSrc *type_value, IrInstSrc *ptr, IrInstSrc *cmp_value, IrInstSrc *new_value, | ||
| 1876 | IrInstSrc *success_order_value, IrInstSrc *failure_order_value, bool is_weak, ResultLoc *result_loc) | ||
| 1877 | { | ||
| 1878 | IrInstSrcCmpxchg *instruction = ir_build_instruction<IrInstSrcCmpxchg>(ag, scope, source_node); | ||
| 1879 | instruction->type_value = type_value; | ||
| 1880 | instruction->ptr = ptr; | ||
| 1881 | instruction->cmp_value = cmp_value; | ||
| 1882 | instruction->new_value = new_value; | ||
| 1883 | instruction->success_order_value = success_order_value; | ||
| 1884 | instruction->failure_order_value = failure_order_value; | ||
| 1885 | instruction->is_weak = is_weak; | ||
| 1886 | instruction->result_loc = result_loc; | ||
| 1887 | |||
| 1888 | ir_ref_instruction(type_value, ag->current_basic_block); | ||
| 1889 | ir_ref_instruction(ptr, ag->current_basic_block); | ||
| 1890 | ir_ref_instruction(cmp_value, ag->current_basic_block); | ||
| 1891 | ir_ref_instruction(new_value, ag->current_basic_block); | ||
| 1892 | ir_ref_instruction(success_order_value, ag->current_basic_block); | ||
| 1893 | ir_ref_instruction(failure_order_value, ag->current_basic_block); | ||
| 1894 | |||
| 1895 | return &instruction->base; | ||
| 1896 | } | ||
| 1897 | |||
| 1898 | static IrInstSrc *ir_build_fence(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *order) { | ||
| 1899 | IrInstSrcFence *instruction = ir_build_instruction<IrInstSrcFence>(ag, scope, source_node); | ||
| 1900 | instruction->order = order; | ||
| 1901 | |||
| 1902 | ir_ref_instruction(order, ag->current_basic_block); | ||
| 1903 | |||
| 1904 | return &instruction->base; | ||
| 1905 | } | ||
| 1906 | |||
| 1907 | static IrInstSrc *ir_build_reduce(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *op, IrInstSrc *value) { | ||
| 1908 | IrInstSrcReduce *instruction = ir_build_instruction<IrInstSrcReduce>(ag, scope, source_node); | ||
| 1909 | instruction->op = op; | ||
| 1910 | instruction->value = value; | ||
| 1911 | |||
| 1912 | ir_ref_instruction(op, ag->current_basic_block); | ||
| 1913 | ir_ref_instruction(value, ag->current_basic_block); | ||
| 1914 | |||
| 1915 | return &instruction->base; | ||
| 1916 | } | ||
| 1917 | |||
| 1918 | static IrInstSrc *ir_build_truncate(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1919 | IrInstSrc *dest_type, IrInstSrc *target) | ||
| 1920 | { | ||
| 1921 | IrInstSrcTruncate *instruction = ir_build_instruction<IrInstSrcTruncate>(ag, scope, source_node); | ||
| 1922 | instruction->dest_type = dest_type; | ||
| 1923 | instruction->target = target; | ||
| 1924 | |||
| 1925 | ir_ref_instruction(dest_type, ag->current_basic_block); | ||
| 1926 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 1927 | |||
| 1928 | return &instruction->base; | ||
| 1929 | } | ||
| 1930 | |||
| 1931 | static IrInstSrc *ir_build_int_cast(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, | ||
| 1932 | IrInstSrc *target) | ||
| 1933 | { | ||
| 1934 | IrInstSrcIntCast *instruction = ir_build_instruction<IrInstSrcIntCast>(ag, scope, source_node); | ||
| 1935 | instruction->dest_type = dest_type; | ||
| 1936 | instruction->target = target; | ||
| 1937 | |||
| 1938 | ir_ref_instruction(dest_type, ag->current_basic_block); | ||
| 1939 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 1940 | |||
| 1941 | return &instruction->base; | ||
| 1942 | } | ||
| 1943 | |||
| 1944 | static IrInstSrc *ir_build_float_cast(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, | ||
| 1945 | IrInstSrc *target) | ||
| 1946 | { | ||
| 1947 | IrInstSrcFloatCast *instruction = ir_build_instruction<IrInstSrcFloatCast>(ag, scope, source_node); | ||
| 1948 | instruction->dest_type = dest_type; | ||
| 1949 | instruction->target = target; | ||
| 1950 | |||
| 1951 | ir_ref_instruction(dest_type, ag->current_basic_block); | ||
| 1952 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 1953 | |||
| 1954 | return &instruction->base; | ||
| 1955 | } | ||
| 1956 | |||
| 1957 | static IrInstSrc *ir_build_err_set_cast(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1958 | IrInstSrc *dest_type, IrInstSrc *target) | ||
| 1959 | { | ||
| 1960 | IrInstSrcErrSetCast *instruction = ir_build_instruction<IrInstSrcErrSetCast>(ag, scope, source_node); | ||
| 1961 | instruction->dest_type = dest_type; | ||
| 1962 | instruction->target = target; | ||
| 1963 | |||
| 1964 | ir_ref_instruction(dest_type, ag->current_basic_block); | ||
| 1965 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 1966 | |||
| 1967 | return &instruction->base; | ||
| 1968 | } | ||
| 1969 | |||
| 1970 | static IrInstSrc *ir_build_int_to_float(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1971 | IrInstSrc *dest_type, IrInstSrc *target) | ||
| 1972 | { | ||
| 1973 | IrInstSrcIntToFloat *instruction = ir_build_instruction<IrInstSrcIntToFloat>(ag, scope, source_node); | ||
| 1974 | instruction->dest_type = dest_type; | ||
| 1975 | instruction->target = target; | ||
| 1976 | |||
| 1977 | ir_ref_instruction(dest_type, ag->current_basic_block); | ||
| 1978 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 1979 | |||
| 1980 | return &instruction->base; | ||
| 1981 | } | ||
| 1982 | |||
| 1983 | static IrInstSrc *ir_build_float_to_int(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 1984 | IrInstSrc *dest_type, IrInstSrc *target) | ||
| 1985 | { | ||
| 1986 | IrInstSrcFloatToInt *instruction = ir_build_instruction<IrInstSrcFloatToInt>(ag, scope, source_node); | ||
| 1987 | instruction->dest_type = dest_type; | ||
| 1988 | instruction->target = target; | ||
| 1989 | |||
| 1990 | ir_ref_instruction(dest_type, ag->current_basic_block); | ||
| 1991 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 1992 | |||
| 1993 | return &instruction->base; | ||
| 1994 | } | ||
| 1995 | |||
| 1996 | static IrInstSrc *ir_build_bool_to_int(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *target) { | ||
| 1997 | IrInstSrcBoolToInt *instruction = ir_build_instruction<IrInstSrcBoolToInt>(ag, scope, source_node); | ||
| 1998 | instruction->target = target; | ||
| 1999 | |||
| 2000 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 2001 | |||
| 2002 | return &instruction->base; | ||
| 2003 | } | ||
| 2004 | |||
| 2005 | static IrInstSrc *ir_build_vector_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *len, | ||
| 2006 | IrInstSrc *elem_type) | ||
| 2007 | { | ||
| 2008 | IrInstSrcVectorType *instruction = ir_build_instruction<IrInstSrcVectorType>(ag, scope, source_node); | ||
| 2009 | instruction->len = len; | ||
| 2010 | instruction->elem_type = elem_type; | ||
| 2011 | |||
| 2012 | ir_ref_instruction(len, ag->current_basic_block); | ||
| 2013 | ir_ref_instruction(elem_type, ag->current_basic_block); | ||
| 2014 | |||
| 2015 | return &instruction->base; | ||
| 2016 | } | ||
| 2017 | |||
| 2018 | static IrInstSrc *ir_build_shuffle_vector(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2019 | IrInstSrc *scalar_type, IrInstSrc *a, IrInstSrc *b, IrInstSrc *mask) | ||
| 2020 | { | ||
| 2021 | IrInstSrcShuffleVector *instruction = ir_build_instruction<IrInstSrcShuffleVector>(ag, scope, source_node); | ||
| 2022 | instruction->scalar_type = scalar_type; | ||
| 2023 | instruction->a = a; | ||
| 2024 | instruction->b = b; | ||
| 2025 | instruction->mask = mask; | ||
| 2026 | |||
| 2027 | if (scalar_type != nullptr) ir_ref_instruction(scalar_type, ag->current_basic_block); | ||
| 2028 | ir_ref_instruction(a, ag->current_basic_block); | ||
| 2029 | ir_ref_instruction(b, ag->current_basic_block); | ||
| 2030 | ir_ref_instruction(mask, ag->current_basic_block); | ||
| 2031 | |||
| 2032 | return &instruction->base; | ||
| 2033 | } | ||
| 2034 | |||
| 2035 | static IrInstSrc *ir_build_splat_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2036 | IrInstSrc *len, IrInstSrc *scalar) | ||
| 2037 | { | ||
| 2038 | IrInstSrcSplat *instruction = ir_build_instruction<IrInstSrcSplat>(ag, scope, source_node); | ||
| 2039 | instruction->len = len; | ||
| 2040 | instruction->scalar = scalar; | ||
| 2041 | |||
| 2042 | ir_ref_instruction(len, ag->current_basic_block); | ||
| 2043 | ir_ref_instruction(scalar, ag->current_basic_block); | ||
| 2044 | |||
| 2045 | return &instruction->base; | ||
| 2046 | } | ||
| 2047 | |||
| 2048 | static IrInstSrc *ir_build_bool_not(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *value) { | ||
| 2049 | IrInstSrcBoolNot *instruction = ir_build_instruction<IrInstSrcBoolNot>(ag, scope, source_node); | ||
| 2050 | instruction->value = value; | ||
| 2051 | |||
| 2052 | ir_ref_instruction(value, ag->current_basic_block); | ||
| 2053 | |||
| 2054 | return &instruction->base; | ||
| 2055 | } | ||
| 2056 | |||
| 2057 | static IrInstSrc *ir_build_memset_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2058 | IrInstSrc *dest_ptr, IrInstSrc *byte, IrInstSrc *count) | ||
| 2059 | { | ||
| 2060 | IrInstSrcMemset *instruction = ir_build_instruction<IrInstSrcMemset>(ag, scope, source_node); | ||
| 2061 | instruction->dest_ptr = dest_ptr; | ||
| 2062 | instruction->byte = byte; | ||
| 2063 | instruction->count = count; | ||
| 2064 | |||
| 2065 | ir_ref_instruction(dest_ptr, ag->current_basic_block); | ||
| 2066 | ir_ref_instruction(byte, ag->current_basic_block); | ||
| 2067 | ir_ref_instruction(count, ag->current_basic_block); | ||
| 2068 | |||
| 2069 | return &instruction->base; | ||
| 2070 | } | ||
| 2071 | |||
| 2072 | static IrInstSrc *ir_build_memcpy_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2073 | IrInstSrc *dest_ptr, IrInstSrc *src_ptr, IrInstSrc *count) | ||
| 2074 | { | ||
| 2075 | IrInstSrcMemcpy *instruction = ir_build_instruction<IrInstSrcMemcpy>(ag, scope, source_node); | ||
| 2076 | instruction->dest_ptr = dest_ptr; | ||
| 2077 | instruction->src_ptr = src_ptr; | ||
| 2078 | instruction->count = count; | ||
| 2079 | |||
| 2080 | ir_ref_instruction(dest_ptr, ag->current_basic_block); | ||
| 2081 | ir_ref_instruction(src_ptr, ag->current_basic_block); | ||
| 2082 | ir_ref_instruction(count, ag->current_basic_block); | ||
| 2083 | |||
| 2084 | return &instruction->base; | ||
| 2085 | } | ||
| 2086 | |||
| 2087 | static IrInstSrc *ir_build_slice_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2088 | IrInstSrc *ptr, IrInstSrc *start, IrInstSrc *end, IrInstSrc *sentinel, | ||
| 2089 | bool safety_check_on, ResultLoc *result_loc) | ||
| 2090 | { | ||
| 2091 | IrInstSrcSlice *instruction = ir_build_instruction<IrInstSrcSlice>(ag, scope, source_node); | ||
| 2092 | instruction->ptr = ptr; | ||
| 2093 | instruction->start = start; | ||
| 2094 | instruction->end = end; | ||
| 2095 | instruction->sentinel = sentinel; | ||
| 2096 | instruction->safety_check_on = safety_check_on; | ||
| 2097 | instruction->result_loc = result_loc; | ||
| 2098 | |||
| 2099 | ir_ref_instruction(ptr, ag->current_basic_block); | ||
| 2100 | ir_ref_instruction(start, ag->current_basic_block); | ||
| 2101 | if (end) ir_ref_instruction(end, ag->current_basic_block); | ||
| 2102 | if (sentinel) ir_ref_instruction(sentinel, ag->current_basic_block); | ||
| 2103 | |||
| 2104 | return &instruction->base; | ||
| 2105 | } | ||
| 2106 | |||
| 2107 | static IrInstSrc *ir_build_breakpoint(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | ||
| 2108 | IrInstSrcBreakpoint *instruction = ir_build_instruction<IrInstSrcBreakpoint>(ag, scope, source_node); | ||
| 2109 | return &instruction->base; | ||
| 2110 | } | ||
| 2111 | |||
| 2112 | static IrInstSrc *ir_build_return_address_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | ||
| 2113 | IrInstSrcReturnAddress *instruction = ir_build_instruction<IrInstSrcReturnAddress>(ag, scope, source_node); | ||
| 2114 | return &instruction->base; | ||
| 2115 | } | ||
| 2116 | |||
| 2117 | static IrInstSrc *ir_build_frame_address_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | ||
| 2118 | IrInstSrcFrameAddress *inst = ir_build_instruction<IrInstSrcFrameAddress>(ag, scope, source_node); | ||
| 2119 | return &inst->base; | ||
| 2120 | } | ||
| 2121 | |||
| 2122 | static IrInstSrc *ir_build_handle_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | ||
| 2123 | IrInstSrcFrameHandle *inst = ir_build_instruction<IrInstSrcFrameHandle>(ag, scope, source_node); | ||
| 2124 | return &inst->base; | ||
| 2125 | } | ||
| 2126 | |||
| 2127 | static IrInstSrc *ir_build_frame_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *fn) { | ||
| 2128 | IrInstSrcFrameType *inst = ir_build_instruction<IrInstSrcFrameType>(ag, scope, source_node); | ||
| 2129 | inst->fn = fn; | ||
| 2130 | |||
| 2131 | ir_ref_instruction(fn, ag->current_basic_block); | ||
| 2132 | |||
| 2133 | return &inst->base; | ||
| 2134 | } | ||
| 2135 | |||
| 2136 | static IrInstSrc *ir_build_frame_size_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *fn) { | ||
| 2137 | IrInstSrcFrameSize *inst = ir_build_instruction<IrInstSrcFrameSize>(ag, scope, source_node); | ||
| 2138 | inst->fn = fn; | ||
| 2139 | |||
| 2140 | ir_ref_instruction(fn, ag->current_basic_block); | ||
| 2141 | |||
| 2142 | return &inst->base; | ||
| 2143 | } | ||
| 2144 | |||
| 2145 | static IrInstSrc *ir_build_overflow_op_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2146 | IrOverflowOp op, IrInstSrc *type_value, IrInstSrc *op1, IrInstSrc *op2, IrInstSrc *result_ptr) | ||
| 2147 | { | ||
| 2148 | IrInstSrcOverflowOp *instruction = ir_build_instruction<IrInstSrcOverflowOp>(ag, scope, source_node); | ||
| 2149 | instruction->op = op; | ||
| 2150 | instruction->type_value = type_value; | ||
| 2151 | instruction->op1 = op1; | ||
| 2152 | instruction->op2 = op2; | ||
| 2153 | instruction->result_ptr = result_ptr; | ||
| 2154 | |||
| 2155 | ir_ref_instruction(type_value, ag->current_basic_block); | ||
| 2156 | ir_ref_instruction(op1, ag->current_basic_block); | ||
| 2157 | ir_ref_instruction(op2, ag->current_basic_block); | ||
| 2158 | ir_ref_instruction(result_ptr, ag->current_basic_block); | ||
| 2159 | |||
| 2160 | return &instruction->base; | ||
| 2161 | } | ||
| 2162 | |||
| 2163 | static IrInstSrc *ir_build_float_op_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *operand, | ||
| 2164 | BuiltinFnId fn_id) | ||
| 2165 | { | ||
| 2166 | IrInstSrcFloatOp *instruction = ir_build_instruction<IrInstSrcFloatOp>(ag, scope, source_node); | ||
| 2167 | instruction->operand = operand; | ||
| 2168 | instruction->fn_id = fn_id; | ||
| 2169 | |||
| 2170 | ir_ref_instruction(operand, ag->current_basic_block); | ||
| 2171 | |||
| 2172 | return &instruction->base; | ||
| 2173 | } | ||
| 2174 | |||
| 2175 | static IrInstSrc *ir_build_mul_add_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2176 | IrInstSrc *type_value, IrInstSrc *op1, IrInstSrc *op2, IrInstSrc *op3) | ||
| 2177 | { | ||
| 2178 | IrInstSrcMulAdd *instruction = ir_build_instruction<IrInstSrcMulAdd>(ag, scope, source_node); | ||
| 2179 | instruction->type_value = type_value; | ||
| 2180 | instruction->op1 = op1; | ||
| 2181 | instruction->op2 = op2; | ||
| 2182 | instruction->op3 = op3; | ||
| 2183 | |||
| 2184 | ir_ref_instruction(type_value, ag->current_basic_block); | ||
| 2185 | ir_ref_instruction(op1, ag->current_basic_block); | ||
| 2186 | ir_ref_instruction(op2, ag->current_basic_block); | ||
| 2187 | ir_ref_instruction(op3, ag->current_basic_block); | ||
| 2188 | |||
| 2189 | return &instruction->base; | ||
| 2190 | } | ||
| 2191 | |||
| 2192 | static IrInstSrc *ir_build_align_of(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { | ||
| 2193 | IrInstSrcAlignOf *instruction = ir_build_instruction<IrInstSrcAlignOf>(ag, scope, source_node); | ||
| 2194 | instruction->type_value = type_value; | ||
| 2195 | |||
| 2196 | ir_ref_instruction(type_value, ag->current_basic_block); | ||
| 2197 | |||
| 2198 | return &instruction->base; | ||
| 2199 | } | ||
| 2200 | |||
| 2201 | static IrInstSrc *ir_build_test_err_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2202 | IrInstSrc *base_ptr, bool resolve_err_set, bool base_ptr_is_payload) | ||
| 2203 | { | ||
| 2204 | IrInstSrcTestErr *instruction = ir_build_instruction<IrInstSrcTestErr>(ag, scope, source_node); | ||
| 2205 | instruction->base_ptr = base_ptr; | ||
| 2206 | instruction->resolve_err_set = resolve_err_set; | ||
| 2207 | instruction->base_ptr_is_payload = base_ptr_is_payload; | ||
| 2208 | |||
| 2209 | ir_ref_instruction(base_ptr, ag->current_basic_block); | ||
| 2210 | |||
| 2211 | return &instruction->base; | ||
| 2212 | } | ||
| 2213 | |||
| 2214 | static IrInstSrc *ir_build_unwrap_err_code_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2215 | IrInstSrc *err_union_ptr) | ||
| 2216 | { | ||
| 2217 | IrInstSrcUnwrapErrCode *inst = ir_build_instruction<IrInstSrcUnwrapErrCode>(ag, scope, source_node); | ||
| 2218 | inst->err_union_ptr = err_union_ptr; | ||
| 2219 | |||
| 2220 | ir_ref_instruction(err_union_ptr, ag->current_basic_block); | ||
| 2221 | |||
| 2222 | return &inst->base; | ||
| 2223 | } | ||
| 2224 | |||
| 2225 | static IrInstSrc *ir_build_unwrap_err_payload_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2226 | IrInstSrc *value, bool safety_check_on, bool initializing) | ||
| 2227 | { | ||
| 2228 | IrInstSrcUnwrapErrPayload *inst = ir_build_instruction<IrInstSrcUnwrapErrPayload>(ag, scope, source_node); | ||
| 2229 | inst->value = value; | ||
| 2230 | inst->safety_check_on = safety_check_on; | ||
| 2231 | inst->initializing = initializing; | ||
| 2232 | |||
| 2233 | ir_ref_instruction(value, ag->current_basic_block); | ||
| 2234 | |||
| 2235 | return &inst->base; | ||
| 2236 | } | ||
| 2237 | |||
| 2238 | static IrInstSrc *ir_build_fn_proto(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2239 | IrInstSrc **param_types, IrInstSrc *align_value, IrInstSrc *callconv_value, | ||
| 2240 | IrInstSrc *return_type, bool is_var_args) | ||
| 2241 | { | ||
| 2242 | IrInstSrcFnProto *instruction = ir_build_instruction<IrInstSrcFnProto>(ag, scope, source_node); | ||
| 2243 | instruction->param_types = param_types; | ||
| 2244 | instruction->align_value = align_value; | ||
| 2245 | instruction->callconv_value = callconv_value; | ||
| 2246 | instruction->return_type = return_type; | ||
| 2247 | instruction->is_var_args = is_var_args; | ||
| 2248 | |||
| 2249 | assert(source_node->type == NodeTypeFnProto); | ||
| 2250 | size_t param_count = source_node->data.fn_proto.params.length; | ||
| 2251 | if (is_var_args) param_count -= 1; | ||
| 2252 | for (size_t i = 0; i < param_count; i += 1) { | ||
| 2253 | if (param_types[i] != nullptr) ir_ref_instruction(param_types[i], ag->current_basic_block); | ||
| 2254 | } | ||
| 2255 | if (align_value != nullptr) ir_ref_instruction(align_value, ag->current_basic_block); | ||
| 2256 | if (callconv_value != nullptr) ir_ref_instruction(callconv_value, ag->current_basic_block); | ||
| 2257 | ir_ref_instruction(return_type, ag->current_basic_block); | ||
| 2258 | |||
| 2259 | return &instruction->base; | ||
| 2260 | } | ||
| 2261 | |||
| 2262 | static IrInstSrc *ir_build_test_comptime(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *value) { | ||
| 2263 | IrInstSrcTestComptime *instruction = ir_build_instruction<IrInstSrcTestComptime>(ag, scope, source_node); | ||
| 2264 | instruction->value = value; | ||
| 2265 | |||
| 2266 | ir_ref_instruction(value, ag->current_basic_block); | ||
| 2267 | |||
| 2268 | return &instruction->base; | ||
| 2269 | } | ||
| 2270 | |||
| 2271 | static IrInstSrc *ir_build_ptr_cast_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2272 | IrInstSrc *dest_type, IrInstSrc *ptr, bool safety_check_on) | ||
| 2273 | { | ||
| 2274 | IrInstSrcPtrCast *instruction = ir_build_instruction<IrInstSrcPtrCast>( | ||
| 2275 | ag, scope, source_node); | ||
| 2276 | instruction->dest_type = dest_type; | ||
| 2277 | instruction->ptr = ptr; | ||
| 2278 | instruction->safety_check_on = safety_check_on; | ||
| 2279 | |||
| 2280 | ir_ref_instruction(dest_type, ag->current_basic_block); | ||
| 2281 | ir_ref_instruction(ptr, ag->current_basic_block); | ||
| 2282 | |||
| 2283 | return &instruction->base; | ||
| 2284 | } | ||
| 2285 | |||
| 2286 | static IrInstSrc *ir_build_implicit_cast(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2287 | IrInstSrc *operand, ResultLocCast *result_loc_cast) | ||
| 2288 | { | ||
| 2289 | IrInstSrcImplicitCast *instruction = ir_build_instruction<IrInstSrcImplicitCast>(ag, scope, source_node); | ||
| 2290 | instruction->operand = operand; | ||
| 2291 | instruction->result_loc_cast = result_loc_cast; | ||
| 2292 | |||
| 2293 | ir_ref_instruction(operand, ag->current_basic_block); | ||
| 2294 | |||
| 2295 | return &instruction->base; | ||
| 2296 | } | ||
| 2297 | |||
| 2298 | static IrInstSrc *ir_build_bit_cast_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2299 | IrInstSrc *operand, ResultLocBitCast *result_loc_bit_cast) | ||
| 2300 | { | ||
| 2301 | IrInstSrcBitCast *instruction = ir_build_instruction<IrInstSrcBitCast>(ag, scope, source_node); | ||
| 2302 | instruction->operand = operand; | ||
| 2303 | instruction->result_loc_bit_cast = result_loc_bit_cast; | ||
| 2304 | |||
| 2305 | ir_ref_instruction(operand, ag->current_basic_block); | ||
| 2306 | |||
| 2307 | return &instruction->base; | ||
| 2308 | } | ||
| 2309 | |||
| 2310 | static IrInstSrc *ir_build_int_to_ptr_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2311 | IrInstSrc *dest_type, IrInstSrc *target) | ||
| 2312 | { | ||
| 2313 | IrInstSrcIntToPtr *instruction = ir_build_instruction<IrInstSrcIntToPtr>(ag, scope, source_node); | ||
| 2314 | instruction->dest_type = dest_type; | ||
| 2315 | instruction->target = target; | ||
| 2316 | |||
| 2317 | ir_ref_instruction(dest_type, ag->current_basic_block); | ||
| 2318 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 2319 | |||
| 2320 | return &instruction->base; | ||
| 2321 | } | ||
| 2322 | |||
| 2323 | static IrInstSrc *ir_build_ptr_to_int_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2324 | IrInstSrc *target) | ||
| 2325 | { | ||
| 2326 | IrInstSrcPtrToInt *inst = ir_build_instruction<IrInstSrcPtrToInt>(ag, scope, source_node); | ||
| 2327 | inst->target = target; | ||
| 2328 | |||
| 2329 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 2330 | |||
| 2331 | return &inst->base; | ||
| 2332 | } | ||
| 2333 | |||
| 2334 | static IrInstSrc *ir_build_int_to_enum_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2335 | IrInstSrc *dest_type, IrInstSrc *target) | ||
| 2336 | { | ||
| 2337 | IrInstSrcIntToEnum *instruction = ir_build_instruction<IrInstSrcIntToEnum>(ag, scope, source_node); | ||
| 2338 | instruction->dest_type = dest_type; | ||
| 2339 | instruction->target = target; | ||
| 2340 | |||
| 2341 | if (dest_type) ir_ref_instruction(dest_type, ag->current_basic_block); | ||
| 2342 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 2343 | |||
| 2344 | return &instruction->base; | ||
| 2345 | } | ||
| 2346 | |||
| 2347 | static IrInstSrc *ir_build_enum_to_int(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2348 | IrInstSrc *target) | ||
| 2349 | { | ||
| 2350 | IrInstSrcEnumToInt *instruction = ir_build_instruction<IrInstSrcEnumToInt>( | ||
| 2351 | ag, scope, source_node); | ||
| 2352 | instruction->target = target; | ||
| 2353 | |||
| 2354 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 2355 | |||
| 2356 | return &instruction->base; | ||
| 2357 | } | ||
| 2358 | |||
| 2359 | static IrInstSrc *ir_build_int_to_err_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2360 | IrInstSrc *target) | ||
| 2361 | { | ||
| 2362 | IrInstSrcIntToErr *instruction = ir_build_instruction<IrInstSrcIntToErr>(ag, scope, source_node); | ||
| 2363 | instruction->target = target; | ||
| 2364 | |||
| 2365 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 2366 | |||
| 2367 | return &instruction->base; | ||
| 2368 | } | ||
| 2369 | |||
| 2370 | static IrInstSrc *ir_build_err_to_int_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2371 | IrInstSrc *target) | ||
| 2372 | { | ||
| 2373 | IrInstSrcErrToInt *instruction = ir_build_instruction<IrInstSrcErrToInt>( | ||
| 2374 | ag, scope, source_node); | ||
| 2375 | instruction->target = target; | ||
| 2376 | |||
| 2377 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 2378 | |||
| 2379 | return &instruction->base; | ||
| 2380 | } | ||
| 2381 | |||
| 2382 | static IrInstSrc *ir_build_check_switch_prongs(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2383 | IrInstSrc *target_value, IrInstSrcCheckSwitchProngsRange *ranges, size_t range_count, | ||
| 2384 | AstNode* else_prong, bool have_underscore_prong) | ||
| 2385 | { | ||
| 2386 | IrInstSrcCheckSwitchProngs *instruction = heap::c_allocator.create<IrInstSrcCheckSwitchProngs>(); | ||
| 2387 | instruction->base.id = have_underscore_prong ? | ||
| 2388 | IrInstSrcIdCheckSwitchProngsUnderYes : IrInstSrcIdCheckSwitchProngsUnderNo; | ||
| 2389 | instruction->base.base.scope = scope; | ||
| 2390 | instruction->base.base.source_node = source_node; | ||
| 2391 | instruction->base.base.debug_id = irb_next_debug_id(ag); | ||
| 2392 | instruction->base.owner_bb = ag->current_basic_block; | ||
| 2393 | ir_instruction_append(ag->current_basic_block, &instruction->base); | ||
| 2394 | |||
| 2395 | instruction->target_value = target_value; | ||
| 2396 | instruction->ranges = ranges; | ||
| 2397 | instruction->range_count = range_count; | ||
| 2398 | instruction->else_prong = else_prong; | ||
| 2399 | |||
| 2400 | ir_ref_instruction(target_value, ag->current_basic_block); | ||
| 2401 | for (size_t i = 0; i < range_count; i += 1) { | ||
| 2402 | ir_ref_instruction(ranges[i].start, ag->current_basic_block); | ||
| 2403 | ir_ref_instruction(ranges[i].end, ag->current_basic_block); | ||
| 2404 | } | ||
| 2405 | |||
| 2406 | return &instruction->base; | ||
| 2407 | } | ||
| 2408 | |||
| 2409 | static IrInstSrc *ir_build_check_statement_is_void(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2410 | IrInstSrc* statement_value) | ||
| 2411 | { | ||
| 2412 | IrInstSrcCheckStatementIsVoid *instruction = ir_build_instruction<IrInstSrcCheckStatementIsVoid>( | ||
| 2413 | ag, scope, source_node); | ||
| 2414 | instruction->statement_value = statement_value; | ||
| 2415 | |||
| 2416 | ir_ref_instruction(statement_value, ag->current_basic_block); | ||
| 2417 | |||
| 2418 | return &instruction->base; | ||
| 2419 | } | ||
| 2420 | |||
| 2421 | static IrInstSrc *ir_build_type_name(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2422 | IrInstSrc *type_value) | ||
| 2423 | { | ||
| 2424 | IrInstSrcTypeName *instruction = ir_build_instruction<IrInstSrcTypeName>(ag, scope, source_node); | ||
| 2425 | instruction->type_value = type_value; | ||
| 2426 | |||
| 2427 | ir_ref_instruction(type_value, ag->current_basic_block); | ||
| 2428 | |||
| 2429 | return &instruction->base; | ||
| 2430 | } | ||
| 2431 | |||
| 2432 | static IrInstSrc *ir_build_decl_ref(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Tld *tld, LVal lval) { | ||
| 2433 | IrInstSrcDeclRef *instruction = ir_build_instruction<IrInstSrcDeclRef>(ag, scope, source_node); | ||
| 2434 | instruction->tld = tld; | ||
| 2435 | instruction->lval = lval; | ||
| 2436 | |||
| 2437 | return &instruction->base; | ||
| 2438 | } | ||
| 2439 | |||
| 2440 | static IrInstSrc *ir_build_panic_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *msg) { | ||
| 2441 | IrInstSrcPanic *instruction = ir_build_instruction<IrInstSrcPanic>(ag, scope, source_node); | ||
| 2442 | instruction->base.is_noreturn = true; | ||
| 2443 | instruction->msg = msg; | ||
| 2444 | |||
| 2445 | ir_ref_instruction(msg, ag->current_basic_block); | ||
| 2446 | |||
| 2447 | return &instruction->base; | ||
| 2448 | } | ||
| 2449 | |||
| 2450 | static IrInstSrc *ir_build_tag_name_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *target) { | ||
| 2451 | IrInstSrcTagName *instruction = ir_build_instruction<IrInstSrcTagName>(ag, scope, source_node); | ||
| 2452 | instruction->target = target; | ||
| 2453 | |||
| 2454 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 2455 | |||
| 2456 | return &instruction->base; | ||
| 2457 | } | ||
| 2458 | |||
| 2459 | static IrInstSrc *ir_build_field_parent_ptr_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2460 | IrInstSrc *type_value, IrInstSrc *field_name, IrInstSrc *field_ptr) | ||
| 2461 | { | ||
| 2462 | IrInstSrcFieldParentPtr *inst = ir_build_instruction<IrInstSrcFieldParentPtr>( | ||
| 2463 | ag, scope, source_node); | ||
| 2464 | inst->type_value = type_value; | ||
| 2465 | inst->field_name = field_name; | ||
| 2466 | inst->field_ptr = field_ptr; | ||
| 2467 | |||
| 2468 | ir_ref_instruction(type_value, ag->current_basic_block); | ||
| 2469 | ir_ref_instruction(field_name, ag->current_basic_block); | ||
| 2470 | ir_ref_instruction(field_ptr, ag->current_basic_block); | ||
| 2471 | |||
| 2472 | return &inst->base; | ||
| 2473 | } | ||
| 2474 | |||
| 2475 | static IrInstSrc *ir_build_byte_offset_of(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2476 | IrInstSrc *type_value, IrInstSrc *field_name) | ||
| 2477 | { | ||
| 2478 | IrInstSrcByteOffsetOf *instruction = ir_build_instruction<IrInstSrcByteOffsetOf>(ag, scope, source_node); | ||
| 2479 | instruction->type_value = type_value; | ||
| 2480 | instruction->field_name = field_name; | ||
| 2481 | |||
| 2482 | ir_ref_instruction(type_value, ag->current_basic_block); | ||
| 2483 | ir_ref_instruction(field_name, ag->current_basic_block); | ||
| 2484 | |||
| 2485 | return &instruction->base; | ||
| 2486 | } | ||
| 2487 | |||
| 2488 | static IrInstSrc *ir_build_bit_offset_of(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2489 | IrInstSrc *type_value, IrInstSrc *field_name) | ||
| 2490 | { | ||
| 2491 | IrInstSrcBitOffsetOf *instruction = ir_build_instruction<IrInstSrcBitOffsetOf>(ag, scope, source_node); | ||
| 2492 | instruction->type_value = type_value; | ||
| 2493 | instruction->field_name = field_name; | ||
| 2494 | |||
| 2495 | ir_ref_instruction(type_value, ag->current_basic_block); | ||
| 2496 | ir_ref_instruction(field_name, ag->current_basic_block); | ||
| 2497 | |||
| 2498 | return &instruction->base; | ||
| 2499 | } | ||
| 2500 | |||
| 2501 | static IrInstSrc *ir_build_type_info(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { | ||
| 2502 | IrInstSrcTypeInfo *instruction = ir_build_instruction<IrInstSrcTypeInfo>(ag, scope, source_node); | ||
| 2503 | instruction->type_value = type_value; | ||
| 2504 | |||
| 2505 | ir_ref_instruction(type_value, ag->current_basic_block); | ||
| 2506 | |||
| 2507 | return &instruction->base; | ||
| 2508 | } | ||
| 2509 | |||
| 2510 | static IrInstSrc *ir_build_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *type_info) { | ||
| 2511 | IrInstSrcType *instruction = ir_build_instruction<IrInstSrcType>(ag, scope, source_node); | ||
| 2512 | instruction->type_info = type_info; | ||
| 2513 | |||
| 2514 | ir_ref_instruction(type_info, ag->current_basic_block); | ||
| 2515 | |||
| 2516 | return &instruction->base; | ||
| 2517 | } | ||
| 2518 | |||
| 2519 | static IrInstSrc *ir_build_set_eval_branch_quota(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2520 | IrInstSrc *new_quota) | ||
| 2521 | { | ||
| 2522 | IrInstSrcSetEvalBranchQuota *instruction = ir_build_instruction<IrInstSrcSetEvalBranchQuota>(ag, scope, source_node); | ||
| 2523 | instruction->new_quota = new_quota; | ||
| 2524 | |||
| 2525 | ir_ref_instruction(new_quota, ag->current_basic_block); | ||
| 2526 | |||
| 2527 | return &instruction->base; | ||
| 2528 | } | ||
| 2529 | |||
| 2530 | static IrInstSrc *ir_build_align_cast_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2531 | IrInstSrc *align_bytes, IrInstSrc *target) | ||
| 2532 | { | ||
| 2533 | IrInstSrcAlignCast *instruction = ir_build_instruction<IrInstSrcAlignCast>(ag, scope, source_node); | ||
| 2534 | instruction->align_bytes = align_bytes; | ||
| 2535 | instruction->target = target; | ||
| 2536 | |||
| 2537 | ir_ref_instruction(align_bytes, ag->current_basic_block); | ||
| 2538 | ir_ref_instruction(target, ag->current_basic_block); | ||
| 2539 | |||
| 2540 | return &instruction->base; | ||
| 2541 | } | ||
| 2542 | |||
| 2543 | static IrInstSrc *ir_build_resolve_result(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2544 | ResultLoc *result_loc, IrInstSrc *ty) | ||
| 2545 | { | ||
| 2546 | IrInstSrcResolveResult *instruction = ir_build_instruction<IrInstSrcResolveResult>(ag, scope, source_node); | ||
| 2547 | instruction->result_loc = result_loc; | ||
| 2548 | instruction->ty = ty; | ||
| 2549 | |||
| 2550 | if (ty != nullptr) ir_ref_instruction(ty, ag->current_basic_block); | ||
| 2551 | |||
| 2552 | return &instruction->base; | ||
| 2553 | } | ||
| 2554 | |||
| 2555 | static IrInstSrc *ir_build_reset_result(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2556 | ResultLoc *result_loc) | ||
| 2557 | { | ||
| 2558 | IrInstSrcResetResult *instruction = ir_build_instruction<IrInstSrcResetResult>(ag, scope, source_node); | ||
| 2559 | instruction->result_loc = result_loc; | ||
| 2560 | instruction->base.is_gen = true; | ||
| 2561 | |||
| 2562 | return &instruction->base; | ||
| 2563 | } | ||
| 2564 | |||
| 2565 | static IrInstSrc *ir_build_set_align_stack(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2566 | IrInstSrc *align_bytes) | ||
| 2567 | { | ||
| 2568 | IrInstSrcSetAlignStack *instruction = ir_build_instruction<IrInstSrcSetAlignStack>(ag, scope, source_node); | ||
| 2569 | instruction->align_bytes = align_bytes; | ||
| 2570 | |||
| 2571 | ir_ref_instruction(align_bytes, ag->current_basic_block); | ||
| 2572 | |||
| 2573 | return &instruction->base; | ||
| 2574 | } | ||
| 2575 | |||
| 2576 | static IrInstSrc *ir_build_arg_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2577 | IrInstSrc *fn_type, IrInstSrc *arg_index, bool allow_var) | ||
| 2578 | { | ||
| 2579 | IrInstSrcArgType *instruction = heap::c_allocator.create<IrInstSrcArgType>(); | ||
| 2580 | instruction->base.id = allow_var ? | ||
| 2581 | IrInstSrcIdArgTypeAllowVarTrue : IrInstSrcIdArgTypeAllowVarFalse; | ||
| 2582 | instruction->base.base.scope = scope; | ||
| 2583 | instruction->base.base.source_node = source_node; | ||
| 2584 | instruction->base.base.debug_id = irb_next_debug_id(ag); | ||
| 2585 | instruction->base.owner_bb = ag->current_basic_block; | ||
| 2586 | ir_instruction_append(ag->current_basic_block, &instruction->base); | ||
| 2587 | |||
| 2588 | instruction->fn_type = fn_type; | ||
| 2589 | instruction->arg_index = arg_index; | ||
| 2590 | |||
| 2591 | ir_ref_instruction(fn_type, ag->current_basic_block); | ||
| 2592 | ir_ref_instruction(arg_index, ag->current_basic_block); | ||
| 2593 | |||
| 2594 | return &instruction->base; | ||
| 2595 | } | ||
| 2596 | |||
| 2597 | static IrInstSrc *ir_build_error_return_trace_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2598 | IrInstErrorReturnTraceOptional optional) | ||
| 2599 | { | ||
| 2600 | IrInstSrcErrorReturnTrace *inst = ir_build_instruction<IrInstSrcErrorReturnTrace>(ag, scope, source_node); | ||
| 2601 | inst->optional = optional; | ||
| 2602 | |||
| 2603 | return &inst->base; | ||
| 2604 | } | ||
| 2605 | |||
| 2606 | static IrInstSrc *ir_build_error_union(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2607 | IrInstSrc *err_set, IrInstSrc *payload) | ||
| 2608 | { | ||
| 2609 | IrInstSrcErrorUnion *instruction = ir_build_instruction<IrInstSrcErrorUnion>(ag, scope, source_node); | ||
| 2610 | instruction->err_set = err_set; | ||
| 2611 | instruction->payload = payload; | ||
| 2612 | |||
| 2613 | ir_ref_instruction(err_set, ag->current_basic_block); | ||
| 2614 | ir_ref_instruction(payload, ag->current_basic_block); | ||
| 2615 | |||
| 2616 | return &instruction->base; | ||
| 2617 | } | ||
| 2618 | |||
| 2619 | static IrInstSrc *ir_build_atomic_rmw_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2620 | IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *op, IrInstSrc *operand, | ||
| 2621 | IrInstSrc *ordering) | ||
| 2622 | { | ||
| 2623 | IrInstSrcAtomicRmw *instruction = ir_build_instruction<IrInstSrcAtomicRmw>(ag, scope, source_node); | ||
| 2624 | instruction->operand_type = operand_type; | ||
| 2625 | instruction->ptr = ptr; | ||
| 2626 | instruction->op = op; | ||
| 2627 | instruction->operand = operand; | ||
| 2628 | instruction->ordering = ordering; | ||
| 2629 | |||
| 2630 | ir_ref_instruction(operand_type, ag->current_basic_block); | ||
| 2631 | ir_ref_instruction(ptr, ag->current_basic_block); | ||
| 2632 | ir_ref_instruction(op, ag->current_basic_block); | ||
| 2633 | ir_ref_instruction(operand, ag->current_basic_block); | ||
| 2634 | ir_ref_instruction(ordering, ag->current_basic_block); | ||
| 2635 | |||
| 2636 | return &instruction->base; | ||
| 2637 | } | ||
| 2638 | |||
| 2639 | static IrInstSrc *ir_build_atomic_load_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2640 | IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *ordering) | ||
| 2641 | { | ||
| 2642 | IrInstSrcAtomicLoad *instruction = ir_build_instruction<IrInstSrcAtomicLoad>(ag, scope, source_node); | ||
| 2643 | instruction->operand_type = operand_type; | ||
| 2644 | instruction->ptr = ptr; | ||
| 2645 | instruction->ordering = ordering; | ||
| 2646 | |||
| 2647 | ir_ref_instruction(operand_type, ag->current_basic_block); | ||
| 2648 | ir_ref_instruction(ptr, ag->current_basic_block); | ||
| 2649 | ir_ref_instruction(ordering, ag->current_basic_block); | ||
| 2650 | |||
| 2651 | return &instruction->base; | ||
| 2652 | } | ||
| 2653 | |||
| 2654 | static IrInstSrc *ir_build_atomic_store_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2655 | IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *value, IrInstSrc *ordering) | ||
| 2656 | { | ||
| 2657 | IrInstSrcAtomicStore *instruction = ir_build_instruction<IrInstSrcAtomicStore>(ag, scope, source_node); | ||
| 2658 | instruction->operand_type = operand_type; | ||
| 2659 | instruction->ptr = ptr; | ||
| 2660 | instruction->value = value; | ||
| 2661 | instruction->ordering = ordering; | ||
| 2662 | |||
| 2663 | ir_ref_instruction(operand_type, ag->current_basic_block); | ||
| 2664 | ir_ref_instruction(ptr, ag->current_basic_block); | ||
| 2665 | ir_ref_instruction(value, ag->current_basic_block); | ||
| 2666 | ir_ref_instruction(ordering, ag->current_basic_block); | ||
| 2667 | |||
| 2668 | return &instruction->base; | ||
| 2669 | } | ||
| 2670 | |||
| 2671 | static IrInstSrc *ir_build_save_err_ret_addr_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | ||
| 2672 | IrInstSrcSaveErrRetAddr *inst = ir_build_instruction<IrInstSrcSaveErrRetAddr>(ag, scope, source_node); | ||
| 2673 | return &inst->base; | ||
| 2674 | } | ||
| 2675 | |||
| 2676 | static IrInstSrc *ir_build_add_implicit_return_type(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2677 | IrInstSrc *value, ResultLocReturn *result_loc_ret) | ||
| 2678 | { | ||
| 2679 | IrInstSrcAddImplicitReturnType *inst = ir_build_instruction<IrInstSrcAddImplicitReturnType>(ag, scope, source_node); | ||
| 2680 | inst->value = value; | ||
| 2681 | inst->result_loc_ret = result_loc_ret; | ||
| 2682 | |||
| 2683 | ir_ref_instruction(value, ag->current_basic_block); | ||
| 2684 | |||
| 2685 | return &inst->base; | ||
| 2686 | } | ||
| 2687 | |||
| 2688 | static IrInstSrc *ir_build_has_decl(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2689 | IrInstSrc *container, IrInstSrc *name) | ||
| 2690 | { | ||
| 2691 | IrInstSrcHasDecl *instruction = ir_build_instruction<IrInstSrcHasDecl>(ag, scope, source_node); | ||
| 2692 | instruction->container = container; | ||
| 2693 | instruction->name = name; | ||
| 2694 | |||
| 2695 | ir_ref_instruction(container, ag->current_basic_block); | ||
| 2696 | ir_ref_instruction(name, ag->current_basic_block); | ||
| 2697 | |||
| 2698 | return &instruction->base; | ||
| 2699 | } | ||
| 2700 | |||
| 2701 | static IrInstSrc *ir_build_undeclared_identifier(Stage1AstGen *ag, Scope *scope, AstNode *source_node, Buf *name) { | ||
| 2702 | IrInstSrcUndeclaredIdent *instruction = ir_build_instruction<IrInstSrcUndeclaredIdent>(ag, scope, source_node); | ||
| 2703 | instruction->name = name; | ||
| 2704 | |||
| 2705 | return &instruction->base; | ||
| 2706 | } | ||
| 2707 | |||
| 2708 | static IrInstSrc *ir_build_check_runtime_scope(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *scope_is_comptime, IrInstSrc *is_comptime) { | ||
| 2709 | IrInstSrcCheckRuntimeScope *instruction = ir_build_instruction<IrInstSrcCheckRuntimeScope>(ag, scope, source_node); | ||
| 2710 | instruction->scope_is_comptime = scope_is_comptime; | ||
| 2711 | instruction->is_comptime = is_comptime; | ||
| 2712 | |||
| 2713 | ir_ref_instruction(scope_is_comptime, ag->current_basic_block); | ||
| 2714 | ir_ref_instruction(is_comptime, ag->current_basic_block); | ||
| 2715 | |||
| 2716 | return &instruction->base; | ||
| 2717 | } | ||
| 2718 | |||
| 2719 | static IrInstSrc *ir_build_union_init_named_field(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2720 | IrInstSrc *union_type, IrInstSrc *field_name, IrInstSrc *field_result_loc, IrInstSrc *result_loc) | ||
| 2721 | { | ||
| 2722 | IrInstSrcUnionInitNamedField *instruction = ir_build_instruction<IrInstSrcUnionInitNamedField>(ag, scope, source_node); | ||
| 2723 | instruction->union_type = union_type; | ||
| 2724 | instruction->field_name = field_name; | ||
| 2725 | instruction->field_result_loc = field_result_loc; | ||
| 2726 | instruction->result_loc = result_loc; | ||
| 2727 | |||
| 2728 | ir_ref_instruction(union_type, ag->current_basic_block); | ||
| 2729 | ir_ref_instruction(field_name, ag->current_basic_block); | ||
| 2730 | ir_ref_instruction(field_result_loc, ag->current_basic_block); | ||
| 2731 | if (result_loc != nullptr) ir_ref_instruction(result_loc, ag->current_basic_block); | ||
| 2732 | |||
| 2733 | return &instruction->base; | ||
| 2734 | } | ||
| 2735 | |||
| 2736 | static IrInstSrc *ir_build_alloca_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2737 | IrInstSrc *align, const char *name_hint, IrInstSrc *is_comptime) | ||
| 2738 | { | ||
| 2739 | IrInstSrcAlloca *instruction = ir_build_instruction<IrInstSrcAlloca>(ag, scope, source_node); | ||
| 2740 | instruction->base.is_gen = true; | ||
| 2741 | instruction->align = align; | ||
| 2742 | instruction->name_hint = name_hint; | ||
| 2743 | instruction->is_comptime = is_comptime; | ||
| 2744 | |||
| 2745 | if (align != nullptr) ir_ref_instruction(align, ag->current_basic_block); | ||
| 2746 | if (is_comptime != nullptr) ir_ref_instruction(is_comptime, ag->current_basic_block); | ||
| 2747 | |||
| 2748 | return &instruction->base; | ||
| 2749 | } | ||
| 2750 | |||
| 2751 | static IrInstSrc *ir_build_end_expr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2752 | IrInstSrc *value, ResultLoc *result_loc) | ||
| 2753 | { | ||
| 2754 | IrInstSrcEndExpr *instruction = ir_build_instruction<IrInstSrcEndExpr>(ag, scope, source_node); | ||
| 2755 | instruction->base.is_gen = true; | ||
| 2756 | instruction->value = value; | ||
| 2757 | instruction->result_loc = result_loc; | ||
| 2758 | |||
| 2759 | ir_ref_instruction(value, ag->current_basic_block); | ||
| 2760 | |||
| 2761 | return &instruction->base; | ||
| 2762 | } | ||
| 2763 | |||
| 2764 | static IrInstSrcSuspendBegin *ir_build_suspend_begin_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | ||
| 2765 | return ir_build_instruction<IrInstSrcSuspendBegin>(ag, scope, source_node); | ||
| 2766 | } | ||
| 2767 | |||
| 2768 | static IrInstSrc *ir_build_suspend_finish_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2769 | IrInstSrcSuspendBegin *begin) | ||
| 2770 | { | ||
| 2771 | IrInstSrcSuspendFinish *inst = ir_build_instruction<IrInstSrcSuspendFinish>(ag, scope, source_node); | ||
| 2772 | inst->begin = begin; | ||
| 2773 | |||
| 2774 | ir_ref_instruction(&begin->base, ag->current_basic_block); | ||
| 2775 | |||
| 2776 | return &inst->base; | ||
| 2777 | } | ||
| 2778 | |||
| 2779 | static IrInstSrc *ir_build_await_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2780 | IrInstSrc *frame, ResultLoc *result_loc, bool is_nosuspend) | ||
| 2781 | { | ||
| 2782 | IrInstSrcAwait *instruction = ir_build_instruction<IrInstSrcAwait>(ag, scope, source_node); | ||
| 2783 | instruction->frame = frame; | ||
| 2784 | instruction->result_loc = result_loc; | ||
| 2785 | instruction->is_nosuspend = is_nosuspend; | ||
| 2786 | |||
| 2787 | ir_ref_instruction(frame, ag->current_basic_block); | ||
| 2788 | |||
| 2789 | return &instruction->base; | ||
| 2790 | } | ||
| 2791 | |||
| 2792 | static IrInstSrc *ir_build_resume_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *frame) { | ||
| 2793 | IrInstSrcResume *instruction = ir_build_instruction<IrInstSrcResume>(ag, scope, source_node); | ||
| 2794 | instruction->frame = frame; | ||
| 2795 | |||
| 2796 | ir_ref_instruction(frame, ag->current_basic_block); | ||
| 2797 | |||
| 2798 | return &instruction->base; | ||
| 2799 | } | ||
| 2800 | |||
| 2801 | static IrInstSrcSpillBegin *ir_build_spill_begin_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2802 | IrInstSrc *operand, SpillId spill_id) | ||
| 2803 | { | ||
| 2804 | IrInstSrcSpillBegin *instruction = ir_build_instruction<IrInstSrcSpillBegin>(ag, scope, source_node); | ||
| 2805 | instruction->operand = operand; | ||
| 2806 | instruction->spill_id = spill_id; | ||
| 2807 | |||
| 2808 | ir_ref_instruction(operand, ag->current_basic_block); | ||
| 2809 | |||
| 2810 | return instruction; | ||
| 2811 | } | ||
| 2812 | |||
| 2813 | static IrInstSrc *ir_build_spill_end_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 2814 | IrInstSrcSpillBegin *begin) | ||
| 2815 | { | ||
| 2816 | IrInstSrcSpillEnd *instruction = ir_build_instruction<IrInstSrcSpillEnd>(ag, scope, source_node); | ||
| 2817 | instruction->begin = begin; | ||
| 2818 | |||
| 2819 | ir_ref_instruction(&begin->base, ag->current_basic_block); | ||
| 2820 | |||
| 2821 | return &instruction->base; | ||
| 2822 | } | ||
| 2823 | |||
| 2824 | static IrInstSrc *ir_build_wasm_memory_size_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *index) { | ||
| 2825 | IrInstSrcWasmMemorySize *instruction = ir_build_instruction<IrInstSrcWasmMemorySize>(ag, scope, source_node); | ||
| 2826 | instruction->index = index; | ||
| 2827 | |||
| 2828 | ir_ref_instruction(index, ag->current_basic_block); | ||
| 2829 | |||
| 2830 | return &instruction->base; | ||
| 2831 | } | ||
| 2832 | |||
| 2833 | static IrInstSrc *ir_build_wasm_memory_grow_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node, IrInstSrc *index, IrInstSrc *delta) { | ||
| 2834 | IrInstSrcWasmMemoryGrow *instruction = ir_build_instruction<IrInstSrcWasmMemoryGrow>(ag, scope, source_node); | ||
| 2835 | instruction->index = index; | ||
| 2836 | instruction->delta = delta; | ||
| 2837 | |||
| 2838 | ir_ref_instruction(index, ag->current_basic_block); | ||
| 2839 | ir_ref_instruction(delta, ag->current_basic_block); | ||
| 2840 | |||
| 2841 | return &instruction->base; | ||
| 2842 | } | ||
| 2843 | |||
| 2844 | static IrInstSrc *ir_build_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node) { | ||
| 2845 | IrInstSrcSrc *instruction = ir_build_instruction<IrInstSrcSrc>(ag, scope, source_node); | ||
| 2846 | |||
| 2847 | return &instruction->base; | ||
| 2848 | } | ||
| 2849 | |||
| 2850 | static void ir_count_defers(Stage1AstGen *ag, Scope *inner_scope, Scope *outer_scope, size_t *results) { | ||
| 2851 | results[ReturnKindUnconditional] = 0; | ||
| 2852 | results[ReturnKindError] = 0; | ||
| 2853 | |||
| 2854 | Scope *scope = inner_scope; | ||
| 2855 | |||
| 2856 | while (scope != outer_scope) { | ||
| 2857 | assert(scope); | ||
| 2858 | switch (scope->id) { | ||
| 2859 | case ScopeIdDefer: { | ||
| 2860 | AstNode *defer_node = scope->source_node; | ||
| 2861 | assert(defer_node->type == NodeTypeDefer); | ||
| 2862 | ReturnKind defer_kind = defer_node->data.defer.kind; | ||
| 2863 | results[defer_kind] += 1; | ||
| 2864 | scope = scope->parent; | ||
| 2865 | continue; | ||
| 2866 | } | ||
| 2867 | case ScopeIdDecls: | ||
| 2868 | case ScopeIdFnDef: | ||
| 2869 | return; | ||
| 2870 | case ScopeIdBlock: | ||
| 2871 | case ScopeIdVarDecl: | ||
| 2872 | case ScopeIdLoop: | ||
| 2873 | case ScopeIdSuspend: | ||
| 2874 | case ScopeIdCompTime: | ||
| 2875 | case ScopeIdNoSuspend: | ||
| 2876 | case ScopeIdRuntime: | ||
| 2877 | case ScopeIdTypeOf: | ||
| 2878 | case ScopeIdExpr: | ||
| 2879 | scope = scope->parent; | ||
| 2880 | continue; | ||
| 2881 | case ScopeIdDeferExpr: | ||
| 2882 | case ScopeIdCImport: | ||
| 2883 | zig_unreachable(); | ||
| 2884 | } | ||
| 2885 | } | ||
| 2886 | } | ||
| 2887 | |||
| 2888 | static IrInstSrc *ir_mark_gen(IrInstSrc *instruction) { | ||
| 2889 | instruction->is_gen = true; | ||
| 2890 | return instruction; | ||
| 2891 | } | ||
| 2892 | |||
| 2893 | static bool astgen_defers_for_block(Stage1AstGen *ag, Scope *inner_scope, Scope *outer_scope, bool *is_noreturn, IrInstSrc *err_value) { | ||
| 2894 | Scope *scope = inner_scope; | ||
| 2895 | if (is_noreturn != nullptr) *is_noreturn = false; | ||
| 2896 | while (scope != outer_scope) { | ||
| 2897 | if (!scope) | ||
| 2898 | return true; | ||
| 2899 | |||
| 2900 | switch (scope->id) { | ||
| 2901 | case ScopeIdDefer: { | ||
| 2902 | AstNode *defer_node = scope->source_node; | ||
| 2903 | assert(defer_node->type == NodeTypeDefer); | ||
| 2904 | ReturnKind defer_kind = defer_node->data.defer.kind; | ||
| 2905 | AstNode *defer_expr_node = defer_node->data.defer.expr; | ||
| 2906 | AstNode *defer_var_node = defer_node->data.defer.err_payload; | ||
| 2907 | |||
| 2908 | if (defer_kind == ReturnKindError && err_value == nullptr) { | ||
| 2909 | // This is an `errdefer` but we're generating code for a | ||
| 2910 | // `return` that doesn't return an error, skip it | ||
| 2911 | scope = scope->parent; | ||
| 2912 | continue; | ||
| 2913 | } | ||
| 2914 | |||
| 2915 | Scope *defer_expr_scope = defer_node->data.defer.expr_scope; | ||
| 2916 | if (defer_var_node != nullptr) { | ||
| 2917 | assert(defer_kind == ReturnKindError); | ||
| 2918 | assert(defer_var_node->type == NodeTypeIdentifier); | ||
| 2919 | Buf *var_name = node_identifier_buf(defer_var_node); | ||
| 2920 | |||
| 2921 | if (defer_expr_node->type == NodeTypeUnreachable) { | ||
| 2922 | add_node_error(ag->codegen, defer_var_node, | ||
| 2923 | buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); | ||
| 2924 | return false; | ||
| 2925 | } | ||
| 2926 | |||
| 2927 | IrInstSrc *is_comptime; | ||
| 2928 | if (ir_should_inline(ag->exec, defer_expr_scope)) { | ||
| 2929 | is_comptime = ir_build_const_bool(ag, defer_expr_scope, | ||
| 2930 | defer_expr_node, true); | ||
| 2931 | } else { | ||
| 2932 | is_comptime = ir_build_test_comptime(ag, defer_expr_scope, | ||
| 2933 | defer_expr_node, err_value); | ||
| 2934 | } | ||
| 2935 | |||
| 2936 | ZigVar *err_var = ir_create_var(ag, defer_var_node, defer_expr_scope, | ||
| 2937 | var_name, true, true, false, is_comptime); | ||
| 2938 | build_decl_var_and_init(ag, defer_expr_scope, defer_var_node, err_var, err_value, | ||
| 2939 | buf_ptr(var_name), is_comptime); | ||
| 2940 | |||
| 2941 | defer_expr_scope = err_var->child_scope; | ||
| 2942 | } | ||
| 2943 | |||
| 2944 | IrInstSrc *defer_expr_value = astgen_node(ag, defer_expr_node, defer_expr_scope); | ||
| 2945 | if (defer_expr_value == ag->codegen->invalid_inst_src) | ||
| 2946 | return ag->codegen->invalid_inst_src; | ||
| 2947 | |||
| 2948 | if (defer_expr_value->is_noreturn) { | ||
| 2949 | if (is_noreturn != nullptr) *is_noreturn = true; | ||
| 2950 | } else { | ||
| 2951 | ir_mark_gen(ir_build_check_statement_is_void(ag, defer_expr_scope, defer_expr_node, | ||
| 2952 | defer_expr_value)); | ||
| 2953 | } | ||
| 2954 | scope = scope->parent; | ||
| 2955 | continue; | ||
| 2956 | } | ||
| 2957 | case ScopeIdDecls: | ||
| 2958 | case ScopeIdFnDef: | ||
| 2959 | return true; | ||
| 2960 | case ScopeIdBlock: | ||
| 2961 | case ScopeIdVarDecl: | ||
| 2962 | case ScopeIdLoop: | ||
| 2963 | case ScopeIdSuspend: | ||
| 2964 | case ScopeIdCompTime: | ||
| 2965 | case ScopeIdNoSuspend: | ||
| 2966 | case ScopeIdRuntime: | ||
| 2967 | case ScopeIdTypeOf: | ||
| 2968 | case ScopeIdExpr: | ||
| 2969 | scope = scope->parent; | ||
| 2970 | continue; | ||
| 2971 | case ScopeIdDeferExpr: | ||
| 2972 | case ScopeIdCImport: | ||
| 2973 | zig_unreachable(); | ||
| 2974 | } | ||
| 2975 | } | ||
| 2976 | return true; | ||
| 2977 | } | ||
| 2978 | |||
| 2979 | static void ir_set_cursor_at_end(Stage1AstGen *ag, Stage1ZirBasicBlock *basic_block) { | ||
| 2980 | assert(basic_block); | ||
| 2981 | ag->current_basic_block = basic_block; | ||
| 2982 | } | ||
| 2983 | |||
| 2984 | static void ir_set_cursor_at_end_and_append_block(Stage1AstGen *ag, Stage1ZirBasicBlock *basic_block) { | ||
| 2985 | basic_block->index = ag->exec->basic_block_list.length; | ||
| 2986 | ag->exec->basic_block_list.append(basic_block); | ||
| 2987 | ir_set_cursor_at_end(ag, basic_block); | ||
| 2988 | } | ||
| 2989 | |||
| 2990 | static ScopeSuspend *get_scope_suspend(Scope *scope) { | ||
| 2991 | while (scope) { | ||
| 2992 | if (scope->id == ScopeIdSuspend) | ||
| 2993 | return (ScopeSuspend *)scope; | ||
| 2994 | if (scope->id == ScopeIdFnDef) | ||
| 2995 | return nullptr; | ||
| 2996 | |||
| 2997 | scope = scope->parent; | ||
| 2998 | } | ||
| 2999 | return nullptr; | ||
| 3000 | } | ||
| 3001 | |||
| 3002 | static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { | ||
| 3003 | while (scope) { | ||
| 3004 | if (scope->id == ScopeIdDeferExpr) | ||
| 3005 | return (ScopeDeferExpr *)scope; | ||
| 3006 | if (scope->id == ScopeIdFnDef) | ||
| 3007 | return nullptr; | ||
| 3008 | |||
| 3009 | scope = scope->parent; | ||
| 3010 | } | ||
| 3011 | return nullptr; | ||
| 3012 | } | ||
| 3013 | |||
| 3014 | static IrInstSrc *astgen_return(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { | ||
| 3015 | assert(node->type == NodeTypeReturnExpr); | ||
| 3016 | |||
| 3017 | ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(scope); | ||
| 3018 | if (scope_defer_expr) { | ||
| 3019 | if (!scope_defer_expr->reported_err) { | ||
| 3020 | add_node_error(ag->codegen, node, buf_sprintf("cannot return from defer expression")); | ||
| 3021 | scope_defer_expr->reported_err = true; | ||
| 3022 | } | ||
| 3023 | return ag->codegen->invalid_inst_src; | ||
| 3024 | } | ||
| 3025 | |||
| 3026 | Scope *outer_scope = ag->exec->begin_scope; | ||
| 3027 | |||
| 3028 | AstNode *expr_node = node->data.return_expr.expr; | ||
| 3029 | switch (node->data.return_expr.kind) { | ||
| 3030 | case ReturnKindUnconditional: | ||
| 3031 | { | ||
| 3032 | ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>(); | ||
| 3033 | result_loc_ret->base.id = ResultLocIdReturn; | ||
| 3034 | ir_build_reset_result(ag, scope, node, &result_loc_ret->base); | ||
| 3035 | |||
| 3036 | IrInstSrc *return_value; | ||
| 3037 | if (expr_node) { | ||
| 3038 | // Temporarily set this so that if we return a type it gets the name of the function | ||
| 3039 | ZigFn *prev_name_fn = ag->exec->name_fn; | ||
| 3040 | ag->exec->name_fn = ag->fn; | ||
| 3041 | return_value = astgen_node_extra(ag, expr_node, scope, LValNone, &result_loc_ret->base); | ||
| 3042 | ag->exec->name_fn = prev_name_fn; | ||
| 3043 | if (return_value == ag->codegen->invalid_inst_src) | ||
| 3044 | return ag->codegen->invalid_inst_src; | ||
| 3045 | } else { | ||
| 3046 | return_value = ir_build_const_void(ag, scope, node); | ||
| 3047 | ir_build_end_expr(ag, scope, node, return_value, &result_loc_ret->base); | ||
| 3048 | } | ||
| 3049 | |||
| 3050 | ir_mark_gen(ir_build_add_implicit_return_type(ag, scope, node, return_value, result_loc_ret)); | ||
| 3051 | |||
| 3052 | size_t defer_counts[2]; | ||
| 3053 | ir_count_defers(ag, scope, outer_scope, defer_counts); | ||
| 3054 | bool have_err_defers = defer_counts[ReturnKindError] > 0; | ||
| 3055 | if (!have_err_defers && !ag->codegen->have_err_ret_tracing) { | ||
| 3056 | // only generate unconditional defers | ||
| 3057 | if (!astgen_defers_for_block(ag, scope, outer_scope, nullptr, nullptr)) | ||
| 3058 | return ag->codegen->invalid_inst_src; | ||
| 3059 | IrInstSrc *result = ir_build_return_src(ag, scope, node, nullptr); | ||
| 3060 | result_loc_ret->base.source_instruction = result; | ||
| 3061 | return result; | ||
| 3062 | } | ||
| 3063 | bool should_inline = ir_should_inline(ag->exec, scope); | ||
| 3064 | |||
| 3065 | Stage1ZirBasicBlock *err_block = ir_create_basic_block(ag, scope, "ErrRetErr"); | ||
| 3066 | Stage1ZirBasicBlock *ok_block = ir_create_basic_block(ag, scope, "ErrRetOk"); | ||
| 3067 | |||
| 3068 | IrInstSrc *is_err = ir_build_test_err_src(ag, scope, node, return_value, false, true); | ||
| 3069 | |||
| 3070 | IrInstSrc *is_comptime; | ||
| 3071 | if (should_inline) { | ||
| 3072 | is_comptime = ir_build_const_bool(ag, scope, node, should_inline); | ||
| 3073 | } else { | ||
| 3074 | is_comptime = ir_build_test_comptime(ag, scope, node, is_err); | ||
| 3075 | } | ||
| 3076 | |||
| 3077 | ir_mark_gen(ir_build_cond_br(ag, scope, node, is_err, err_block, ok_block, is_comptime)); | ||
| 3078 | Stage1ZirBasicBlock *ret_stmt_block = ir_create_basic_block(ag, scope, "RetStmt"); | ||
| 3079 | |||
| 3080 | ir_set_cursor_at_end_and_append_block(ag, err_block); | ||
| 3081 | if (!astgen_defers_for_block(ag, scope, outer_scope, nullptr, return_value)) | ||
| 3082 | return ag->codegen->invalid_inst_src; | ||
| 3083 | if (ag->codegen->have_err_ret_tracing && !should_inline) { | ||
| 3084 | ir_build_save_err_ret_addr_src(ag, scope, node); | ||
| 3085 | } | ||
| 3086 | ir_build_br(ag, scope, node, ret_stmt_block, is_comptime); | ||
| 3087 | |||
| 3088 | ir_set_cursor_at_end_and_append_block(ag, ok_block); | ||
| 3089 | if (!astgen_defers_for_block(ag, scope, outer_scope, nullptr, nullptr)) | ||
| 3090 | return ag->codegen->invalid_inst_src; | ||
| 3091 | ir_build_br(ag, scope, node, ret_stmt_block, is_comptime); | ||
| 3092 | |||
| 3093 | ir_set_cursor_at_end_and_append_block(ag, ret_stmt_block); | ||
| 3094 | IrInstSrc *result = ir_build_return_src(ag, scope, node, nullptr); | ||
| 3095 | result_loc_ret->base.source_instruction = result; | ||
| 3096 | return result; | ||
| 3097 | } | ||
| 3098 | case ReturnKindError: | ||
| 3099 | { | ||
| 3100 | assert(expr_node); | ||
| 3101 | IrInstSrc *err_union_ptr = astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr); | ||
| 3102 | if (err_union_ptr == ag->codegen->invalid_inst_src) | ||
| 3103 | return ag->codegen->invalid_inst_src; | ||
| 3104 | IrInstSrc *is_err_val = ir_build_test_err_src(ag, scope, node, err_union_ptr, true, false); | ||
| 3105 | |||
| 3106 | Stage1ZirBasicBlock *return_block = ir_create_basic_block(ag, scope, "ErrRetReturn"); | ||
| 3107 | Stage1ZirBasicBlock *continue_block = ir_create_basic_block(ag, scope, "ErrRetContinue"); | ||
| 3108 | IrInstSrc *is_comptime; | ||
| 3109 | bool should_inline = ir_should_inline(ag->exec, scope); | ||
| 3110 | if (should_inline) { | ||
| 3111 | is_comptime = ir_build_const_bool(ag, scope, node, true); | ||
| 3112 | } else { | ||
| 3113 | is_comptime = ir_build_test_comptime(ag, scope, node, is_err_val); | ||
| 3114 | } | ||
| 3115 | ir_mark_gen(ir_build_cond_br(ag, scope, node, is_err_val, return_block, continue_block, is_comptime)); | ||
| 3116 | |||
| 3117 | ir_set_cursor_at_end_and_append_block(ag, return_block); | ||
| 3118 | IrInstSrc *err_val_ptr = ir_build_unwrap_err_code_src(ag, scope, node, err_union_ptr); | ||
| 3119 | IrInstSrc *err_val = ir_build_load_ptr(ag, scope, node, err_val_ptr); | ||
| 3120 | ir_mark_gen(ir_build_add_implicit_return_type(ag, scope, node, err_val, nullptr)); | ||
| 3121 | IrInstSrcSpillBegin *spill_begin = ir_build_spill_begin_src(ag, scope, node, err_val, | ||
| 3122 | SpillIdRetErrCode); | ||
| 3123 | ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>(); | ||
| 3124 | result_loc_ret->base.id = ResultLocIdReturn; | ||
| 3125 | ir_build_reset_result(ag, scope, node, &result_loc_ret->base); | ||
| 3126 | ir_build_end_expr(ag, scope, node, err_val, &result_loc_ret->base); | ||
| 3127 | |||
| 3128 | bool is_noreturn = false; | ||
| 3129 | if (!astgen_defers_for_block(ag, scope, outer_scope, &is_noreturn, err_val)) { | ||
| 3130 | return ag->codegen->invalid_inst_src; | ||
| 3131 | } | ||
| 3132 | if (!is_noreturn) { | ||
| 3133 | if (ag->codegen->have_err_ret_tracing && !should_inline) { | ||
| 3134 | ir_build_save_err_ret_addr_src(ag, scope, node); | ||
| 3135 | } | ||
| 3136 | err_val = ir_build_spill_end_src(ag, scope, node, spill_begin); | ||
| 3137 | IrInstSrc *ret_inst = ir_build_return_src(ag, scope, node, err_val); | ||
| 3138 | result_loc_ret->base.source_instruction = ret_inst; | ||
| 3139 | } | ||
| 3140 | |||
| 3141 | ir_set_cursor_at_end_and_append_block(ag, continue_block); | ||
| 3142 | IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(ag, scope, node, err_union_ptr, false, false); | ||
| 3143 | if (lval == LValPtr) | ||
| 3144 | return unwrapped_ptr; | ||
| 3145 | else | ||
| 3146 | return ir_expr_wrap(ag, scope, ir_build_load_ptr(ag, scope, node, unwrapped_ptr), result_loc); | ||
| 3147 | } | ||
| 3148 | } | ||
| 3149 | zig_unreachable(); | ||
| 3150 | } | ||
| 3151 | |||
| 3152 | ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope, | ||
| 3153 | Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime, | ||
| 3154 | bool skip_name_check) | ||
| 3155 | { | ||
| 3156 | ZigVar *variable_entry = heap::c_allocator.create<ZigVar>(); | ||
| 3157 | variable_entry->parent_scope = parent_scope; | ||
| 3158 | variable_entry->shadowable = is_shadowable; | ||
| 3159 | variable_entry->is_comptime = is_comptime; | ||
| 3160 | variable_entry->src_arg_index = SIZE_MAX; | ||
| 3161 | variable_entry->const_value = codegen->pass1_arena->create<ZigValue>(); | ||
| 3162 | |||
| 3163 | if (is_comptime != nullptr) { | ||
| 3164 | is_comptime->base.ref_count += 1; | ||
| 3165 | } | ||
| 3166 | |||
| 3167 | if (name) { | ||
| 3168 | variable_entry->name = strdup(buf_ptr(name)); | ||
| 3169 | |||
| 3170 | if (!skip_name_check) { | ||
| 3171 | ZigVar *existing_var = find_variable(codegen, parent_scope, name, nullptr); | ||
| 3172 | if (existing_var && !existing_var->shadowable) { | ||
| 3173 | if (existing_var->var_type == nullptr || !type_is_invalid(existing_var->var_type)) { | ||
| 3174 | ErrorMsg *msg = add_node_error(codegen, node, | ||
| 3175 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); | ||
| 3176 | add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); | ||
| 3177 | } | ||
| 3178 | variable_entry->var_type = codegen->builtin_types.entry_invalid; | ||
| 3179 | } else { | ||
| 3180 | ZigType *type; | ||
| 3181 | if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) { | ||
| 3182 | add_node_error(codegen, node, | ||
| 3183 | buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name))); | ||
| 3184 | variable_entry->var_type = codegen->builtin_types.entry_invalid; | ||
| 3185 | } else { | ||
| 3186 | Tld *tld = find_decl(codegen, parent_scope, name); | ||
| 3187 | if (tld != nullptr) { | ||
| 3188 | bool want_err_msg = true; | ||
| 3189 | if (tld->id == TldIdVar) { | ||
| 3190 | ZigVar *var = reinterpret_cast<TldVar *>(tld)->var; | ||
| 3191 | if (var != nullptr && var->var_type != nullptr && type_is_invalid(var->var_type)) { | ||
| 3192 | want_err_msg = false; | ||
| 3193 | } | ||
| 3194 | } | ||
| 3195 | if (want_err_msg) { | ||
| 3196 | ErrorMsg *msg = add_node_error(codegen, node, | ||
| 3197 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); | ||
| 3198 | add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here")); | ||
| 3199 | } | ||
| 3200 | variable_entry->var_type = codegen->builtin_types.entry_invalid; | ||
| 3201 | } | ||
| 3202 | } | ||
| 3203 | } | ||
| 3204 | } | ||
| 3205 | } else { | ||
| 3206 | assert(is_shadowable); | ||
| 3207 | // TODO make this name not actually be in scope. user should be able to make a variable called "_anon" | ||
| 3208 | // might already be solved, let's just make sure it has test coverage | ||
| 3209 | // maybe we put a prefix on this so the debug info doesn't clobber user debug info for same named variables | ||
| 3210 | variable_entry->name = "_anon"; | ||
| 3211 | } | ||
| 3212 | |||
| 3213 | variable_entry->src_is_const = src_is_const; | ||
| 3214 | variable_entry->gen_is_const = gen_is_const; | ||
| 3215 | variable_entry->decl_node = node; | ||
| 3216 | variable_entry->child_scope = create_var_scope(codegen, node, parent_scope, variable_entry); | ||
| 3217 | |||
| 3218 | return variable_entry; | ||
| 3219 | } | ||
| 3220 | |||
| 3221 | |||
| 3222 | // Set name to nullptr to make the variable anonymous (not visible to programmer). | ||
| 3223 | // After you call this function var->child_scope has the variable in scope | ||
| 3224 | static ZigVar *ir_create_var(Stage1AstGen *ag, AstNode *node, Scope *scope, Buf *name, | ||
| 3225 | bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime) | ||
| 3226 | { | ||
| 3227 | bool is_underscored = name ? buf_eql_str(name, "_") : false; | ||
| 3228 | ZigVar *var = create_local_var(ag->codegen, node, scope, | ||
| 3229 | (is_underscored ? nullptr : name), src_is_const, gen_is_const, | ||
| 3230 | (is_underscored ? true : is_shadowable), is_comptime, false); | ||
| 3231 | assert(var->child_scope); | ||
| 3232 | return var; | ||
| 3233 | } | ||
| 3234 | |||
| 3235 | static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) { | ||
| 3236 | ResultLocPeer *result = heap::c_allocator.create<ResultLocPeer>(); | ||
| 3237 | result->base.id = ResultLocIdPeer; | ||
| 3238 | result->base.source_instruction = peer_parent->base.source_instruction; | ||
| 3239 | result->parent = peer_parent; | ||
| 3240 | result->base.allow_write_through_const = peer_parent->parent->allow_write_through_const; | ||
| 3241 | return result; | ||
| 3242 | } | ||
| 3243 | |||
| 3244 | static bool is_duplicate_label(CodeGen *g, Scope *scope, AstNode *node, Buf *name) { | ||
| 3245 | if (name == nullptr) return false; | ||
| 3246 | |||
| 3247 | for (;;) { | ||
| 3248 | if (scope == nullptr || scope->id == ScopeIdFnDef) { | ||
| 3249 | break; | ||
| 3250 | } else if (scope->id == ScopeIdBlock || scope->id == ScopeIdLoop) { | ||
| 3251 | Buf *this_block_name = scope->id == ScopeIdBlock ? ((ScopeBlock *)scope)->name : ((ScopeLoop *)scope)->name; | ||
| 3252 | if (this_block_name != nullptr && buf_eql_buf(name, this_block_name)) { | ||
| 3253 | ErrorMsg *msg = add_node_error(g, node, buf_sprintf("redeclaration of label '%s'", buf_ptr(name))); | ||
| 3254 | add_error_note(g, msg, scope->source_node, buf_sprintf("previous declaration is here")); | ||
| 3255 | return true; | ||
| 3256 | } | ||
| 3257 | } | ||
| 3258 | scope = scope->parent; | ||
| 3259 | } | ||
| 3260 | return false; | ||
| 3261 | } | ||
| 3262 | |||
| 3263 | static IrInstSrc *astgen_block(Stage1AstGen *ag, Scope *parent_scope, AstNode *block_node, LVal lval, | ||
| 3264 | ResultLoc *result_loc) | ||
| 3265 | { | ||
| 3266 | assert(block_node->type == NodeTypeBlock); | ||
| 3267 | |||
| 3268 | ZigList<IrInstSrc *> incoming_values = {0}; | ||
| 3269 | ZigList<Stage1ZirBasicBlock *> incoming_blocks = {0}; | ||
| 3270 | |||
| 3271 | if (is_duplicate_label(ag->codegen, parent_scope, block_node, block_node->data.block.name)) | ||
| 3272 | return ag->codegen->invalid_inst_src; | ||
| 3273 | |||
| 3274 | ScopeBlock *scope_block = create_block_scope(ag->codegen, block_node, parent_scope); | ||
| 3275 | |||
| 3276 | Scope *outer_block_scope = &scope_block->base; | ||
| 3277 | Scope *child_scope = outer_block_scope; | ||
| 3278 | |||
| 3279 | ZigFn *fn_entry = scope_fn_entry(parent_scope); | ||
| 3280 | if (fn_entry && fn_entry->child_scope == parent_scope) { | ||
| 3281 | fn_entry->def_scope = scope_block; | ||
| 3282 | } | ||
| 3283 | |||
| 3284 | if (block_node->data.block.statements.length == 0) { | ||
| 3285 | if (scope_block->name != nullptr) { | ||
| 3286 | add_node_error(ag->codegen, block_node, buf_sprintf("unused block label")); | ||
| 3287 | } | ||
| 3288 | // {} | ||
| 3289 | return ir_lval_wrap(ag, parent_scope, ir_build_const_void(ag, child_scope, block_node), lval, result_loc); | ||
| 3290 | } | ||
| 3291 | |||
| 3292 | if (block_node->data.block.name != nullptr) { | ||
| 3293 | scope_block->lval = lval; | ||
| 3294 | scope_block->incoming_blocks = &incoming_blocks; | ||
| 3295 | scope_block->incoming_values = &incoming_values; | ||
| 3296 | scope_block->end_block = ir_create_basic_block(ag, parent_scope, "BlockEnd"); | ||
| 3297 | scope_block->is_comptime = ir_build_const_bool(ag, parent_scope, block_node, | ||
| 3298 | ir_should_inline(ag->exec, parent_scope)); | ||
| 3299 | |||
| 3300 | scope_block->peer_parent = heap::c_allocator.create<ResultLocPeerParent>(); | ||
| 3301 | scope_block->peer_parent->base.id = ResultLocIdPeerParent; | ||
| 3302 | scope_block->peer_parent->base.source_instruction = scope_block->is_comptime; | ||
| 3303 | scope_block->peer_parent->base.allow_write_through_const = result_loc->allow_write_through_const; | ||
| 3304 | scope_block->peer_parent->end_bb = scope_block->end_block; | ||
| 3305 | scope_block->peer_parent->is_comptime = scope_block->is_comptime; | ||
| 3306 | scope_block->peer_parent->parent = result_loc; | ||
| 3307 | ir_build_reset_result(ag, parent_scope, block_node, &scope_block->peer_parent->base); | ||
| 3308 | } | ||
| 3309 | |||
| 3310 | bool is_continuation_unreachable = false; | ||
| 3311 | bool found_invalid_inst = false; | ||
| 3312 | IrInstSrc *noreturn_return_value = nullptr; | ||
| 3313 | for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { | ||
| 3314 | AstNode *statement_node = block_node->data.block.statements.at(i); | ||
| 3315 | |||
| 3316 | IrInstSrc *statement_value = astgen_node(ag, statement_node, child_scope); | ||
| 3317 | if (statement_value == ag->codegen->invalid_inst_src) { | ||
| 3318 | // keep generating all the elements of the block in case of error, | ||
| 3319 | // we want to collect other compile errors | ||
| 3320 | found_invalid_inst = true; | ||
| 3321 | continue; | ||
| 3322 | } | ||
| 3323 | |||
| 3324 | is_continuation_unreachable = instr_is_unreachable(statement_value); | ||
| 3325 | if (is_continuation_unreachable) { | ||
| 3326 | // keep the last noreturn statement value around in case we need to return it | ||
| 3327 | noreturn_return_value = statement_value; | ||
| 3328 | } | ||
| 3329 | // This logic must be kept in sync with | ||
| 3330 | // [STMT_EXPR_TEST_THING] <--- (search this token) | ||
| 3331 | if (statement_node->type == NodeTypeDefer) { | ||
| 3332 | // defer starts a new scope | ||
| 3333 | child_scope = statement_node->data.defer.child_scope; | ||
| 3334 | assert(child_scope); | ||
| 3335 | } else if (statement_value->id == IrInstSrcIdDeclVar) { | ||
| 3336 | // variable declarations start a new scope | ||
| 3337 | IrInstSrcDeclVar *decl_var_instruction = (IrInstSrcDeclVar *)statement_value; | ||
| 3338 | child_scope = decl_var_instruction->var->child_scope; | ||
| 3339 | } else if (!is_continuation_unreachable) { | ||
| 3340 | // this statement's value must be void | ||
| 3341 | ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, statement_node, statement_value)); | ||
| 3342 | } | ||
| 3343 | } | ||
| 3344 | |||
| 3345 | if (scope_block->name != nullptr && scope_block->name_used == false) { | ||
| 3346 | add_node_error(ag->codegen, block_node, buf_sprintf("unused block label")); | ||
| 3347 | } | ||
| 3348 | |||
| 3349 | if (found_invalid_inst) | ||
| 3350 | return ag->codegen->invalid_inst_src; | ||
| 3351 | |||
| 3352 | if (is_continuation_unreachable) { | ||
| 3353 | assert(noreturn_return_value != nullptr); | ||
| 3354 | if (block_node->data.block.name == nullptr || incoming_blocks.length == 0) { | ||
| 3355 | return noreturn_return_value; | ||
| 3356 | } | ||
| 3357 | |||
| 3358 | if (scope_block->peer_parent != nullptr && scope_block->peer_parent->peers.length != 0) { | ||
| 3359 | scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block; | ||
| 3360 | } | ||
| 3361 | ir_set_cursor_at_end_and_append_block(ag, scope_block->end_block); | ||
| 3362 | IrInstSrc *phi = ir_build_phi(ag, parent_scope, block_node, incoming_blocks.length, | ||
| 3363 | incoming_blocks.items, incoming_values.items, scope_block->peer_parent); | ||
| 3364 | return ir_expr_wrap(ag, parent_scope, phi, result_loc); | ||
| 3365 | } else { | ||
| 3366 | incoming_blocks.append(ag->current_basic_block); | ||
| 3367 | IrInstSrc *else_expr_result = ir_mark_gen(ir_build_const_void(ag, parent_scope, block_node)); | ||
| 3368 | |||
| 3369 | if (scope_block->peer_parent != nullptr) { | ||
| 3370 | ResultLocPeer *peer_result = create_peer_result(scope_block->peer_parent); | ||
| 3371 | scope_block->peer_parent->peers.append(peer_result); | ||
| 3372 | ir_build_end_expr(ag, parent_scope, block_node, else_expr_result, &peer_result->base); | ||
| 3373 | |||
| 3374 | if (scope_block->peer_parent->peers.length != 0) { | ||
| 3375 | scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block; | ||
| 3376 | } | ||
| 3377 | } | ||
| 3378 | |||
| 3379 | incoming_values.append(else_expr_result); | ||
| 3380 | } | ||
| 3381 | |||
| 3382 | bool is_return_from_fn = block_node == ag->main_block_node; | ||
| 3383 | if (!is_return_from_fn) { | ||
| 3384 | if (!astgen_defers_for_block(ag, child_scope, outer_block_scope, nullptr, nullptr)) | ||
| 3385 | return ag->codegen->invalid_inst_src; | ||
| 3386 | } | ||
| 3387 | |||
| 3388 | IrInstSrc *result; | ||
| 3389 | if (block_node->data.block.name != nullptr) { | ||
| 3390 | ir_mark_gen(ir_build_br(ag, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime)); | ||
| 3391 | ir_set_cursor_at_end_and_append_block(ag, scope_block->end_block); | ||
| 3392 | IrInstSrc *phi = ir_build_phi(ag, parent_scope, block_node, incoming_blocks.length, | ||
| 3393 | incoming_blocks.items, incoming_values.items, scope_block->peer_parent); | ||
| 3394 | result = ir_expr_wrap(ag, parent_scope, phi, result_loc); | ||
| 3395 | } else { | ||
| 3396 | IrInstSrc *void_inst = ir_mark_gen(ir_build_const_void(ag, child_scope, block_node)); | ||
| 3397 | result = ir_lval_wrap(ag, parent_scope, void_inst, lval, result_loc); | ||
| 3398 | } | ||
| 3399 | if (!is_return_from_fn) | ||
| 3400 | return result; | ||
| 3401 | |||
| 3402 | // no need for save_err_ret_addr because this cannot return error | ||
| 3403 | // only generate unconditional defers | ||
| 3404 | |||
| 3405 | ir_mark_gen(ir_build_add_implicit_return_type(ag, child_scope, block_node, result, nullptr)); | ||
| 3406 | ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>(); | ||
| 3407 | result_loc_ret->base.id = ResultLocIdReturn; | ||
| 3408 | ir_build_reset_result(ag, parent_scope, block_node, &result_loc_ret->base); | ||
| 3409 | ir_mark_gen(ir_build_end_expr(ag, parent_scope, block_node, result, &result_loc_ret->base)); | ||
| 3410 | if (!astgen_defers_for_block(ag, child_scope, outer_block_scope, nullptr, nullptr)) | ||
| 3411 | return ag->codegen->invalid_inst_src; | ||
| 3412 | return ir_mark_gen(ir_build_return_src(ag, child_scope, result->base.source_node, result)); | ||
| 3413 | } | ||
| 3414 | |||
| 3415 | static IrInstSrc *astgen_bin_op_id(Stage1AstGen *ag, Scope *scope, AstNode *node, IrBinOp op_id) { | ||
| 3416 | Scope *inner_scope = scope; | ||
| 3417 | if (op_id == IrBinOpArrayCat || op_id == IrBinOpArrayMult) { | ||
| 3418 | inner_scope = create_comptime_scope(ag->codegen, node, scope); | ||
| 3419 | } | ||
| 3420 | |||
| 3421 | IrInstSrc *op1 = astgen_node(ag, node->data.bin_op_expr.op1, inner_scope); | ||
| 3422 | IrInstSrc *op2 = astgen_node(ag, node->data.bin_op_expr.op2, inner_scope); | ||
| 3423 | |||
| 3424 | if (op1 == ag->codegen->invalid_inst_src || op2 == ag->codegen->invalid_inst_src) | ||
| 3425 | return ag->codegen->invalid_inst_src; | ||
| 3426 | |||
| 3427 | return ir_build_bin_op(ag, scope, node, op_id, op1, op2, true); | ||
| 3428 | } | ||
| 3429 | |||
| 3430 | static IrInstSrc *astgen_merge_err_sets(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 3431 | IrInstSrc *op1 = astgen_node(ag, node->data.bin_op_expr.op1, scope); | ||
| 3432 | IrInstSrc *op2 = astgen_node(ag, node->data.bin_op_expr.op2, scope); | ||
| 3433 | |||
| 3434 | if (op1 == ag->codegen->invalid_inst_src || op2 == ag->codegen->invalid_inst_src) | ||
| 3435 | return ag->codegen->invalid_inst_src; | ||
| 3436 | |||
| 3437 | // TODO only pass type_name when the || operator is the top level AST node in the var decl expr | ||
| 3438 | Buf bare_name = BUF_INIT; | ||
| 3439 | Buf *type_name = get_anon_type_name(ag->codegen, ag->exec, "error", scope, node, &bare_name); | ||
| 3440 | |||
| 3441 | return ir_build_merge_err_sets(ag, scope, node, op1, op2, type_name); | ||
| 3442 | } | ||
| 3443 | |||
| 3444 | static IrInstSrc *astgen_assign(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 3445 | IrInstSrc *lvalue = astgen_node_extra(ag, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); | ||
| 3446 | if (lvalue == ag->codegen->invalid_inst_src) | ||
| 3447 | return ag->codegen->invalid_inst_src; | ||
| 3448 | |||
| 3449 | ResultLocInstruction *result_loc_inst = heap::c_allocator.create<ResultLocInstruction>(); | ||
| 3450 | result_loc_inst->base.id = ResultLocIdInstruction; | ||
| 3451 | result_loc_inst->base.source_instruction = lvalue; | ||
| 3452 | ir_ref_instruction(lvalue, ag->current_basic_block); | ||
| 3453 | ir_build_reset_result(ag, scope, node, &result_loc_inst->base); | ||
| 3454 | |||
| 3455 | IrInstSrc *rvalue = astgen_node_extra(ag, node->data.bin_op_expr.op2, scope, LValNone, | ||
| 3456 | &result_loc_inst->base); | ||
| 3457 | if (rvalue == ag->codegen->invalid_inst_src) | ||
| 3458 | return ag->codegen->invalid_inst_src; | ||
| 3459 | |||
| 3460 | return ir_build_const_void(ag, scope, node); | ||
| 3461 | } | ||
| 3462 | |||
| 3463 | static IrInstSrc *astgen_assign_op(Stage1AstGen *ag, Scope *scope, AstNode *node, IrBinOp op_id) { | ||
| 3464 | IrInstSrc *lvalue = astgen_node_extra(ag, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); | ||
| 3465 | if (lvalue == ag->codegen->invalid_inst_src) | ||
| 3466 | return lvalue; | ||
| 3467 | IrInstSrc *op1 = ir_build_load_ptr(ag, scope, node->data.bin_op_expr.op1, lvalue); | ||
| 3468 | IrInstSrc *op2 = astgen_node(ag, node->data.bin_op_expr.op2, scope); | ||
| 3469 | if (op2 == ag->codegen->invalid_inst_src) | ||
| 3470 | return op2; | ||
| 3471 | IrInstSrc *result = ir_build_bin_op(ag, scope, node, op_id, op1, op2, true); | ||
| 3472 | ir_build_store_ptr(ag, scope, node, lvalue, result); | ||
| 3473 | return ir_build_const_void(ag, scope, node); | ||
| 3474 | } | ||
| 3475 | |||
| 3476 | static IrInstSrc *astgen_bool_or(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 3477 | assert(node->type == NodeTypeBinOpExpr); | ||
| 3478 | |||
| 3479 | IrInstSrc *val1 = astgen_node(ag, node->data.bin_op_expr.op1, scope); | ||
| 3480 | if (val1 == ag->codegen->invalid_inst_src) | ||
| 3481 | return ag->codegen->invalid_inst_src; | ||
| 3482 | Stage1ZirBasicBlock *post_val1_block = ag->current_basic_block; | ||
| 3483 | |||
| 3484 | IrInstSrc *is_comptime; | ||
| 3485 | if (ir_should_inline(ag->exec, scope)) { | ||
| 3486 | is_comptime = ir_build_const_bool(ag, scope, node, true); | ||
| 3487 | } else { | ||
| 3488 | is_comptime = ir_build_test_comptime(ag, scope, node, val1); | ||
| 3489 | } | ||
| 3490 | |||
| 3491 | // block for when val1 == false | ||
| 3492 | Stage1ZirBasicBlock *false_block = ir_create_basic_block(ag, scope, "BoolOrFalse"); | ||
| 3493 | // block for when val1 == true (don't even evaluate the second part) | ||
| 3494 | Stage1ZirBasicBlock *true_block = ir_create_basic_block(ag, scope, "BoolOrTrue"); | ||
| 3495 | |||
| 3496 | ir_build_cond_br(ag, scope, node, val1, true_block, false_block, is_comptime); | ||
| 3497 | |||
| 3498 | ir_set_cursor_at_end_and_append_block(ag, false_block); | ||
| 3499 | IrInstSrc *val2 = astgen_node(ag, node->data.bin_op_expr.op2, scope); | ||
| 3500 | if (val2 == ag->codegen->invalid_inst_src) | ||
| 3501 | return ag->codegen->invalid_inst_src; | ||
| 3502 | Stage1ZirBasicBlock *post_val2_block = ag->current_basic_block; | ||
| 3503 | |||
| 3504 | ir_build_br(ag, scope, node, true_block, is_comptime); | ||
| 3505 | |||
| 3506 | ir_set_cursor_at_end_and_append_block(ag, true_block); | ||
| 3507 | |||
| 3508 | IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2); | ||
| 3509 | incoming_values[0] = val1; | ||
| 3510 | incoming_values[1] = val2; | ||
| 3511 | Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate<Stage1ZirBasicBlock *>(2); | ||
| 3512 | incoming_blocks[0] = post_val1_block; | ||
| 3513 | incoming_blocks[1] = post_val2_block; | ||
| 3514 | |||
| 3515 | return ir_build_phi(ag, scope, node, 2, incoming_blocks, incoming_values, nullptr); | ||
| 3516 | } | ||
| 3517 | |||
| 3518 | static IrInstSrc *astgen_bool_and(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 3519 | assert(node->type == NodeTypeBinOpExpr); | ||
| 3520 | |||
| 3521 | IrInstSrc *val1 = astgen_node(ag, node->data.bin_op_expr.op1, scope); | ||
| 3522 | if (val1 == ag->codegen->invalid_inst_src) | ||
| 3523 | return ag->codegen->invalid_inst_src; | ||
| 3524 | Stage1ZirBasicBlock *post_val1_block = ag->current_basic_block; | ||
| 3525 | |||
| 3526 | IrInstSrc *is_comptime; | ||
| 3527 | if (ir_should_inline(ag->exec, scope)) { | ||
| 3528 | is_comptime = ir_build_const_bool(ag, scope, node, true); | ||
| 3529 | } else { | ||
| 3530 | is_comptime = ir_build_test_comptime(ag, scope, node, val1); | ||
| 3531 | } | ||
| 3532 | |||
| 3533 | // block for when val1 == true | ||
| 3534 | Stage1ZirBasicBlock *true_block = ir_create_basic_block(ag, scope, "BoolAndTrue"); | ||
| 3535 | // block for when val1 == false (don't even evaluate the second part) | ||
| 3536 | Stage1ZirBasicBlock *false_block = ir_create_basic_block(ag, scope, "BoolAndFalse"); | ||
| 3537 | |||
| 3538 | ir_build_cond_br(ag, scope, node, val1, true_block, false_block, is_comptime); | ||
| 3539 | |||
| 3540 | ir_set_cursor_at_end_and_append_block(ag, true_block); | ||
| 3541 | IrInstSrc *val2 = astgen_node(ag, node->data.bin_op_expr.op2, scope); | ||
| 3542 | if (val2 == ag->codegen->invalid_inst_src) | ||
| 3543 | return ag->codegen->invalid_inst_src; | ||
| 3544 | Stage1ZirBasicBlock *post_val2_block = ag->current_basic_block; | ||
| 3545 | |||
| 3546 | ir_build_br(ag, scope, node, false_block, is_comptime); | ||
| 3547 | |||
| 3548 | ir_set_cursor_at_end_and_append_block(ag, false_block); | ||
| 3549 | |||
| 3550 | IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2); | ||
| 3551 | incoming_values[0] = val1; | ||
| 3552 | incoming_values[1] = val2; | ||
| 3553 | Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate<Stage1ZirBasicBlock *>(2); | ||
| 3554 | incoming_blocks[0] = post_val1_block; | ||
| 3555 | incoming_blocks[1] = post_val2_block; | ||
| 3556 | |||
| 3557 | return ir_build_phi(ag, scope, node, 2, incoming_blocks, incoming_values, nullptr); | ||
| 3558 | } | ||
| 3559 | |||
| 3560 | static ResultLocPeerParent *ir_build_result_peers(Stage1AstGen *ag, IrInstSrc *cond_br_inst, | ||
| 3561 | Stage1ZirBasicBlock *end_block, ResultLoc *parent, IrInstSrc *is_comptime) | ||
| 3562 | { | ||
| 3563 | ResultLocPeerParent *peer_parent = heap::c_allocator.create<ResultLocPeerParent>(); | ||
| 3564 | peer_parent->base.id = ResultLocIdPeerParent; | ||
| 3565 | peer_parent->base.source_instruction = cond_br_inst; | ||
| 3566 | peer_parent->base.allow_write_through_const = parent->allow_write_through_const; | ||
| 3567 | peer_parent->end_bb = end_block; | ||
| 3568 | peer_parent->is_comptime = is_comptime; | ||
| 3569 | peer_parent->parent = parent; | ||
| 3570 | |||
| 3571 | IrInstSrc *popped_inst = ag->current_basic_block->instruction_list.pop(); | ||
| 3572 | ir_assert(popped_inst == cond_br_inst, &cond_br_inst->base); | ||
| 3573 | |||
| 3574 | ir_build_reset_result(ag, cond_br_inst->base.scope, cond_br_inst->base.source_node, &peer_parent->base); | ||
| 3575 | ag->current_basic_block->instruction_list.append(popped_inst); | ||
| 3576 | |||
| 3577 | return peer_parent; | ||
| 3578 | } | ||
| 3579 | |||
| 3580 | static ResultLocPeerParent *ir_build_binary_result_peers(Stage1AstGen *ag, IrInstSrc *cond_br_inst, | ||
| 3581 | Stage1ZirBasicBlock *else_block, Stage1ZirBasicBlock *end_block, ResultLoc *parent, IrInstSrc *is_comptime) | ||
| 3582 | { | ||
| 3583 | ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, parent, is_comptime); | ||
| 3584 | |||
| 3585 | peer_parent->peers.append(create_peer_result(peer_parent)); | ||
| 3586 | peer_parent->peers.last()->next_bb = else_block; | ||
| 3587 | |||
| 3588 | peer_parent->peers.append(create_peer_result(peer_parent)); | ||
| 3589 | peer_parent->peers.last()->next_bb = end_block; | ||
| 3590 | |||
| 3591 | return peer_parent; | ||
| 3592 | } | ||
| 3593 | |||
| 3594 | static IrInstSrc *astgen_orelse(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval, | ||
| 3595 | ResultLoc *result_loc) | ||
| 3596 | { | ||
| 3597 | assert(node->type == NodeTypeBinOpExpr); | ||
| 3598 | |||
| 3599 | AstNode *op1_node = node->data.bin_op_expr.op1; | ||
| 3600 | AstNode *op2_node = node->data.bin_op_expr.op2; | ||
| 3601 | |||
| 3602 | IrInstSrc *maybe_ptr = astgen_node_extra(ag, op1_node, parent_scope, LValPtr, nullptr); | ||
| 3603 | if (maybe_ptr == ag->codegen->invalid_inst_src) | ||
| 3604 | return ag->codegen->invalid_inst_src; | ||
| 3605 | |||
| 3606 | IrInstSrc *maybe_val = ir_build_load_ptr(ag, parent_scope, node, maybe_ptr); | ||
| 3607 | IrInstSrc *is_non_null = ir_build_test_non_null_src(ag, parent_scope, node, maybe_val); | ||
| 3608 | |||
| 3609 | IrInstSrc *is_comptime; | ||
| 3610 | if (ir_should_inline(ag->exec, parent_scope)) { | ||
| 3611 | is_comptime = ir_build_const_bool(ag, parent_scope, node, true); | ||
| 3612 | } else { | ||
| 3613 | is_comptime = ir_build_test_comptime(ag, parent_scope, node, is_non_null); | ||
| 3614 | } | ||
| 3615 | |||
| 3616 | Stage1ZirBasicBlock *ok_block = ir_create_basic_block(ag, parent_scope, "OptionalNonNull"); | ||
| 3617 | Stage1ZirBasicBlock *null_block = ir_create_basic_block(ag, parent_scope, "OptionalNull"); | ||
| 3618 | Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, parent_scope, "OptionalEnd"); | ||
| 3619 | IrInstSrc *cond_br_inst = ir_build_cond_br(ag, parent_scope, node, is_non_null, ok_block, null_block, is_comptime); | ||
| 3620 | |||
| 3621 | ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, ok_block, end_block, | ||
| 3622 | result_loc, is_comptime); | ||
| 3623 | |||
| 3624 | ir_set_cursor_at_end_and_append_block(ag, null_block); | ||
| 3625 | IrInstSrc *null_result = astgen_node_extra(ag, op2_node, parent_scope, LValNone, | ||
| 3626 | &peer_parent->peers.at(0)->base); | ||
| 3627 | if (null_result == ag->codegen->invalid_inst_src) | ||
| 3628 | return ag->codegen->invalid_inst_src; | ||
| 3629 | Stage1ZirBasicBlock *after_null_block = ag->current_basic_block; | ||
| 3630 | if (!instr_is_unreachable(null_result)) | ||
| 3631 | ir_mark_gen(ir_build_br(ag, parent_scope, node, end_block, is_comptime)); | ||
| 3632 | |||
| 3633 | ir_set_cursor_at_end_and_append_block(ag, ok_block); | ||
| 3634 | IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(ag, parent_scope, node, maybe_ptr, false); | ||
| 3635 | IrInstSrc *unwrapped_payload = ir_build_load_ptr(ag, parent_scope, node, unwrapped_ptr); | ||
| 3636 | ir_build_end_expr(ag, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); | ||
| 3637 | Stage1ZirBasicBlock *after_ok_block = ag->current_basic_block; | ||
| 3638 | ir_build_br(ag, parent_scope, node, end_block, is_comptime); | ||
| 3639 | |||
| 3640 | ir_set_cursor_at_end_and_append_block(ag, end_block); | ||
| 3641 | IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2); | ||
| 3642 | incoming_values[0] = null_result; | ||
| 3643 | incoming_values[1] = unwrapped_payload; | ||
| 3644 | Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate<Stage1ZirBasicBlock *>(2); | ||
| 3645 | incoming_blocks[0] = after_null_block; | ||
| 3646 | incoming_blocks[1] = after_ok_block; | ||
| 3647 | IrInstSrc *phi = ir_build_phi(ag, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); | ||
| 3648 | return ir_lval_wrap(ag, parent_scope, phi, lval, result_loc); | ||
| 3649 | } | ||
| 3650 | |||
| 3651 | static IrInstSrc *astgen_error_union(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { | ||
| 3652 | assert(node->type == NodeTypeBinOpExpr); | ||
| 3653 | |||
| 3654 | AstNode *op1_node = node->data.bin_op_expr.op1; | ||
| 3655 | AstNode *op2_node = node->data.bin_op_expr.op2; | ||
| 3656 | |||
| 3657 | IrInstSrc *err_set = astgen_node(ag, op1_node, parent_scope); | ||
| 3658 | if (err_set == ag->codegen->invalid_inst_src) | ||
| 3659 | return ag->codegen->invalid_inst_src; | ||
| 3660 | |||
| 3661 | IrInstSrc *payload = astgen_node(ag, op2_node, parent_scope); | ||
| 3662 | if (payload == ag->codegen->invalid_inst_src) | ||
| 3663 | return ag->codegen->invalid_inst_src; | ||
| 3664 | |||
| 3665 | return ir_build_error_union(ag, parent_scope, node, err_set, payload); | ||
| 3666 | } | ||
| 3667 | |||
| 3668 | static IrInstSrc *astgen_bin_op(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { | ||
| 3669 | assert(node->type == NodeTypeBinOpExpr); | ||
| 3670 | |||
| 3671 | BinOpType bin_op_type = node->data.bin_op_expr.bin_op; | ||
| 3672 | switch (bin_op_type) { | ||
| 3673 | case BinOpTypeInvalid: | ||
| 3674 | zig_unreachable(); | ||
| 3675 | case BinOpTypeAssign: | ||
| 3676 | return ir_lval_wrap(ag, scope, astgen_assign(ag, scope, node), lval, result_loc); | ||
| 3677 | case BinOpTypeAssignTimes: | ||
| 3678 | return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpMult), lval, result_loc); | ||
| 3679 | case BinOpTypeAssignTimesWrap: | ||
| 3680 | return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpMultWrap), lval, result_loc); | ||
| 3681 | case BinOpTypeAssignDiv: | ||
| 3682 | return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpDivUnspecified), lval, result_loc); | ||
| 3683 | case BinOpTypeAssignMod: | ||
| 3684 | return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpRemUnspecified), lval, result_loc); | ||
| 3685 | case BinOpTypeAssignPlus: | ||
| 3686 | return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpAdd), lval, result_loc); | ||
| 3687 | case BinOpTypeAssignPlusWrap: | ||
| 3688 | return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpAddWrap), lval, result_loc); | ||
| 3689 | case BinOpTypeAssignMinus: | ||
| 3690 | return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpSub), lval, result_loc); | ||
| 3691 | case BinOpTypeAssignMinusWrap: | ||
| 3692 | return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpSubWrap), lval, result_loc); | ||
| 3693 | case BinOpTypeAssignBitShiftLeft: | ||
| 3694 | return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); | ||
| 3695 | case BinOpTypeAssignBitShiftRight: | ||
| 3696 | return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); | ||
| 3697 | case BinOpTypeAssignBitAnd: | ||
| 3698 | return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBinAnd), lval, result_loc); | ||
| 3699 | case BinOpTypeAssignBitXor: | ||
| 3700 | return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBinXor), lval, result_loc); | ||
| 3701 | case BinOpTypeAssignBitOr: | ||
| 3702 | return ir_lval_wrap(ag, scope, astgen_assign_op(ag, scope, node, IrBinOpBinOr), lval, result_loc); | ||
| 3703 | case BinOpTypeBoolOr: | ||
| 3704 | return ir_lval_wrap(ag, scope, astgen_bool_or(ag, scope, node), lval, result_loc); | ||
| 3705 | case BinOpTypeBoolAnd: | ||
| 3706 | return ir_lval_wrap(ag, scope, astgen_bool_and(ag, scope, node), lval, result_loc); | ||
| 3707 | case BinOpTypeCmpEq: | ||
| 3708 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpEq), lval, result_loc); | ||
| 3709 | case BinOpTypeCmpNotEq: | ||
| 3710 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpNotEq), lval, result_loc); | ||
| 3711 | case BinOpTypeCmpLessThan: | ||
| 3712 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpLessThan), lval, result_loc); | ||
| 3713 | case BinOpTypeCmpGreaterThan: | ||
| 3714 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpGreaterThan), lval, result_loc); | ||
| 3715 | case BinOpTypeCmpLessOrEq: | ||
| 3716 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpLessOrEq), lval, result_loc); | ||
| 3717 | case BinOpTypeCmpGreaterOrEq: | ||
| 3718 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpCmpGreaterOrEq), lval, result_loc); | ||
| 3719 | case BinOpTypeBinOr: | ||
| 3720 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBinOr), lval, result_loc); | ||
| 3721 | case BinOpTypeBinXor: | ||
| 3722 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBinXor), lval, result_loc); | ||
| 3723 | case BinOpTypeBinAnd: | ||
| 3724 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBinAnd), lval, result_loc); | ||
| 3725 | case BinOpTypeBitShiftLeft: | ||
| 3726 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); | ||
| 3727 | case BinOpTypeBitShiftRight: | ||
| 3728 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); | ||
| 3729 | case BinOpTypeAdd: | ||
| 3730 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpAdd), lval, result_loc); | ||
| 3731 | case BinOpTypeAddWrap: | ||
| 3732 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpAddWrap), lval, result_loc); | ||
| 3733 | case BinOpTypeSub: | ||
| 3734 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpSub), lval, result_loc); | ||
| 3735 | case BinOpTypeSubWrap: | ||
| 3736 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpSubWrap), lval, result_loc); | ||
| 3737 | case BinOpTypeMult: | ||
| 3738 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpMult), lval, result_loc); | ||
| 3739 | case BinOpTypeMultWrap: | ||
| 3740 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpMultWrap), lval, result_loc); | ||
| 3741 | case BinOpTypeDiv: | ||
| 3742 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpDivUnspecified), lval, result_loc); | ||
| 3743 | case BinOpTypeMod: | ||
| 3744 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpRemUnspecified), lval, result_loc); | ||
| 3745 | case BinOpTypeArrayCat: | ||
| 3746 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpArrayCat), lval, result_loc); | ||
| 3747 | case BinOpTypeArrayMult: | ||
| 3748 | return ir_lval_wrap(ag, scope, astgen_bin_op_id(ag, scope, node, IrBinOpArrayMult), lval, result_loc); | ||
| 3749 | case BinOpTypeMergeErrorSets: | ||
| 3750 | return ir_lval_wrap(ag, scope, astgen_merge_err_sets(ag, scope, node), lval, result_loc); | ||
| 3751 | case BinOpTypeUnwrapOptional: | ||
| 3752 | return astgen_orelse(ag, scope, node, lval, result_loc); | ||
| 3753 | case BinOpTypeErrorUnion: | ||
| 3754 | return ir_lval_wrap(ag, scope, astgen_error_union(ag, scope, node), lval, result_loc); | ||
| 3755 | } | ||
| 3756 | zig_unreachable(); | ||
| 3757 | } | ||
| 3758 | |||
| 3759 | static IrInstSrc *astgen_int_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 3760 | assert(node->type == NodeTypeIntLiteral); | ||
| 3761 | |||
| 3762 | RootStruct *root_struct = node->owner->data.structure.root_struct; | ||
| 3763 | BigInt bigint; | ||
| 3764 | token_number_literal_bigint(root_struct, &bigint, node->main_token); | ||
| 3765 | return ir_build_const_bigint(ag, scope, node, bigint); | ||
| 3766 | } | ||
| 3767 | |||
| 3768 | static IrInstSrc *astgen_float_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 3769 | Error err; | ||
| 3770 | assert(node->type == NodeTypeFloatLiteral); | ||
| 3771 | |||
| 3772 | RootStruct *root_struct = node->owner->data.structure.root_struct; | ||
| 3773 | const char *source = buf_ptr(root_struct->source_code); | ||
| 3774 | uint32_t byte_offset = root_struct->token_locs[node->main_token].offset; | ||
| 3775 | |||
| 3776 | BigFloat bigfloat; | ||
| 3777 | if ((err = bigfloat_init_buf(&bigfloat, (const uint8_t *)source + byte_offset))) { | ||
| 3778 | add_node_error(ag->codegen, node, buf_sprintf("float literal out of range of any type")); | ||
| 3779 | return ag->codegen->invalid_inst_src; | ||
| 3780 | } | ||
| 3781 | |||
| 3782 | return ir_build_const_bigfloat(ag, scope, node, bigfloat); | ||
| 3783 | } | ||
| 3784 | |||
| 3785 | static IrInstSrc *astgen_char_lit(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 3786 | Error err; | ||
| 3787 | assert(node->type == NodeTypeCharLiteral); | ||
| 3788 | |||
| 3789 | RootStruct *root_struct = node->owner->data.structure.root_struct; | ||
| 3790 | const char *source = buf_ptr(root_struct->source_code); | ||
| 3791 | uint32_t byte_offset = root_struct->token_locs[node->main_token].offset; | ||
| 3792 | |||
| 3793 | src_assert(source[byte_offset] == '\'', node); | ||
| 3794 | byte_offset += 1; | ||
| 3795 | |||
| 3796 | uint32_t codepoint; | ||
| 3797 | size_t bad_index; | ||
| 3798 | if ((err = source_char_literal(source + byte_offset, &codepoint, &bad_index))) { | ||
| 3799 | add_node_error(ag->codegen, node, buf_sprintf("invalid character")); | ||
| 3800 | return ag->codegen->invalid_inst_src; | ||
| 3801 | } | ||
| 3802 | return ir_build_const_uint(ag, scope, node, codepoint); | ||
| 3803 | } | ||
| 3804 | |||
| 3805 | static IrInstSrc *astgen_null_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 3806 | assert(node->type == NodeTypeNullLiteral); | ||
| 3807 | |||
| 3808 | return ir_build_const_null(ag, scope, node); | ||
| 3809 | } | ||
| 3810 | |||
| 3811 | static IrInstSrc *astgen_identifier(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, | ||
| 3812 | ResultLoc *result_loc) | ||
| 3813 | { | ||
| 3814 | Error err; | ||
| 3815 | assert(node->type == NodeTypeIdentifier); | ||
| 3816 | |||
| 3817 | Buf *variable_name = node_identifier_buf(node); | ||
| 3818 | |||
| 3819 | if (buf_eql_str(variable_name, "_")) { | ||
| 3820 | if (lval == LValAssign) { | ||
| 3821 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(ag, scope, node); | ||
| 3822 | const_instruction->value = ag->codegen->pass1_arena->create<ZigValue>(); | ||
| 3823 | const_instruction->value->type = get_pointer_to_type(ag->codegen, | ||
| 3824 | ag->codegen->builtin_types.entry_void, false); | ||
| 3825 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 3826 | const_instruction->value->data.x_ptr.special = ConstPtrSpecialDiscard; | ||
| 3827 | return &const_instruction->base; | ||
| 3828 | } else { | ||
| 3829 | add_node_error(ag->codegen, node, buf_sprintf("`_` may only be used to assign things to")); | ||
| 3830 | return ag->codegen->invalid_inst_src; | ||
| 3831 | } | ||
| 3832 | } | ||
| 3833 | |||
| 3834 | ZigType *primitive_type; | ||
| 3835 | if ((err = get_primitive_type(ag->codegen, variable_name, &primitive_type))) { | ||
| 3836 | if (err == ErrorOverflow) { | ||
| 3837 | add_node_error(ag->codegen, node, | ||
| 3838 | buf_sprintf("primitive integer type '%s' exceeds maximum bit width of 65535", | ||
| 3839 | buf_ptr(variable_name))); | ||
| 3840 | return ag->codegen->invalid_inst_src; | ||
| 3841 | } | ||
| 3842 | assert(err == ErrorPrimitiveTypeNotFound); | ||
| 3843 | } else { | ||
| 3844 | IrInstSrc *value = ir_build_const_type(ag, scope, node, primitive_type); | ||
| 3845 | if (lval == LValPtr || lval == LValAssign) { | ||
| 3846 | return ir_build_ref_src(ag, scope, node, value); | ||
| 3847 | } else { | ||
| 3848 | return ir_expr_wrap(ag, scope, value, result_loc); | ||
| 3849 | } | ||
| 3850 | } | ||
| 3851 | |||
| 3852 | ScopeFnDef *crossed_fndef_scope; | ||
| 3853 | ZigVar *var = find_variable(ag->codegen, scope, variable_name, &crossed_fndef_scope); | ||
| 3854 | if (var) { | ||
| 3855 | IrInstSrc *var_ptr = ir_build_var_ptr_x(ag, scope, node, var, crossed_fndef_scope); | ||
| 3856 | if (lval == LValPtr || lval == LValAssign) { | ||
| 3857 | return var_ptr; | ||
| 3858 | } else { | ||
| 3859 | return ir_expr_wrap(ag, scope, ir_build_load_ptr(ag, scope, node, var_ptr), result_loc); | ||
| 3860 | } | ||
| 3861 | } | ||
| 3862 | |||
| 3863 | Tld *tld = find_decl(ag->codegen, scope, variable_name); | ||
| 3864 | if (tld) { | ||
| 3865 | IrInstSrc *decl_ref = ir_build_decl_ref(ag, scope, node, tld, lval); | ||
| 3866 | if (lval == LValPtr || lval == LValAssign) { | ||
| 3867 | return decl_ref; | ||
| 3868 | } else { | ||
| 3869 | return ir_expr_wrap(ag, scope, decl_ref, result_loc); | ||
| 3870 | } | ||
| 3871 | } | ||
| 3872 | |||
| 3873 | if (get_container_scope(node->owner)->any_imports_failed) { | ||
| 3874 | // skip the error message since we had a failing import in this file | ||
| 3875 | // if an import breaks we don't need redundant undeclared identifier errors | ||
| 3876 | return ag->codegen->invalid_inst_src; | ||
| 3877 | } | ||
| 3878 | |||
| 3879 | return ir_build_undeclared_identifier(ag, scope, node, variable_name); | ||
| 3880 | } | ||
| 3881 | |||
| 3882 | static IrInstSrc *astgen_array_access(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, | ||
| 3883 | ResultLoc *result_loc) | ||
| 3884 | { | ||
| 3885 | assert(node->type == NodeTypeArrayAccessExpr); | ||
| 3886 | |||
| 3887 | AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr; | ||
| 3888 | IrInstSrc *array_ref_instruction = astgen_node_extra(ag, array_ref_node, scope, LValPtr, nullptr); | ||
| 3889 | if (array_ref_instruction == ag->codegen->invalid_inst_src) | ||
| 3890 | return array_ref_instruction; | ||
| 3891 | |||
| 3892 | // Create an usize-typed result location to hold the subscript value, this | ||
| 3893 | // makes it possible for the compiler to infer the subscript expression type | ||
| 3894 | // if needed | ||
| 3895 | IrInstSrc *usize_type_inst = ir_build_const_type(ag, scope, node, ag->codegen->builtin_types.entry_usize); | ||
| 3896 | ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, usize_type_inst, no_result_loc()); | ||
| 3897 | |||
| 3898 | AstNode *subscript_node = node->data.array_access_expr.subscript; | ||
| 3899 | IrInstSrc *subscript_value = astgen_node_extra(ag, subscript_node, scope, LValNone, &result_loc_cast->base); | ||
| 3900 | if (subscript_value == ag->codegen->invalid_inst_src) | ||
| 3901 | return ag->codegen->invalid_inst_src; | ||
| 3902 | |||
| 3903 | IrInstSrc *subscript_instruction = ir_build_implicit_cast(ag, scope, subscript_node, subscript_value, result_loc_cast); | ||
| 3904 | |||
| 3905 | IrInstSrc *ptr_instruction = ir_build_elem_ptr(ag, scope, node, array_ref_instruction, | ||
| 3906 | subscript_instruction, true, PtrLenSingle, nullptr); | ||
| 3907 | if (lval == LValPtr || lval == LValAssign) | ||
| 3908 | return ptr_instruction; | ||
| 3909 | |||
| 3910 | IrInstSrc *load_ptr = ir_build_load_ptr(ag, scope, node, ptr_instruction); | ||
| 3911 | return ir_expr_wrap(ag, scope, load_ptr, result_loc); | ||
| 3912 | } | ||
| 3913 | |||
| 3914 | static IrInstSrc *astgen_field_access(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 3915 | assert(node->type == NodeTypeFieldAccessExpr); | ||
| 3916 | |||
| 3917 | AstNode *container_ref_node = node->data.field_access_expr.struct_expr; | ||
| 3918 | Buf *field_name = node->data.field_access_expr.field_name; | ||
| 3919 | |||
| 3920 | IrInstSrc *container_ref_instruction = astgen_node_extra(ag, container_ref_node, scope, LValPtr, nullptr); | ||
| 3921 | if (container_ref_instruction == ag->codegen->invalid_inst_src) | ||
| 3922 | return container_ref_instruction; | ||
| 3923 | |||
| 3924 | return ir_build_field_ptr(ag, scope, node, container_ref_instruction, field_name, false); | ||
| 3925 | } | ||
| 3926 | |||
| 3927 | static IrInstSrc *astgen_overflow_op(Stage1AstGen *ag, Scope *scope, AstNode *node, IrOverflowOp op) { | ||
| 3928 | assert(node->type == NodeTypeFnCallExpr); | ||
| 3929 | |||
| 3930 | AstNode *type_node = node->data.fn_call_expr.params.at(0); | ||
| 3931 | AstNode *op1_node = node->data.fn_call_expr.params.at(1); | ||
| 3932 | AstNode *op2_node = node->data.fn_call_expr.params.at(2); | ||
| 3933 | AstNode *result_ptr_node = node->data.fn_call_expr.params.at(3); | ||
| 3934 | |||
| 3935 | |||
| 3936 | IrInstSrc *type_value = astgen_node(ag, type_node, scope); | ||
| 3937 | if (type_value == ag->codegen->invalid_inst_src) | ||
| 3938 | return ag->codegen->invalid_inst_src; | ||
| 3939 | |||
| 3940 | IrInstSrc *op1 = astgen_node(ag, op1_node, scope); | ||
| 3941 | if (op1 == ag->codegen->invalid_inst_src) | ||
| 3942 | return ag->codegen->invalid_inst_src; | ||
| 3943 | |||
| 3944 | IrInstSrc *op2 = astgen_node(ag, op2_node, scope); | ||
| 3945 | if (op2 == ag->codegen->invalid_inst_src) | ||
| 3946 | return ag->codegen->invalid_inst_src; | ||
| 3947 | |||
| 3948 | IrInstSrc *result_ptr = astgen_node(ag, result_ptr_node, scope); | ||
| 3949 | if (result_ptr == ag->codegen->invalid_inst_src) | ||
| 3950 | return ag->codegen->invalid_inst_src; | ||
| 3951 | |||
| 3952 | return ir_build_overflow_op_src(ag, scope, node, op, type_value, op1, op2, result_ptr); | ||
| 3953 | } | ||
| 3954 | |||
| 3955 | static IrInstSrc *astgen_mul_add(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 3956 | assert(node->type == NodeTypeFnCallExpr); | ||
| 3957 | |||
| 3958 | AstNode *type_node = node->data.fn_call_expr.params.at(0); | ||
| 3959 | AstNode *op1_node = node->data.fn_call_expr.params.at(1); | ||
| 3960 | AstNode *op2_node = node->data.fn_call_expr.params.at(2); | ||
| 3961 | AstNode *op3_node = node->data.fn_call_expr.params.at(3); | ||
| 3962 | |||
| 3963 | IrInstSrc *type_value = astgen_node(ag, type_node, scope); | ||
| 3964 | if (type_value == ag->codegen->invalid_inst_src) | ||
| 3965 | return ag->codegen->invalid_inst_src; | ||
| 3966 | |||
| 3967 | IrInstSrc *op1 = astgen_node(ag, op1_node, scope); | ||
| 3968 | if (op1 == ag->codegen->invalid_inst_src) | ||
| 3969 | return ag->codegen->invalid_inst_src; | ||
| 3970 | |||
| 3971 | IrInstSrc *op2 = astgen_node(ag, op2_node, scope); | ||
| 3972 | if (op2 == ag->codegen->invalid_inst_src) | ||
| 3973 | return ag->codegen->invalid_inst_src; | ||
| 3974 | |||
| 3975 | IrInstSrc *op3 = astgen_node(ag, op3_node, scope); | ||
| 3976 | if (op3 == ag->codegen->invalid_inst_src) | ||
| 3977 | return ag->codegen->invalid_inst_src; | ||
| 3978 | |||
| 3979 | return ir_build_mul_add_src(ag, scope, node, type_value, op1, op2, op3); | ||
| 3980 | } | ||
| 3981 | |||
| 3982 | static IrInstSrc *astgen_this(Stage1AstGen *ag, Scope *orig_scope, AstNode *node) { | ||
| 3983 | for (Scope *it_scope = orig_scope; it_scope != nullptr; it_scope = it_scope->parent) { | ||
| 3984 | if (it_scope->id == ScopeIdDecls) { | ||
| 3985 | ScopeDecls *decls_scope = (ScopeDecls *)it_scope; | ||
| 3986 | ZigType *container_type = decls_scope->container_type; | ||
| 3987 | if (container_type != nullptr) { | ||
| 3988 | return ir_build_const_type(ag, orig_scope, node, container_type); | ||
| 3989 | } else { | ||
| 3990 | return ir_build_const_import(ag, orig_scope, node, decls_scope->import); | ||
| 3991 | } | ||
| 3992 | } | ||
| 3993 | } | ||
| 3994 | zig_unreachable(); | ||
| 3995 | } | ||
| 3996 | |||
| 3997 | static IrInstSrc *astgen_async_call(Stage1AstGen *ag, Scope *scope, AstNode *await_node, AstNode *call_node, | ||
| 3998 | LVal lval, ResultLoc *result_loc) | ||
| 3999 | { | ||
| 4000 | if (call_node->data.fn_call_expr.params.length != 4) { | ||
| 4001 | add_node_error(ag->codegen, call_node, | ||
| 4002 | buf_sprintf("expected 4 arguments, found %" ZIG_PRI_usize, | ||
| 4003 | call_node->data.fn_call_expr.params.length)); | ||
| 4004 | return ag->codegen->invalid_inst_src; | ||
| 4005 | } | ||
| 4006 | |||
| 4007 | AstNode *bytes_node = call_node->data.fn_call_expr.params.at(0); | ||
| 4008 | IrInstSrc *bytes = astgen_node(ag, bytes_node, scope); | ||
| 4009 | if (bytes == ag->codegen->invalid_inst_src) | ||
| 4010 | return bytes; | ||
| 4011 | |||
| 4012 | AstNode *ret_ptr_node = call_node->data.fn_call_expr.params.at(1); | ||
| 4013 | IrInstSrc *ret_ptr = astgen_node(ag, ret_ptr_node, scope); | ||
| 4014 | if (ret_ptr == ag->codegen->invalid_inst_src) | ||
| 4015 | return ret_ptr; | ||
| 4016 | |||
| 4017 | AstNode *fn_ref_node = call_node->data.fn_call_expr.params.at(2); | ||
| 4018 | IrInstSrc *fn_ref = astgen_node(ag, fn_ref_node, scope); | ||
| 4019 | if (fn_ref == ag->codegen->invalid_inst_src) | ||
| 4020 | return fn_ref; | ||
| 4021 | |||
| 4022 | CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone; | ||
| 4023 | bool is_async_call_builtin = true; | ||
| 4024 | AstNode *args_node = call_node->data.fn_call_expr.params.at(3); | ||
| 4025 | if (args_node->type == NodeTypeContainerInitExpr) { | ||
| 4026 | if (args_node->data.container_init_expr.kind == ContainerInitKindArray || | ||
| 4027 | args_node->data.container_init_expr.entries.length == 0) | ||
| 4028 | { | ||
| 4029 | size_t arg_count = args_node->data.container_init_expr.entries.length; | ||
| 4030 | IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(arg_count); | ||
| 4031 | for (size_t i = 0; i < arg_count; i += 1) { | ||
| 4032 | AstNode *arg_node = args_node->data.container_init_expr.entries.at(i); | ||
| 4033 | IrInstSrc *arg = astgen_node(ag, arg_node, scope); | ||
| 4034 | if (arg == ag->codegen->invalid_inst_src) | ||
| 4035 | return arg; | ||
| 4036 | args[i] = arg; | ||
| 4037 | } | ||
| 4038 | |||
| 4039 | IrInstSrc *call = ir_build_call_src(ag, scope, call_node, nullptr, fn_ref, arg_count, args, | ||
| 4040 | ret_ptr, modifier, is_async_call_builtin, bytes, result_loc); | ||
| 4041 | return ir_lval_wrap(ag, scope, call, lval, result_loc); | ||
| 4042 | } else { | ||
| 4043 | exec_add_error_node(ag->codegen, ag->exec, args_node, | ||
| 4044 | buf_sprintf("TODO: @asyncCall with anon struct literal")); | ||
| 4045 | return ag->codegen->invalid_inst_src; | ||
| 4046 | } | ||
| 4047 | } | ||
| 4048 | IrInstSrc *args = astgen_node(ag, args_node, scope); | ||
| 4049 | if (args == ag->codegen->invalid_inst_src) | ||
| 4050 | return args; | ||
| 4051 | |||
| 4052 | IrInstSrc *call = ir_build_async_call_extra(ag, scope, call_node, modifier, fn_ref, ret_ptr, bytes, args, result_loc); | ||
| 4053 | return ir_lval_wrap(ag, scope, call, lval, result_loc); | ||
| 4054 | } | ||
| 4055 | |||
| 4056 | static IrInstSrc *astgen_fn_call_with_args(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 4057 | AstNode *fn_ref_node, CallModifier modifier, IrInstSrc *options, | ||
| 4058 | AstNode **args_ptr, size_t args_len, LVal lval, ResultLoc *result_loc) | ||
| 4059 | { | ||
| 4060 | IrInstSrc *fn_ref = astgen_node(ag, fn_ref_node, scope); | ||
| 4061 | if (fn_ref == ag->codegen->invalid_inst_src) | ||
| 4062 | return fn_ref; | ||
| 4063 | |||
| 4064 | IrInstSrc *fn_type = ir_build_typeof_1(ag, scope, source_node, fn_ref); | ||
| 4065 | |||
| 4066 | IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(args_len); | ||
| 4067 | for (size_t i = 0; i < args_len; i += 1) { | ||
| 4068 | AstNode *arg_node = args_ptr[i]; | ||
| 4069 | |||
| 4070 | IrInstSrc *arg_index = ir_build_const_usize(ag, scope, arg_node, i); | ||
| 4071 | IrInstSrc *arg_type = ir_build_arg_type(ag, scope, source_node, fn_type, arg_index, true); | ||
| 4072 | ResultLoc *no_result = no_result_loc(); | ||
| 4073 | ir_build_reset_result(ag, scope, source_node, no_result); | ||
| 4074 | ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, arg_type, no_result); | ||
| 4075 | |||
| 4076 | IrInstSrc *arg = astgen_node_extra(ag, arg_node, scope, LValNone, &result_loc_cast->base); | ||
| 4077 | if (arg == ag->codegen->invalid_inst_src) | ||
| 4078 | return arg; | ||
| 4079 | |||
| 4080 | args[i] = ir_build_implicit_cast(ag, scope, arg_node, arg, result_loc_cast); | ||
| 4081 | } | ||
| 4082 | |||
| 4083 | IrInstSrc *fn_call; | ||
| 4084 | if (options != nullptr) { | ||
| 4085 | fn_call = ir_build_call_args(ag, scope, source_node, options, fn_ref, args, args_len, result_loc); | ||
| 4086 | } else { | ||
| 4087 | fn_call = ir_build_call_src(ag, scope, source_node, nullptr, fn_ref, args_len, args, nullptr, | ||
| 4088 | modifier, false, nullptr, result_loc); | ||
| 4089 | } | ||
| 4090 | return ir_lval_wrap(ag, scope, fn_call, lval, result_loc); | ||
| 4091 | } | ||
| 4092 | |||
| 4093 | static IrInstSrc *astgen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, | ||
| 4094 | ResultLoc *result_loc) | ||
| 4095 | { | ||
| 4096 | assert(node->type == NodeTypeFnCallExpr); | ||
| 4097 | |||
| 4098 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; | ||
| 4099 | Buf *name = node_identifier_buf(fn_ref_expr); | ||
| 4100 | auto entry = ag->codegen->builtin_fn_table.maybe_get(name); | ||
| 4101 | |||
| 4102 | if (!entry) { | ||
| 4103 | add_node_error(ag->codegen, node, | ||
| 4104 | buf_sprintf("invalid builtin function: '%s'", buf_ptr(name))); | ||
| 4105 | return ag->codegen->invalid_inst_src; | ||
| 4106 | } | ||
| 4107 | |||
| 4108 | BuiltinFnEntry *builtin_fn = entry->value; | ||
| 4109 | size_t actual_param_count = node->data.fn_call_expr.params.length; | ||
| 4110 | |||
| 4111 | if (builtin_fn->param_count != SIZE_MAX && builtin_fn->param_count != actual_param_count) { | ||
| 4112 | add_node_error(ag->codegen, node, | ||
| 4113 | buf_sprintf("expected %" ZIG_PRI_usize " argument(s), found %" ZIG_PRI_usize, | ||
| 4114 | builtin_fn->param_count, actual_param_count)); | ||
| 4115 | return ag->codegen->invalid_inst_src; | ||
| 4116 | } | ||
| 4117 | |||
| 4118 | switch (builtin_fn->id) { | ||
| 4119 | case BuiltinFnIdInvalid: | ||
| 4120 | zig_unreachable(); | ||
| 4121 | case BuiltinFnIdTypeof: | ||
| 4122 | { | ||
| 4123 | Scope *sub_scope = create_typeof_scope(ag->codegen, node, scope); | ||
| 4124 | |||
| 4125 | size_t arg_count = node->data.fn_call_expr.params.length; | ||
| 4126 | |||
| 4127 | IrInstSrc *type_of; | ||
| 4128 | |||
| 4129 | if (arg_count == 0) { | ||
| 4130 | add_node_error(ag->codegen, node, | ||
| 4131 | buf_sprintf("expected at least 1 argument, found 0")); | ||
| 4132 | return ag->codegen->invalid_inst_src; | ||
| 4133 | } else if (arg_count == 1) { | ||
| 4134 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4135 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, sub_scope); | ||
| 4136 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4137 | return arg0_value; | ||
| 4138 | |||
| 4139 | type_of = ir_build_typeof_1(ag, scope, node, arg0_value); | ||
| 4140 | } else { | ||
| 4141 | IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(arg_count); | ||
| 4142 | for (size_t i = 0; i < arg_count; i += 1) { | ||
| 4143 | AstNode *arg_node = node->data.fn_call_expr.params.at(i); | ||
| 4144 | IrInstSrc *arg = astgen_node(ag, arg_node, sub_scope); | ||
| 4145 | if (arg == ag->codegen->invalid_inst_src) | ||
| 4146 | return ag->codegen->invalid_inst_src; | ||
| 4147 | args[i] = arg; | ||
| 4148 | } | ||
| 4149 | |||
| 4150 | type_of = ir_build_typeof_n(ag, scope, node, args, arg_count); | ||
| 4151 | } | ||
| 4152 | return ir_lval_wrap(ag, scope, type_of, lval, result_loc); | ||
| 4153 | } | ||
| 4154 | case BuiltinFnIdSetCold: | ||
| 4155 | { | ||
| 4156 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4157 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4158 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4159 | return arg0_value; | ||
| 4160 | |||
| 4161 | IrInstSrc *set_cold = ir_build_set_cold(ag, scope, node, arg0_value); | ||
| 4162 | return ir_lval_wrap(ag, scope, set_cold, lval, result_loc); | ||
| 4163 | } | ||
| 4164 | case BuiltinFnIdSetRuntimeSafety: | ||
| 4165 | { | ||
| 4166 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4167 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4168 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4169 | return arg0_value; | ||
| 4170 | |||
| 4171 | IrInstSrc *set_safety = ir_build_set_runtime_safety(ag, scope, node, arg0_value); | ||
| 4172 | return ir_lval_wrap(ag, scope, set_safety, lval, result_loc); | ||
| 4173 | } | ||
| 4174 | case BuiltinFnIdSetFloatMode: | ||
| 4175 | { | ||
| 4176 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4177 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4178 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4179 | return arg0_value; | ||
| 4180 | |||
| 4181 | IrInstSrc *set_float_mode = ir_build_set_float_mode(ag, scope, node, arg0_value); | ||
| 4182 | return ir_lval_wrap(ag, scope, set_float_mode, lval, result_loc); | ||
| 4183 | } | ||
| 4184 | case BuiltinFnIdSizeof: | ||
| 4185 | case BuiltinFnIdBitSizeof: | ||
| 4186 | { | ||
| 4187 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4188 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4189 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4190 | return arg0_value; | ||
| 4191 | |||
| 4192 | IrInstSrc *size_of = ir_build_size_of(ag, scope, node, arg0_value, builtin_fn->id == BuiltinFnIdBitSizeof); | ||
| 4193 | return ir_lval_wrap(ag, scope, size_of, lval, result_loc); | ||
| 4194 | } | ||
| 4195 | case BuiltinFnIdImport: | ||
| 4196 | { | ||
| 4197 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4198 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4199 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4200 | return arg0_value; | ||
| 4201 | |||
| 4202 | IrInstSrc *import = ir_build_import(ag, scope, node, arg0_value); | ||
| 4203 | return ir_lval_wrap(ag, scope, import, lval, result_loc); | ||
| 4204 | } | ||
| 4205 | case BuiltinFnIdCImport: | ||
| 4206 | { | ||
| 4207 | IrInstSrc *c_import = ir_build_c_import(ag, scope, node); | ||
| 4208 | return ir_lval_wrap(ag, scope, c_import, lval, result_loc); | ||
| 4209 | } | ||
| 4210 | case BuiltinFnIdCInclude: | ||
| 4211 | { | ||
| 4212 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4213 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4214 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4215 | return arg0_value; | ||
| 4216 | |||
| 4217 | if (!ag->in_c_import_scope) { | ||
| 4218 | add_node_error(ag->codegen, node, buf_sprintf("C include valid only inside C import block")); | ||
| 4219 | return ag->codegen->invalid_inst_src; | ||
| 4220 | } | ||
| 4221 | |||
| 4222 | IrInstSrc *c_include = ir_build_c_include(ag, scope, node, arg0_value); | ||
| 4223 | return ir_lval_wrap(ag, scope, c_include, lval, result_loc); | ||
| 4224 | } | ||
| 4225 | case BuiltinFnIdCDefine: | ||
| 4226 | { | ||
| 4227 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4228 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4229 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4230 | return arg0_value; | ||
| 4231 | |||
| 4232 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4233 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4234 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4235 | return arg1_value; | ||
| 4236 | |||
| 4237 | if (!ag->in_c_import_scope) { | ||
| 4238 | add_node_error(ag->codegen, node, buf_sprintf("C define valid only inside C import block")); | ||
| 4239 | return ag->codegen->invalid_inst_src; | ||
| 4240 | } | ||
| 4241 | |||
| 4242 | IrInstSrc *c_define = ir_build_c_define(ag, scope, node, arg0_value, arg1_value); | ||
| 4243 | return ir_lval_wrap(ag, scope, c_define, lval, result_loc); | ||
| 4244 | } | ||
| 4245 | case BuiltinFnIdCUndef: | ||
| 4246 | { | ||
| 4247 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4248 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4249 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4250 | return arg0_value; | ||
| 4251 | |||
| 4252 | if (!ag->in_c_import_scope) { | ||
| 4253 | add_node_error(ag->codegen, node, buf_sprintf("C undef valid only inside C import block")); | ||
| 4254 | return ag->codegen->invalid_inst_src; | ||
| 4255 | } | ||
| 4256 | |||
| 4257 | IrInstSrc *c_undef = ir_build_c_undef(ag, scope, node, arg0_value); | ||
| 4258 | return ir_lval_wrap(ag, scope, c_undef, lval, result_loc); | ||
| 4259 | } | ||
| 4260 | case BuiltinFnIdCompileErr: | ||
| 4261 | { | ||
| 4262 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4263 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4264 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4265 | return arg0_value; | ||
| 4266 | |||
| 4267 | IrInstSrc *compile_err = ir_build_compile_err(ag, scope, node, arg0_value); | ||
| 4268 | return ir_lval_wrap(ag, scope, compile_err, lval, result_loc); | ||
| 4269 | } | ||
| 4270 | case BuiltinFnIdCompileLog: | ||
| 4271 | { | ||
| 4272 | IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(actual_param_count); | ||
| 4273 | |||
| 4274 | for (size_t i = 0; i < actual_param_count; i += 1) { | ||
| 4275 | AstNode *arg_node = node->data.fn_call_expr.params.at(i); | ||
| 4276 | args[i] = astgen_node(ag, arg_node, scope); | ||
| 4277 | if (args[i] == ag->codegen->invalid_inst_src) | ||
| 4278 | return ag->codegen->invalid_inst_src; | ||
| 4279 | } | ||
| 4280 | |||
| 4281 | IrInstSrc *compile_log = ir_build_compile_log(ag, scope, node, actual_param_count, args); | ||
| 4282 | return ir_lval_wrap(ag, scope, compile_log, lval, result_loc); | ||
| 4283 | } | ||
| 4284 | case BuiltinFnIdErrName: | ||
| 4285 | { | ||
| 4286 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4287 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4288 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4289 | return arg0_value; | ||
| 4290 | |||
| 4291 | IrInstSrc *err_name = ir_build_err_name(ag, scope, node, arg0_value); | ||
| 4292 | return ir_lval_wrap(ag, scope, err_name, lval, result_loc); | ||
| 4293 | } | ||
| 4294 | case BuiltinFnIdEmbedFile: | ||
| 4295 | { | ||
| 4296 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4297 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4298 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4299 | return arg0_value; | ||
| 4300 | |||
| 4301 | IrInstSrc *embed_file = ir_build_embed_file(ag, scope, node, arg0_value); | ||
| 4302 | return ir_lval_wrap(ag, scope, embed_file, lval, result_loc); | ||
| 4303 | } | ||
| 4304 | case BuiltinFnIdCmpxchgWeak: | ||
| 4305 | case BuiltinFnIdCmpxchgStrong: | ||
| 4306 | { | ||
| 4307 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4308 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4309 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4310 | return arg0_value; | ||
| 4311 | |||
| 4312 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4313 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4314 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4315 | return arg1_value; | ||
| 4316 | |||
| 4317 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 4318 | IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); | ||
| 4319 | if (arg2_value == ag->codegen->invalid_inst_src) | ||
| 4320 | return arg2_value; | ||
| 4321 | |||
| 4322 | AstNode *arg3_node = node->data.fn_call_expr.params.at(3); | ||
| 4323 | IrInstSrc *arg3_value = astgen_node(ag, arg3_node, scope); | ||
| 4324 | if (arg3_value == ag->codegen->invalid_inst_src) | ||
| 4325 | return arg3_value; | ||
| 4326 | |||
| 4327 | AstNode *arg4_node = node->data.fn_call_expr.params.at(4); | ||
| 4328 | IrInstSrc *arg4_value = astgen_node(ag, arg4_node, scope); | ||
| 4329 | if (arg4_value == ag->codegen->invalid_inst_src) | ||
| 4330 | return arg4_value; | ||
| 4331 | |||
| 4332 | AstNode *arg5_node = node->data.fn_call_expr.params.at(5); | ||
| 4333 | IrInstSrc *arg5_value = astgen_node(ag, arg5_node, scope); | ||
| 4334 | if (arg5_value == ag->codegen->invalid_inst_src) | ||
| 4335 | return arg5_value; | ||
| 4336 | |||
| 4337 | IrInstSrc *cmpxchg = ir_build_cmpxchg_src(ag, scope, node, arg0_value, arg1_value, | ||
| 4338 | arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak), | ||
| 4339 | result_loc); | ||
| 4340 | return ir_lval_wrap(ag, scope, cmpxchg, lval, result_loc); | ||
| 4341 | } | ||
| 4342 | case BuiltinFnIdFence: | ||
| 4343 | { | ||
| 4344 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4345 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4346 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4347 | return arg0_value; | ||
| 4348 | |||
| 4349 | IrInstSrc *fence = ir_build_fence(ag, scope, node, arg0_value); | ||
| 4350 | return ir_lval_wrap(ag, scope, fence, lval, result_loc); | ||
| 4351 | } | ||
| 4352 | case BuiltinFnIdReduce: | ||
| 4353 | { | ||
| 4354 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4355 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4356 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4357 | return arg0_value; | ||
| 4358 | |||
| 4359 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4360 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4361 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4362 | return arg1_value; | ||
| 4363 | |||
| 4364 | IrInstSrc *reduce = ir_build_reduce(ag, scope, node, arg0_value, arg1_value); | ||
| 4365 | return ir_lval_wrap(ag, scope, reduce, lval, result_loc); | ||
| 4366 | } | ||
| 4367 | case BuiltinFnIdDivExact: | ||
| 4368 | { | ||
| 4369 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4370 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4371 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4372 | return arg0_value; | ||
| 4373 | |||
| 4374 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4375 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4376 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4377 | return arg1_value; | ||
| 4378 | |||
| 4379 | IrInstSrc *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpDivExact, arg0_value, arg1_value, true); | ||
| 4380 | return ir_lval_wrap(ag, scope, bin_op, lval, result_loc); | ||
| 4381 | } | ||
| 4382 | case BuiltinFnIdDivTrunc: | ||
| 4383 | { | ||
| 4384 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4385 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4386 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4387 | return arg0_value; | ||
| 4388 | |||
| 4389 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4390 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4391 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4392 | return arg1_value; | ||
| 4393 | |||
| 4394 | IrInstSrc *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpDivTrunc, arg0_value, arg1_value, true); | ||
| 4395 | return ir_lval_wrap(ag, scope, bin_op, lval, result_loc); | ||
| 4396 | } | ||
| 4397 | case BuiltinFnIdDivFloor: | ||
| 4398 | { | ||
| 4399 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4400 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4401 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4402 | return arg0_value; | ||
| 4403 | |||
| 4404 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4405 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4406 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4407 | return arg1_value; | ||
| 4408 | |||
| 4409 | IrInstSrc *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpDivFloor, arg0_value, arg1_value, true); | ||
| 4410 | return ir_lval_wrap(ag, scope, bin_op, lval, result_loc); | ||
| 4411 | } | ||
| 4412 | case BuiltinFnIdRem: | ||
| 4413 | { | ||
| 4414 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4415 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4416 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4417 | return arg0_value; | ||
| 4418 | |||
| 4419 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4420 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4421 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4422 | return arg1_value; | ||
| 4423 | |||
| 4424 | IrInstSrc *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpRemRem, arg0_value, arg1_value, true); | ||
| 4425 | return ir_lval_wrap(ag, scope, bin_op, lval, result_loc); | ||
| 4426 | } | ||
| 4427 | case BuiltinFnIdMod: | ||
| 4428 | { | ||
| 4429 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4430 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4431 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4432 | return arg0_value; | ||
| 4433 | |||
| 4434 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4435 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4436 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4437 | return arg1_value; | ||
| 4438 | |||
| 4439 | IrInstSrc *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpRemMod, arg0_value, arg1_value, true); | ||
| 4440 | return ir_lval_wrap(ag, scope, bin_op, lval, result_loc); | ||
| 4441 | } | ||
| 4442 | case BuiltinFnIdSqrt: | ||
| 4443 | case BuiltinFnIdSin: | ||
| 4444 | case BuiltinFnIdCos: | ||
| 4445 | case BuiltinFnIdExp: | ||
| 4446 | case BuiltinFnIdExp2: | ||
| 4447 | case BuiltinFnIdLog: | ||
| 4448 | case BuiltinFnIdLog2: | ||
| 4449 | case BuiltinFnIdLog10: | ||
| 4450 | case BuiltinFnIdFabs: | ||
| 4451 | case BuiltinFnIdFloor: | ||
| 4452 | case BuiltinFnIdCeil: | ||
| 4453 | case BuiltinFnIdTrunc: | ||
| 4454 | case BuiltinFnIdNearbyInt: | ||
| 4455 | case BuiltinFnIdRound: | ||
| 4456 | { | ||
| 4457 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4458 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4459 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4460 | return arg0_value; | ||
| 4461 | |||
| 4462 | IrInstSrc *inst = ir_build_float_op_src(ag, scope, node, arg0_value, builtin_fn->id); | ||
| 4463 | return ir_lval_wrap(ag, scope, inst, lval, result_loc); | ||
| 4464 | } | ||
| 4465 | case BuiltinFnIdTruncate: | ||
| 4466 | { | ||
| 4467 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4468 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4469 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4470 | return arg0_value; | ||
| 4471 | |||
| 4472 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4473 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4474 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4475 | return arg1_value; | ||
| 4476 | |||
| 4477 | IrInstSrc *truncate = ir_build_truncate(ag, scope, node, arg0_value, arg1_value); | ||
| 4478 | return ir_lval_wrap(ag, scope, truncate, lval, result_loc); | ||
| 4479 | } | ||
| 4480 | case BuiltinFnIdIntCast: | ||
| 4481 | { | ||
| 4482 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4483 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4484 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4485 | return arg0_value; | ||
| 4486 | |||
| 4487 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4488 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4489 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4490 | return arg1_value; | ||
| 4491 | |||
| 4492 | IrInstSrc *result = ir_build_int_cast(ag, scope, node, arg0_value, arg1_value); | ||
| 4493 | return ir_lval_wrap(ag, scope, result, lval, result_loc); | ||
| 4494 | } | ||
| 4495 | case BuiltinFnIdFloatCast: | ||
| 4496 | { | ||
| 4497 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4498 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4499 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4500 | return arg0_value; | ||
| 4501 | |||
| 4502 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4503 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4504 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4505 | return arg1_value; | ||
| 4506 | |||
| 4507 | IrInstSrc *result = ir_build_float_cast(ag, scope, node, arg0_value, arg1_value); | ||
| 4508 | return ir_lval_wrap(ag, scope, result, lval, result_loc); | ||
| 4509 | } | ||
| 4510 | case BuiltinFnIdErrSetCast: | ||
| 4511 | { | ||
| 4512 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4513 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4514 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4515 | return arg0_value; | ||
| 4516 | |||
| 4517 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4518 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4519 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4520 | return arg1_value; | ||
| 4521 | |||
| 4522 | IrInstSrc *result = ir_build_err_set_cast(ag, scope, node, arg0_value, arg1_value); | ||
| 4523 | return ir_lval_wrap(ag, scope, result, lval, result_loc); | ||
| 4524 | } | ||
| 4525 | case BuiltinFnIdIntToFloat: | ||
| 4526 | { | ||
| 4527 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4528 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4529 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4530 | return arg0_value; | ||
| 4531 | |||
| 4532 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4533 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4534 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4535 | return arg1_value; | ||
| 4536 | |||
| 4537 | IrInstSrc *result = ir_build_int_to_float(ag, scope, node, arg0_value, arg1_value); | ||
| 4538 | return ir_lval_wrap(ag, scope, result, lval, result_loc); | ||
| 4539 | } | ||
| 4540 | case BuiltinFnIdFloatToInt: | ||
| 4541 | { | ||
| 4542 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4543 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4544 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4545 | return arg0_value; | ||
| 4546 | |||
| 4547 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4548 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4549 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4550 | return arg1_value; | ||
| 4551 | |||
| 4552 | IrInstSrc *result = ir_build_float_to_int(ag, scope, node, arg0_value, arg1_value); | ||
| 4553 | return ir_lval_wrap(ag, scope, result, lval, result_loc); | ||
| 4554 | } | ||
| 4555 | case BuiltinFnIdErrToInt: | ||
| 4556 | { | ||
| 4557 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4558 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4559 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4560 | return arg0_value; | ||
| 4561 | |||
| 4562 | IrInstSrc *result = ir_build_err_to_int_src(ag, scope, node, arg0_value); | ||
| 4563 | return ir_lval_wrap(ag, scope, result, lval, result_loc); | ||
| 4564 | } | ||
| 4565 | case BuiltinFnIdIntToErr: | ||
| 4566 | { | ||
| 4567 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4568 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4569 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4570 | return arg0_value; | ||
| 4571 | |||
| 4572 | IrInstSrc *result = ir_build_int_to_err_src(ag, scope, node, arg0_value); | ||
| 4573 | return ir_lval_wrap(ag, scope, result, lval, result_loc); | ||
| 4574 | } | ||
| 4575 | case BuiltinFnIdBoolToInt: | ||
| 4576 | { | ||
| 4577 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4578 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4579 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4580 | return arg0_value; | ||
| 4581 | |||
| 4582 | IrInstSrc *result = ir_build_bool_to_int(ag, scope, node, arg0_value); | ||
| 4583 | return ir_lval_wrap(ag, scope, result, lval, result_loc); | ||
| 4584 | } | ||
| 4585 | case BuiltinFnIdVectorType: | ||
| 4586 | { | ||
| 4587 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4588 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4589 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4590 | return arg0_value; | ||
| 4591 | |||
| 4592 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4593 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4594 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4595 | return arg1_value; | ||
| 4596 | |||
| 4597 | IrInstSrc *vector_type = ir_build_vector_type(ag, scope, node, arg0_value, arg1_value); | ||
| 4598 | return ir_lval_wrap(ag, scope, vector_type, lval, result_loc); | ||
| 4599 | } | ||
| 4600 | case BuiltinFnIdShuffle: | ||
| 4601 | { | ||
| 4602 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4603 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4604 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4605 | return arg0_value; | ||
| 4606 | |||
| 4607 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4608 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4609 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4610 | return arg1_value; | ||
| 4611 | |||
| 4612 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 4613 | IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); | ||
| 4614 | if (arg2_value == ag->codegen->invalid_inst_src) | ||
| 4615 | return arg2_value; | ||
| 4616 | |||
| 4617 | AstNode *arg3_node = node->data.fn_call_expr.params.at(3); | ||
| 4618 | IrInstSrc *arg3_value = astgen_node(ag, arg3_node, scope); | ||
| 4619 | if (arg3_value == ag->codegen->invalid_inst_src) | ||
| 4620 | return arg3_value; | ||
| 4621 | |||
| 4622 | IrInstSrc *shuffle_vector = ir_build_shuffle_vector(ag, scope, node, | ||
| 4623 | arg0_value, arg1_value, arg2_value, arg3_value); | ||
| 4624 | return ir_lval_wrap(ag, scope, shuffle_vector, lval, result_loc); | ||
| 4625 | } | ||
| 4626 | case BuiltinFnIdSplat: | ||
| 4627 | { | ||
| 4628 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4629 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4630 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4631 | return arg0_value; | ||
| 4632 | |||
| 4633 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4634 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4635 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4636 | return arg1_value; | ||
| 4637 | |||
| 4638 | IrInstSrc *splat = ir_build_splat_src(ag, scope, node, | ||
| 4639 | arg0_value, arg1_value); | ||
| 4640 | return ir_lval_wrap(ag, scope, splat, lval, result_loc); | ||
| 4641 | } | ||
| 4642 | case BuiltinFnIdMemcpy: | ||
| 4643 | { | ||
| 4644 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4645 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4646 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4647 | return arg0_value; | ||
| 4648 | |||
| 4649 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4650 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4651 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4652 | return arg1_value; | ||
| 4653 | |||
| 4654 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 4655 | IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); | ||
| 4656 | if (arg2_value == ag->codegen->invalid_inst_src) | ||
| 4657 | return arg2_value; | ||
| 4658 | |||
| 4659 | IrInstSrc *ir_memcpy = ir_build_memcpy_src(ag, scope, node, arg0_value, arg1_value, arg2_value); | ||
| 4660 | return ir_lval_wrap(ag, scope, ir_memcpy, lval, result_loc); | ||
| 4661 | } | ||
| 4662 | case BuiltinFnIdMemset: | ||
| 4663 | { | ||
| 4664 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4665 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4666 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4667 | return arg0_value; | ||
| 4668 | |||
| 4669 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4670 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4671 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4672 | return arg1_value; | ||
| 4673 | |||
| 4674 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 4675 | IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); | ||
| 4676 | if (arg2_value == ag->codegen->invalid_inst_src) | ||
| 4677 | return arg2_value; | ||
| 4678 | |||
| 4679 | IrInstSrc *ir_memset = ir_build_memset_src(ag, scope, node, arg0_value, arg1_value, arg2_value); | ||
| 4680 | return ir_lval_wrap(ag, scope, ir_memset, lval, result_loc); | ||
| 4681 | } | ||
| 4682 | case BuiltinFnIdWasmMemorySize: | ||
| 4683 | { | ||
| 4684 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4685 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4686 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4687 | return arg0_value; | ||
| 4688 | |||
| 4689 | IrInstSrc *ir_wasm_memory_size = ir_build_wasm_memory_size_src(ag, scope, node, arg0_value); | ||
| 4690 | return ir_lval_wrap(ag, scope, ir_wasm_memory_size, lval, result_loc); | ||
| 4691 | } | ||
| 4692 | case BuiltinFnIdWasmMemoryGrow: | ||
| 4693 | { | ||
| 4694 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4695 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4696 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4697 | return arg0_value; | ||
| 4698 | |||
| 4699 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4700 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4701 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4702 | return arg1_value; | ||
| 4703 | |||
| 4704 | IrInstSrc *ir_wasm_memory_grow = ir_build_wasm_memory_grow_src(ag, scope, node, arg0_value, arg1_value); | ||
| 4705 | return ir_lval_wrap(ag, scope, ir_wasm_memory_grow, lval, result_loc); | ||
| 4706 | } | ||
| 4707 | case BuiltinFnIdField: | ||
| 4708 | { | ||
| 4709 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4710 | IrInstSrc *arg0_value = astgen_node_extra(ag, arg0_node, scope, LValPtr, nullptr); | ||
| 4711 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4712 | return arg0_value; | ||
| 4713 | |||
| 4714 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4715 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4716 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4717 | return arg1_value; | ||
| 4718 | |||
| 4719 | IrInstSrc *ptr_instruction = ir_build_field_ptr_instruction(ag, scope, node, | ||
| 4720 | arg0_value, arg1_value, false); | ||
| 4721 | |||
| 4722 | if (lval == LValPtr || lval == LValAssign) | ||
| 4723 | return ptr_instruction; | ||
| 4724 | |||
| 4725 | IrInstSrc *load_ptr = ir_build_load_ptr(ag, scope, node, ptr_instruction); | ||
| 4726 | return ir_expr_wrap(ag, scope, load_ptr, result_loc); | ||
| 4727 | } | ||
| 4728 | case BuiltinFnIdHasField: | ||
| 4729 | { | ||
| 4730 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4731 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4732 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4733 | return arg0_value; | ||
| 4734 | |||
| 4735 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4736 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4737 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4738 | return arg1_value; | ||
| 4739 | |||
| 4740 | IrInstSrc *type_info = ir_build_has_field(ag, scope, node, arg0_value, arg1_value); | ||
| 4741 | return ir_lval_wrap(ag, scope, type_info, lval, result_loc); | ||
| 4742 | } | ||
| 4743 | case BuiltinFnIdTypeInfo: | ||
| 4744 | { | ||
| 4745 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4746 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4747 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4748 | return arg0_value; | ||
| 4749 | |||
| 4750 | IrInstSrc *type_info = ir_build_type_info(ag, scope, node, arg0_value); | ||
| 4751 | return ir_lval_wrap(ag, scope, type_info, lval, result_loc); | ||
| 4752 | } | ||
| 4753 | case BuiltinFnIdType: | ||
| 4754 | { | ||
| 4755 | AstNode *arg_node = node->data.fn_call_expr.params.at(0); | ||
| 4756 | IrInstSrc *arg = astgen_node(ag, arg_node, scope); | ||
| 4757 | if (arg == ag->codegen->invalid_inst_src) | ||
| 4758 | return arg; | ||
| 4759 | |||
| 4760 | IrInstSrc *type = ir_build_type(ag, scope, node, arg); | ||
| 4761 | return ir_lval_wrap(ag, scope, type, lval, result_loc); | ||
| 4762 | } | ||
| 4763 | case BuiltinFnIdBreakpoint: | ||
| 4764 | return ir_lval_wrap(ag, scope, ir_build_breakpoint(ag, scope, node), lval, result_loc); | ||
| 4765 | case BuiltinFnIdReturnAddress: | ||
| 4766 | return ir_lval_wrap(ag, scope, ir_build_return_address_src(ag, scope, node), lval, result_loc); | ||
| 4767 | case BuiltinFnIdFrameAddress: | ||
| 4768 | return ir_lval_wrap(ag, scope, ir_build_frame_address_src(ag, scope, node), lval, result_loc); | ||
| 4769 | case BuiltinFnIdFrameHandle: | ||
| 4770 | if (ag->fn == nullptr) { | ||
| 4771 | add_node_error(ag->codegen, node, | ||
| 4772 | buf_sprintf("@frame() called outside of function definition")); | ||
| 4773 | return ag->codegen->invalid_inst_src; | ||
| 4774 | } | ||
| 4775 | return ir_lval_wrap(ag, scope, ir_build_handle_src(ag, scope, node), lval, result_loc); | ||
| 4776 | case BuiltinFnIdFrameType: { | ||
| 4777 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4778 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4779 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4780 | return arg0_value; | ||
| 4781 | |||
| 4782 | IrInstSrc *frame_type = ir_build_frame_type(ag, scope, node, arg0_value); | ||
| 4783 | return ir_lval_wrap(ag, scope, frame_type, lval, result_loc); | ||
| 4784 | } | ||
| 4785 | case BuiltinFnIdFrameSize: { | ||
| 4786 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4787 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4788 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4789 | return arg0_value; | ||
| 4790 | |||
| 4791 | IrInstSrc *frame_size = ir_build_frame_size_src(ag, scope, node, arg0_value); | ||
| 4792 | return ir_lval_wrap(ag, scope, frame_size, lval, result_loc); | ||
| 4793 | } | ||
| 4794 | case BuiltinFnIdAlignOf: | ||
| 4795 | { | ||
| 4796 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4797 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4798 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4799 | return arg0_value; | ||
| 4800 | |||
| 4801 | IrInstSrc *align_of = ir_build_align_of(ag, scope, node, arg0_value); | ||
| 4802 | return ir_lval_wrap(ag, scope, align_of, lval, result_loc); | ||
| 4803 | } | ||
| 4804 | case BuiltinFnIdAddWithOverflow: | ||
| 4805 | return ir_lval_wrap(ag, scope, astgen_overflow_op(ag, scope, node, IrOverflowOpAdd), lval, result_loc); | ||
| 4806 | case BuiltinFnIdSubWithOverflow: | ||
| 4807 | return ir_lval_wrap(ag, scope, astgen_overflow_op(ag, scope, node, IrOverflowOpSub), lval, result_loc); | ||
| 4808 | case BuiltinFnIdMulWithOverflow: | ||
| 4809 | return ir_lval_wrap(ag, scope, astgen_overflow_op(ag, scope, node, IrOverflowOpMul), lval, result_loc); | ||
| 4810 | case BuiltinFnIdShlWithOverflow: | ||
| 4811 | return ir_lval_wrap(ag, scope, astgen_overflow_op(ag, scope, node, IrOverflowOpShl), lval, result_loc); | ||
| 4812 | case BuiltinFnIdMulAdd: | ||
| 4813 | return ir_lval_wrap(ag, scope, astgen_mul_add(ag, scope, node), lval, result_loc); | ||
| 4814 | case BuiltinFnIdTypeName: | ||
| 4815 | { | ||
| 4816 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4817 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4818 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4819 | return arg0_value; | ||
| 4820 | |||
| 4821 | IrInstSrc *type_name = ir_build_type_name(ag, scope, node, arg0_value); | ||
| 4822 | return ir_lval_wrap(ag, scope, type_name, lval, result_loc); | ||
| 4823 | } | ||
| 4824 | case BuiltinFnIdPanic: | ||
| 4825 | { | ||
| 4826 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4827 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4828 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4829 | return arg0_value; | ||
| 4830 | |||
| 4831 | IrInstSrc *panic = ir_build_panic_src(ag, scope, node, arg0_value); | ||
| 4832 | return ir_lval_wrap(ag, scope, panic, lval, result_loc); | ||
| 4833 | } | ||
| 4834 | case BuiltinFnIdPtrCast: | ||
| 4835 | { | ||
| 4836 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4837 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4838 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4839 | return arg0_value; | ||
| 4840 | |||
| 4841 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4842 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4843 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4844 | return arg1_value; | ||
| 4845 | |||
| 4846 | IrInstSrc *ptr_cast = ir_build_ptr_cast_src(ag, scope, node, arg0_value, arg1_value, true); | ||
| 4847 | return ir_lval_wrap(ag, scope, ptr_cast, lval, result_loc); | ||
| 4848 | } | ||
| 4849 | case BuiltinFnIdBitCast: | ||
| 4850 | { | ||
| 4851 | AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); | ||
| 4852 | IrInstSrc *dest_type = astgen_node(ag, dest_type_node, scope); | ||
| 4853 | if (dest_type == ag->codegen->invalid_inst_src) | ||
| 4854 | return dest_type; | ||
| 4855 | |||
| 4856 | ResultLocBitCast *result_loc_bit_cast = heap::c_allocator.create<ResultLocBitCast>(); | ||
| 4857 | result_loc_bit_cast->base.id = ResultLocIdBitCast; | ||
| 4858 | result_loc_bit_cast->base.source_instruction = dest_type; | ||
| 4859 | result_loc_bit_cast->base.allow_write_through_const = result_loc->allow_write_through_const; | ||
| 4860 | ir_ref_instruction(dest_type, ag->current_basic_block); | ||
| 4861 | result_loc_bit_cast->parent = result_loc; | ||
| 4862 | |||
| 4863 | ir_build_reset_result(ag, scope, node, &result_loc_bit_cast->base); | ||
| 4864 | |||
| 4865 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4866 | IrInstSrc *arg1_value = astgen_node_extra(ag, arg1_node, scope, LValNone, | ||
| 4867 | &result_loc_bit_cast->base); | ||
| 4868 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4869 | return arg1_value; | ||
| 4870 | |||
| 4871 | IrInstSrc *bitcast = ir_build_bit_cast_src(ag, scope, arg1_node, arg1_value, result_loc_bit_cast); | ||
| 4872 | return ir_lval_wrap(ag, scope, bitcast, lval, result_loc); | ||
| 4873 | } | ||
| 4874 | case BuiltinFnIdAs: | ||
| 4875 | { | ||
| 4876 | AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); | ||
| 4877 | IrInstSrc *dest_type = astgen_node(ag, dest_type_node, scope); | ||
| 4878 | if (dest_type == ag->codegen->invalid_inst_src) | ||
| 4879 | return dest_type; | ||
| 4880 | |||
| 4881 | ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, dest_type, result_loc); | ||
| 4882 | |||
| 4883 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4884 | IrInstSrc *arg1_value = astgen_node_extra(ag, arg1_node, scope, LValNone, | ||
| 4885 | &result_loc_cast->base); | ||
| 4886 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4887 | return arg1_value; | ||
| 4888 | |||
| 4889 | IrInstSrc *result = ir_build_implicit_cast(ag, scope, node, arg1_value, result_loc_cast); | ||
| 4890 | return ir_lval_wrap(ag, scope, result, lval, result_loc); | ||
| 4891 | } | ||
| 4892 | case BuiltinFnIdIntToPtr: | ||
| 4893 | { | ||
| 4894 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4895 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4896 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4897 | return arg0_value; | ||
| 4898 | |||
| 4899 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4900 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4901 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4902 | return arg1_value; | ||
| 4903 | |||
| 4904 | IrInstSrc *int_to_ptr = ir_build_int_to_ptr_src(ag, scope, node, arg0_value, arg1_value); | ||
| 4905 | return ir_lval_wrap(ag, scope, int_to_ptr, lval, result_loc); | ||
| 4906 | } | ||
| 4907 | case BuiltinFnIdPtrToInt: | ||
| 4908 | { | ||
| 4909 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4910 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4911 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4912 | return arg0_value; | ||
| 4913 | |||
| 4914 | IrInstSrc *ptr_to_int = ir_build_ptr_to_int_src(ag, scope, node, arg0_value); | ||
| 4915 | return ir_lval_wrap(ag, scope, ptr_to_int, lval, result_loc); | ||
| 4916 | } | ||
| 4917 | case BuiltinFnIdTagName: | ||
| 4918 | { | ||
| 4919 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4920 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4921 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4922 | return arg0_value; | ||
| 4923 | |||
| 4924 | IrInstSrc *tag_name = ir_build_tag_name_src(ag, scope, node, arg0_value); | ||
| 4925 | return ir_lval_wrap(ag, scope, tag_name, lval, result_loc); | ||
| 4926 | } | ||
| 4927 | case BuiltinFnIdFieldParentPtr: | ||
| 4928 | { | ||
| 4929 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4930 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4931 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4932 | return arg0_value; | ||
| 4933 | |||
| 4934 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4935 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4936 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4937 | return arg1_value; | ||
| 4938 | |||
| 4939 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 4940 | IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); | ||
| 4941 | if (arg2_value == ag->codegen->invalid_inst_src) | ||
| 4942 | return arg2_value; | ||
| 4943 | |||
| 4944 | IrInstSrc *field_parent_ptr = ir_build_field_parent_ptr_src(ag, scope, node, | ||
| 4945 | arg0_value, arg1_value, arg2_value); | ||
| 4946 | return ir_lval_wrap(ag, scope, field_parent_ptr, lval, result_loc); | ||
| 4947 | } | ||
| 4948 | case BuiltinFnIdByteOffsetOf: | ||
| 4949 | { | ||
| 4950 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4951 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4952 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4953 | return arg0_value; | ||
| 4954 | |||
| 4955 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4956 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4957 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4958 | return arg1_value; | ||
| 4959 | |||
| 4960 | IrInstSrc *offset_of = ir_build_byte_offset_of(ag, scope, node, arg0_value, arg1_value); | ||
| 4961 | return ir_lval_wrap(ag, scope, offset_of, lval, result_loc); | ||
| 4962 | } | ||
| 4963 | case BuiltinFnIdBitOffsetOf: | ||
| 4964 | { | ||
| 4965 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 4966 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 4967 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 4968 | return arg0_value; | ||
| 4969 | |||
| 4970 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 4971 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 4972 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 4973 | return arg1_value; | ||
| 4974 | |||
| 4975 | IrInstSrc *offset_of = ir_build_bit_offset_of(ag, scope, node, arg0_value, arg1_value); | ||
| 4976 | return ir_lval_wrap(ag, scope, offset_of, lval, result_loc); | ||
| 4977 | } | ||
| 4978 | case BuiltinFnIdCall: { | ||
| 4979 | // Cast the options parameter to the options type | ||
| 4980 | ZigType *options_type = get_builtin_type(ag->codegen, "CallOptions"); | ||
| 4981 | IrInstSrc *options_type_inst = ir_build_const_type(ag, scope, node, options_type); | ||
| 4982 | ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc()); | ||
| 4983 | |||
| 4984 | AstNode *options_node = node->data.fn_call_expr.params.at(0); | ||
| 4985 | IrInstSrc *options_inner = astgen_node_extra(ag, options_node, scope, | ||
| 4986 | LValNone, &result_loc_cast->base); | ||
| 4987 | if (options_inner == ag->codegen->invalid_inst_src) | ||
| 4988 | return options_inner; | ||
| 4989 | IrInstSrc *options = ir_build_implicit_cast(ag, scope, options_node, options_inner, result_loc_cast); | ||
| 4990 | |||
| 4991 | AstNode *fn_ref_node = node->data.fn_call_expr.params.at(1); | ||
| 4992 | AstNode *args_node = node->data.fn_call_expr.params.at(2); | ||
| 4993 | if (args_node->type == NodeTypeContainerInitExpr) { | ||
| 4994 | if (args_node->data.container_init_expr.kind == ContainerInitKindArray || | ||
| 4995 | args_node->data.container_init_expr.entries.length == 0) | ||
| 4996 | { | ||
| 4997 | return astgen_fn_call_with_args(ag, scope, node, | ||
| 4998 | fn_ref_node, CallModifierNone, options, | ||
| 4999 | args_node->data.container_init_expr.entries.items, | ||
| 5000 | args_node->data.container_init_expr.entries.length, | ||
| 5001 | lval, result_loc); | ||
| 5002 | } else { | ||
| 5003 | exec_add_error_node(ag->codegen, ag->exec, args_node, | ||
| 5004 | buf_sprintf("TODO: @call with anon struct literal")); | ||
| 5005 | return ag->codegen->invalid_inst_src; | ||
| 5006 | } | ||
| 5007 | } else { | ||
| 5008 | IrInstSrc *fn_ref = astgen_node(ag, fn_ref_node, scope); | ||
| 5009 | if (fn_ref == ag->codegen->invalid_inst_src) | ||
| 5010 | return fn_ref; | ||
| 5011 | |||
| 5012 | IrInstSrc *args = astgen_node(ag, args_node, scope); | ||
| 5013 | if (args == ag->codegen->invalid_inst_src) | ||
| 5014 | return args; | ||
| 5015 | |||
| 5016 | IrInstSrc *call = ir_build_call_extra(ag, scope, node, options, fn_ref, args, result_loc); | ||
| 5017 | return ir_lval_wrap(ag, scope, call, lval, result_loc); | ||
| 5018 | } | ||
| 5019 | } | ||
| 5020 | case BuiltinFnIdAsyncCall: | ||
| 5021 | return astgen_async_call(ag, scope, nullptr, node, lval, result_loc); | ||
| 5022 | case BuiltinFnIdShlExact: | ||
| 5023 | { | ||
| 5024 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 5025 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 5026 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 5027 | return arg0_value; | ||
| 5028 | |||
| 5029 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 5030 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 5031 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 5032 | return arg1_value; | ||
| 5033 | |||
| 5034 | IrInstSrc *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpBitShiftLeftExact, arg0_value, arg1_value, true); | ||
| 5035 | return ir_lval_wrap(ag, scope, bin_op, lval, result_loc); | ||
| 5036 | } | ||
| 5037 | case BuiltinFnIdShrExact: | ||
| 5038 | { | ||
| 5039 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 5040 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 5041 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 5042 | return arg0_value; | ||
| 5043 | |||
| 5044 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 5045 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 5046 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 5047 | return arg1_value; | ||
| 5048 | |||
| 5049 | IrInstSrc *bin_op = ir_build_bin_op(ag, scope, node, IrBinOpBitShiftRightExact, arg0_value, arg1_value, true); | ||
| 5050 | return ir_lval_wrap(ag, scope, bin_op, lval, result_loc); | ||
| 5051 | } | ||
| 5052 | case BuiltinFnIdSetEvalBranchQuota: | ||
| 5053 | { | ||
| 5054 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 5055 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 5056 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 5057 | return arg0_value; | ||
| 5058 | |||
| 5059 | IrInstSrc *set_eval_branch_quota = ir_build_set_eval_branch_quota(ag, scope, node, arg0_value); | ||
| 5060 | return ir_lval_wrap(ag, scope, set_eval_branch_quota, lval, result_loc); | ||
| 5061 | } | ||
| 5062 | case BuiltinFnIdAlignCast: | ||
| 5063 | { | ||
| 5064 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 5065 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 5066 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 5067 | return arg0_value; | ||
| 5068 | |||
| 5069 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 5070 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 5071 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 5072 | return arg1_value; | ||
| 5073 | |||
| 5074 | IrInstSrc *align_cast = ir_build_align_cast_src(ag, scope, node, arg0_value, arg1_value); | ||
| 5075 | return ir_lval_wrap(ag, scope, align_cast, lval, result_loc); | ||
| 5076 | } | ||
| 5077 | case BuiltinFnIdThis: | ||
| 5078 | { | ||
| 5079 | IrInstSrc *this_inst = astgen_this(ag, scope, node); | ||
| 5080 | return ir_lval_wrap(ag, scope, this_inst, lval, result_loc); | ||
| 5081 | } | ||
| 5082 | case BuiltinFnIdSetAlignStack: | ||
| 5083 | { | ||
| 5084 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 5085 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 5086 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 5087 | return arg0_value; | ||
| 5088 | |||
| 5089 | IrInstSrc *set_align_stack = ir_build_set_align_stack(ag, scope, node, arg0_value); | ||
| 5090 | return ir_lval_wrap(ag, scope, set_align_stack, lval, result_loc); | ||
| 5091 | } | ||
| 5092 | case BuiltinFnIdExport: | ||
| 5093 | { | ||
| 5094 | // Cast the options parameter to the options type | ||
| 5095 | ZigType *options_type = get_builtin_type(ag->codegen, "ExportOptions"); | ||
| 5096 | IrInstSrc *options_type_inst = ir_build_const_type(ag, scope, node, options_type); | ||
| 5097 | ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc()); | ||
| 5098 | |||
| 5099 | AstNode *target_node = node->data.fn_call_expr.params.at(0); | ||
| 5100 | IrInstSrc *target_value = astgen_node(ag, target_node, scope); | ||
| 5101 | if (target_value == ag->codegen->invalid_inst_src) | ||
| 5102 | return target_value; | ||
| 5103 | |||
| 5104 | AstNode *options_node = node->data.fn_call_expr.params.at(1); | ||
| 5105 | IrInstSrc *options_value = astgen_node_extra(ag, options_node, | ||
| 5106 | scope, LValNone, &result_loc_cast->base); | ||
| 5107 | if (options_value == ag->codegen->invalid_inst_src) | ||
| 5108 | return options_value; | ||
| 5109 | |||
| 5110 | IrInstSrc *casted_options_value = ir_build_implicit_cast( | ||
| 5111 | ag, scope, options_node, options_value, result_loc_cast); | ||
| 5112 | |||
| 5113 | IrInstSrc *ir_export = ir_build_export(ag, scope, node, target_value, casted_options_value); | ||
| 5114 | return ir_lval_wrap(ag, scope, ir_export, lval, result_loc); | ||
| 5115 | } | ||
| 5116 | case BuiltinFnIdExtern: | ||
| 5117 | { | ||
| 5118 | // Cast the options parameter to the options type | ||
| 5119 | ZigType *options_type = get_builtin_type(ag->codegen, "ExternOptions"); | ||
| 5120 | IrInstSrc *options_type_inst = ir_build_const_type(ag, scope, node, options_type); | ||
| 5121 | ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc()); | ||
| 5122 | |||
| 5123 | AstNode *type_node = node->data.fn_call_expr.params.at(0); | ||
| 5124 | IrInstSrc *type_value = astgen_node(ag, type_node, scope); | ||
| 5125 | if (type_value == ag->codegen->invalid_inst_src) | ||
| 5126 | return type_value; | ||
| 5127 | |||
| 5128 | AstNode *options_node = node->data.fn_call_expr.params.at(1); | ||
| 5129 | IrInstSrc *options_value = astgen_node_extra(ag, options_node, | ||
| 5130 | scope, LValNone, &result_loc_cast->base); | ||
| 5131 | if (options_value == ag->codegen->invalid_inst_src) | ||
| 5132 | return options_value; | ||
| 5133 | |||
| 5134 | IrInstSrc *casted_options_value = ir_build_implicit_cast( | ||
| 5135 | ag, scope, options_node, options_value, result_loc_cast); | ||
| 5136 | |||
| 5137 | IrInstSrc *ir_extern = ir_build_extern(ag, scope, node, type_value, casted_options_value); | ||
| 5138 | return ir_lval_wrap(ag, scope, ir_extern, lval, result_loc); | ||
| 5139 | } | ||
| 5140 | case BuiltinFnIdErrorReturnTrace: | ||
| 5141 | { | ||
| 5142 | IrInstSrc *error_return_trace = ir_build_error_return_trace_src(ag, scope, node, | ||
| 5143 | IrInstErrorReturnTraceNull); | ||
| 5144 | return ir_lval_wrap(ag, scope, error_return_trace, lval, result_loc); | ||
| 5145 | } | ||
| 5146 | case BuiltinFnIdAtomicRmw: | ||
| 5147 | { | ||
| 5148 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 5149 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 5150 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 5151 | return arg0_value; | ||
| 5152 | |||
| 5153 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 5154 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 5155 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 5156 | return arg1_value; | ||
| 5157 | |||
| 5158 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 5159 | IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); | ||
| 5160 | if (arg2_value == ag->codegen->invalid_inst_src) | ||
| 5161 | return arg2_value; | ||
| 5162 | |||
| 5163 | AstNode *arg3_node = node->data.fn_call_expr.params.at(3); | ||
| 5164 | IrInstSrc *arg3_value = astgen_node(ag, arg3_node, scope); | ||
| 5165 | if (arg3_value == ag->codegen->invalid_inst_src) | ||
| 5166 | return arg3_value; | ||
| 5167 | |||
| 5168 | AstNode *arg4_node = node->data.fn_call_expr.params.at(4); | ||
| 5169 | IrInstSrc *arg4_value = astgen_node(ag, arg4_node, scope); | ||
| 5170 | if (arg4_value == ag->codegen->invalid_inst_src) | ||
| 5171 | return arg4_value; | ||
| 5172 | |||
| 5173 | IrInstSrc *inst = ir_build_atomic_rmw_src(ag, scope, node, | ||
| 5174 | arg0_value, arg1_value, arg2_value, arg3_value, arg4_value); | ||
| 5175 | return ir_lval_wrap(ag, scope, inst, lval, result_loc); | ||
| 5176 | } | ||
| 5177 | case BuiltinFnIdAtomicLoad: | ||
| 5178 | { | ||
| 5179 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 5180 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 5181 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 5182 | return arg0_value; | ||
| 5183 | |||
| 5184 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 5185 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 5186 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 5187 | return arg1_value; | ||
| 5188 | |||
| 5189 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 5190 | IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); | ||
| 5191 | if (arg2_value == ag->codegen->invalid_inst_src) | ||
| 5192 | return arg2_value; | ||
| 5193 | |||
| 5194 | IrInstSrc *inst = ir_build_atomic_load_src(ag, scope, node, arg0_value, arg1_value, arg2_value); | ||
| 5195 | return ir_lval_wrap(ag, scope, inst, lval, result_loc); | ||
| 5196 | } | ||
| 5197 | case BuiltinFnIdAtomicStore: | ||
| 5198 | { | ||
| 5199 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 5200 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 5201 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 5202 | return arg0_value; | ||
| 5203 | |||
| 5204 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 5205 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 5206 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 5207 | return arg1_value; | ||
| 5208 | |||
| 5209 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 5210 | IrInstSrc *arg2_value = astgen_node(ag, arg2_node, scope); | ||
| 5211 | if (arg2_value == ag->codegen->invalid_inst_src) | ||
| 5212 | return arg2_value; | ||
| 5213 | |||
| 5214 | AstNode *arg3_node = node->data.fn_call_expr.params.at(3); | ||
| 5215 | IrInstSrc *arg3_value = astgen_node(ag, arg3_node, scope); | ||
| 5216 | if (arg3_value == ag->codegen->invalid_inst_src) | ||
| 5217 | return arg3_value; | ||
| 5218 | |||
| 5219 | IrInstSrc *inst = ir_build_atomic_store_src(ag, scope, node, arg0_value, arg1_value, | ||
| 5220 | arg2_value, arg3_value); | ||
| 5221 | return ir_lval_wrap(ag, scope, inst, lval, result_loc); | ||
| 5222 | } | ||
| 5223 | case BuiltinFnIdIntToEnum: | ||
| 5224 | { | ||
| 5225 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 5226 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 5227 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 5228 | return arg0_value; | ||
| 5229 | |||
| 5230 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 5231 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 5232 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 5233 | return arg1_value; | ||
| 5234 | |||
| 5235 | IrInstSrc *result = ir_build_int_to_enum_src(ag, scope, node, arg0_value, arg1_value); | ||
| 5236 | return ir_lval_wrap(ag, scope, result, lval, result_loc); | ||
| 5237 | } | ||
| 5238 | case BuiltinFnIdEnumToInt: | ||
| 5239 | { | ||
| 5240 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 5241 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 5242 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 5243 | return arg0_value; | ||
| 5244 | |||
| 5245 | IrInstSrc *result = ir_build_enum_to_int(ag, scope, node, arg0_value); | ||
| 5246 | return ir_lval_wrap(ag, scope, result, lval, result_loc); | ||
| 5247 | } | ||
| 5248 | case BuiltinFnIdCtz: | ||
| 5249 | case BuiltinFnIdPopCount: | ||
| 5250 | case BuiltinFnIdClz: | ||
| 5251 | case BuiltinFnIdBswap: | ||
| 5252 | case BuiltinFnIdBitReverse: | ||
| 5253 | { | ||
| 5254 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 5255 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 5256 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 5257 | return arg0_value; | ||
| 5258 | |||
| 5259 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 5260 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 5261 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 5262 | return arg1_value; | ||
| 5263 | |||
| 5264 | IrInstSrc *result; | ||
| 5265 | switch (builtin_fn->id) { | ||
| 5266 | case BuiltinFnIdCtz: | ||
| 5267 | result = ir_build_ctz(ag, scope, node, arg0_value, arg1_value); | ||
| 5268 | break; | ||
| 5269 | case BuiltinFnIdPopCount: | ||
| 5270 | result = ir_build_pop_count(ag, scope, node, arg0_value, arg1_value); | ||
| 5271 | break; | ||
| 5272 | case BuiltinFnIdClz: | ||
| 5273 | result = ir_build_clz(ag, scope, node, arg0_value, arg1_value); | ||
| 5274 | break; | ||
| 5275 | case BuiltinFnIdBswap: | ||
| 5276 | result = ir_build_bswap(ag, scope, node, arg0_value, arg1_value); | ||
| 5277 | break; | ||
| 5278 | case BuiltinFnIdBitReverse: | ||
| 5279 | result = ir_build_bit_reverse(ag, scope, node, arg0_value, arg1_value); | ||
| 5280 | break; | ||
| 5281 | default: | ||
| 5282 | zig_unreachable(); | ||
| 5283 | } | ||
| 5284 | return ir_lval_wrap(ag, scope, result, lval, result_loc); | ||
| 5285 | } | ||
| 5286 | case BuiltinFnIdHasDecl: | ||
| 5287 | { | ||
| 5288 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 5289 | IrInstSrc *arg0_value = astgen_node(ag, arg0_node, scope); | ||
| 5290 | if (arg0_value == ag->codegen->invalid_inst_src) | ||
| 5291 | return arg0_value; | ||
| 5292 | |||
| 5293 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 5294 | IrInstSrc *arg1_value = astgen_node(ag, arg1_node, scope); | ||
| 5295 | if (arg1_value == ag->codegen->invalid_inst_src) | ||
| 5296 | return arg1_value; | ||
| 5297 | |||
| 5298 | IrInstSrc *has_decl = ir_build_has_decl(ag, scope, node, arg0_value, arg1_value); | ||
| 5299 | return ir_lval_wrap(ag, scope, has_decl, lval, result_loc); | ||
| 5300 | } | ||
| 5301 | case BuiltinFnIdUnionInit: | ||
| 5302 | { | ||
| 5303 | AstNode *union_type_node = node->data.fn_call_expr.params.at(0); | ||
| 5304 | IrInstSrc *union_type_inst = astgen_node(ag, union_type_node, scope); | ||
| 5305 | if (union_type_inst == ag->codegen->invalid_inst_src) | ||
| 5306 | return union_type_inst; | ||
| 5307 | |||
| 5308 | AstNode *name_node = node->data.fn_call_expr.params.at(1); | ||
| 5309 | IrInstSrc *name_inst = astgen_node(ag, name_node, scope); | ||
| 5310 | if (name_inst == ag->codegen->invalid_inst_src) | ||
| 5311 | return name_inst; | ||
| 5312 | |||
| 5313 | AstNode *init_node = node->data.fn_call_expr.params.at(2); | ||
| 5314 | |||
| 5315 | return astgen_union_init_expr(ag, scope, node, union_type_inst, name_inst, init_node, | ||
| 5316 | lval, result_loc); | ||
| 5317 | } | ||
| 5318 | case BuiltinFnIdSrc: | ||
| 5319 | { | ||
| 5320 | IrInstSrc *src_inst = ir_build_src(ag, scope, node); | ||
| 5321 | return ir_lval_wrap(ag, scope, src_inst, lval, result_loc); | ||
| 5322 | } | ||
| 5323 | } | ||
| 5324 | zig_unreachable(); | ||
| 5325 | } | ||
| 5326 | |||
| 5327 | static ScopeNoSuspend *get_scope_nosuspend(Scope *scope) { | ||
| 5328 | while (scope) { | ||
| 5329 | if (scope->id == ScopeIdNoSuspend) | ||
| 5330 | return (ScopeNoSuspend *)scope; | ||
| 5331 | if (scope->id == ScopeIdFnDef) | ||
| 5332 | return nullptr; | ||
| 5333 | |||
| 5334 | scope = scope->parent; | ||
| 5335 | } | ||
| 5336 | return nullptr; | ||
| 5337 | } | ||
| 5338 | |||
| 5339 | static IrInstSrc *astgen_fn_call(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, | ||
| 5340 | ResultLoc *result_loc) | ||
| 5341 | { | ||
| 5342 | assert(node->type == NodeTypeFnCallExpr); | ||
| 5343 | |||
| 5344 | if (node->data.fn_call_expr.modifier == CallModifierBuiltin) | ||
| 5345 | return astgen_builtin_fn_call(ag, scope, node, lval, result_loc); | ||
| 5346 | |||
| 5347 | bool is_nosuspend = get_scope_nosuspend(scope) != nullptr; | ||
| 5348 | CallModifier modifier = node->data.fn_call_expr.modifier; | ||
| 5349 | if (is_nosuspend && modifier != CallModifierAsync) { | ||
| 5350 | modifier = CallModifierNoSuspend; | ||
| 5351 | } | ||
| 5352 | |||
| 5353 | AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; | ||
| 5354 | return astgen_fn_call_with_args(ag, scope, node, fn_ref_node, modifier, | ||
| 5355 | nullptr, node->data.fn_call_expr.params.items, node->data.fn_call_expr.params.length, lval, result_loc); | ||
| 5356 | } | ||
| 5357 | |||
| 5358 | static IrInstSrc *astgen_if_bool_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, | ||
| 5359 | ResultLoc *result_loc) | ||
| 5360 | { | ||
| 5361 | assert(node->type == NodeTypeIfBoolExpr); | ||
| 5362 | |||
| 5363 | IrInstSrc *condition = astgen_node(ag, node->data.if_bool_expr.condition, scope); | ||
| 5364 | if (condition == ag->codegen->invalid_inst_src) | ||
| 5365 | return ag->codegen->invalid_inst_src; | ||
| 5366 | |||
| 5367 | IrInstSrc *is_comptime; | ||
| 5368 | if (ir_should_inline(ag->exec, scope)) { | ||
| 5369 | is_comptime = ir_build_const_bool(ag, scope, node, true); | ||
| 5370 | } else { | ||
| 5371 | is_comptime = ir_build_test_comptime(ag, scope, node, condition); | ||
| 5372 | } | ||
| 5373 | |||
| 5374 | AstNode *then_node = node->data.if_bool_expr.then_block; | ||
| 5375 | AstNode *else_node = node->data.if_bool_expr.else_node; | ||
| 5376 | |||
| 5377 | Stage1ZirBasicBlock *then_block = ir_create_basic_block(ag, scope, "Then"); | ||
| 5378 | Stage1ZirBasicBlock *else_block = ir_create_basic_block(ag, scope, "Else"); | ||
| 5379 | Stage1ZirBasicBlock *endif_block = ir_create_basic_block(ag, scope, "EndIf"); | ||
| 5380 | |||
| 5381 | IrInstSrc *cond_br_inst = ir_build_cond_br(ag, scope, node, condition, | ||
| 5382 | then_block, else_block, is_comptime); | ||
| 5383 | ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, else_block, endif_block, | ||
| 5384 | result_loc, is_comptime); | ||
| 5385 | |||
| 5386 | ir_set_cursor_at_end_and_append_block(ag, then_block); | ||
| 5387 | |||
| 5388 | Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime); | ||
| 5389 | IrInstSrc *then_expr_result = astgen_node_extra(ag, then_node, subexpr_scope, lval, | ||
| 5390 | &peer_parent->peers.at(0)->base); | ||
| 5391 | if (then_expr_result == ag->codegen->invalid_inst_src) | ||
| 5392 | return ag->codegen->invalid_inst_src; | ||
| 5393 | Stage1ZirBasicBlock *after_then_block = ag->current_basic_block; | ||
| 5394 | if (!instr_is_unreachable(then_expr_result)) | ||
| 5395 | ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); | ||
| 5396 | |||
| 5397 | ir_set_cursor_at_end_and_append_block(ag, else_block); | ||
| 5398 | IrInstSrc *else_expr_result; | ||
| 5399 | if (else_node) { | ||
| 5400 | else_expr_result = astgen_node_extra(ag, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); | ||
| 5401 | if (else_expr_result == ag->codegen->invalid_inst_src) | ||
| 5402 | return ag->codegen->invalid_inst_src; | ||
| 5403 | } else { | ||
| 5404 | else_expr_result = ir_build_const_void(ag, scope, node); | ||
| 5405 | ir_build_end_expr(ag, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); | ||
| 5406 | } | ||
| 5407 | Stage1ZirBasicBlock *after_else_block = ag->current_basic_block; | ||
| 5408 | if (!instr_is_unreachable(else_expr_result)) | ||
| 5409 | ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); | ||
| 5410 | |||
| 5411 | ir_set_cursor_at_end_and_append_block(ag, endif_block); | ||
| 5412 | IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2); | ||
| 5413 | incoming_values[0] = then_expr_result; | ||
| 5414 | incoming_values[1] = else_expr_result; | ||
| 5415 | Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate<Stage1ZirBasicBlock *>(2); | ||
| 5416 | incoming_blocks[0] = after_then_block; | ||
| 5417 | incoming_blocks[1] = after_else_block; | ||
| 5418 | |||
| 5419 | IrInstSrc *phi = ir_build_phi(ag, scope, node, 2, incoming_blocks, incoming_values, peer_parent); | ||
| 5420 | return ir_expr_wrap(ag, scope, phi, result_loc); | ||
| 5421 | } | ||
| 5422 | |||
| 5423 | static IrInstSrc *astgen_prefix_op_id_lval(Stage1AstGen *ag, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) { | ||
| 5424 | assert(node->type == NodeTypePrefixOpExpr); | ||
| 5425 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | ||
| 5426 | |||
| 5427 | IrInstSrc *value = astgen_node_extra(ag, expr_node, scope, lval, nullptr); | ||
| 5428 | if (value == ag->codegen->invalid_inst_src) | ||
| 5429 | return value; | ||
| 5430 | |||
| 5431 | return ir_build_un_op(ag, scope, node, op_id, value); | ||
| 5432 | } | ||
| 5433 | |||
| 5434 | static IrInstSrc *astgen_prefix_op_id(Stage1AstGen *ag, Scope *scope, AstNode *node, IrUnOp op_id) { | ||
| 5435 | return astgen_prefix_op_id_lval(ag, scope, node, op_id, LValNone); | ||
| 5436 | } | ||
| 5437 | |||
| 5438 | static IrInstSrc *ir_expr_wrap(Stage1AstGen *ag, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc) { | ||
| 5439 | if (inst == ag->codegen->invalid_inst_src) return inst; | ||
| 5440 | ir_build_end_expr(ag, scope, inst->base.source_node, inst, result_loc); | ||
| 5441 | return inst; | ||
| 5442 | } | ||
| 5443 | |||
| 5444 | static IrInstSrc *ir_lval_wrap(Stage1AstGen *ag, Scope *scope, IrInstSrc *value, LVal lval, | ||
| 5445 | ResultLoc *result_loc) | ||
| 5446 | { | ||
| 5447 | // This logic must be kept in sync with | ||
| 5448 | // [STMT_EXPR_TEST_THING] <--- (search this token) | ||
| 5449 | if (value == ag->codegen->invalid_inst_src || | ||
| 5450 | instr_is_unreachable(value) || | ||
| 5451 | value->base.source_node->type == NodeTypeDefer || | ||
| 5452 | value->id == IrInstSrcIdDeclVar) | ||
| 5453 | { | ||
| 5454 | return value; | ||
| 5455 | } | ||
| 5456 | |||
| 5457 | assert(lval != LValAssign); | ||
| 5458 | if (lval == LValPtr) { | ||
| 5459 | // We needed a pointer to a value, but we got a value. So we create | ||
| 5460 | // an instruction which just makes a pointer of it. | ||
| 5461 | return ir_build_ref_src(ag, scope, value->base.source_node, value); | ||
| 5462 | } else if (result_loc != nullptr) { | ||
| 5463 | return ir_expr_wrap(ag, scope, value, result_loc); | ||
| 5464 | } else { | ||
| 5465 | return value; | ||
| 5466 | } | ||
| 5467 | |||
| 5468 | } | ||
| 5469 | |||
| 5470 | static PtrLen star_token_to_ptr_len(TokenId token_id) { | ||
| 5471 | switch (token_id) { | ||
| 5472 | case TokenIdStar: | ||
| 5473 | case TokenIdStarStar: | ||
| 5474 | return PtrLenSingle; | ||
| 5475 | case TokenIdLBracket: | ||
| 5476 | return PtrLenUnknown; | ||
| 5477 | case TokenIdIdentifier: | ||
| 5478 | return PtrLenC; | ||
| 5479 | default: | ||
| 5480 | zig_unreachable(); | ||
| 5481 | } | ||
| 5482 | } | ||
| 5483 | |||
| 5484 | static Error token_number_literal_u32(Stage1AstGen *ag, AstNode *source_node, | ||
| 5485 | RootStruct *root_struct, uint32_t *result, TokenIndex token) | ||
| 5486 | { | ||
| 5487 | BigInt bigint; | ||
| 5488 | token_number_literal_bigint(root_struct, &bigint, token); | ||
| 5489 | |||
| 5490 | if (!bigint_fits_in_bits(&bigint, 32, false)) { | ||
| 5491 | Buf *val_buf = buf_alloc(); | ||
| 5492 | bigint_append_buf(val_buf, &bigint, 10); | ||
| 5493 | exec_add_error_node(ag->codegen, ag->exec, source_node, | ||
| 5494 | buf_sprintf("value %s too large for u32", buf_ptr(val_buf))); | ||
| 5495 | bigint_deinit(&bigint); | ||
| 5496 | return ErrorSemanticAnalyzeFail; | ||
| 5497 | } | ||
| 5498 | *result = bigint_as_u32(&bigint); | ||
| 5499 | bigint_deinit(&bigint); | ||
| 5500 | return ErrorNone; | ||
| 5501 | |||
| 5502 | } | ||
| 5503 | |||
| 5504 | static IrInstSrc *astgen_pointer_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 5505 | Error err; | ||
| 5506 | assert(node->type == NodeTypePointerType); | ||
| 5507 | |||
| 5508 | RootStruct *root_struct = node->owner->data.structure.root_struct; | ||
| 5509 | TokenId star_tok_id = root_struct->token_ids[node->data.pointer_type.star_token]; | ||
| 5510 | PtrLen ptr_len = star_token_to_ptr_len(star_tok_id); | ||
| 5511 | |||
| 5512 | bool is_const = node->data.pointer_type.is_const; | ||
| 5513 | bool is_volatile = node->data.pointer_type.is_volatile; | ||
| 5514 | bool is_allow_zero = node->data.pointer_type.allow_zero_token != 0; | ||
| 5515 | AstNode *sentinel_expr = node->data.pointer_type.sentinel; | ||
| 5516 | AstNode *expr_node = node->data.pointer_type.op_expr; | ||
| 5517 | AstNode *align_expr = node->data.pointer_type.align_expr; | ||
| 5518 | |||
| 5519 | IrInstSrc *sentinel; | ||
| 5520 | if (sentinel_expr != nullptr) { | ||
| 5521 | sentinel = astgen_node(ag, sentinel_expr, scope); | ||
| 5522 | if (sentinel == ag->codegen->invalid_inst_src) | ||
| 5523 | return sentinel; | ||
| 5524 | } else { | ||
| 5525 | sentinel = nullptr; | ||
| 5526 | } | ||
| 5527 | |||
| 5528 | IrInstSrc *align_value; | ||
| 5529 | if (align_expr != nullptr) { | ||
| 5530 | align_value = astgen_node(ag, align_expr, scope); | ||
| 5531 | if (align_value == ag->codegen->invalid_inst_src) | ||
| 5532 | return align_value; | ||
| 5533 | } else { | ||
| 5534 | align_value = nullptr; | ||
| 5535 | } | ||
| 5536 | |||
| 5537 | IrInstSrc *child_type = astgen_node(ag, expr_node, scope); | ||
| 5538 | if (child_type == ag->codegen->invalid_inst_src) | ||
| 5539 | return child_type; | ||
| 5540 | |||
| 5541 | uint32_t bit_offset_start = 0; | ||
| 5542 | if (node->data.pointer_type.bit_offset_start != 0) { | ||
| 5543 | if ((err = token_number_literal_u32(ag, node, root_struct, &bit_offset_start, | ||
| 5544 | node->data.pointer_type.bit_offset_start))) | ||
| 5545 | { | ||
| 5546 | return ag->codegen->invalid_inst_src; | ||
| 5547 | } | ||
| 5548 | } | ||
| 5549 | |||
| 5550 | uint32_t host_int_bytes = 0; | ||
| 5551 | if (node->data.pointer_type.host_int_bytes != 0) { | ||
| 5552 | if ((err = token_number_literal_u32(ag, node, root_struct, &host_int_bytes, | ||
| 5553 | node->data.pointer_type.host_int_bytes))) | ||
| 5554 | { | ||
| 5555 | return ag->codegen->invalid_inst_src; | ||
| 5556 | } | ||
| 5557 | } | ||
| 5558 | |||
| 5559 | if (host_int_bytes != 0 && bit_offset_start >= host_int_bytes * 8) { | ||
| 5560 | exec_add_error_node(ag->codegen, ag->exec, node, | ||
| 5561 | buf_sprintf("bit offset starts after end of host integer")); | ||
| 5562 | return ag->codegen->invalid_inst_src; | ||
| 5563 | } | ||
| 5564 | |||
| 5565 | return ir_build_ptr_type(ag, scope, node, child_type, is_const, is_volatile, | ||
| 5566 | ptr_len, sentinel, align_value, bit_offset_start, host_int_bytes, is_allow_zero); | ||
| 5567 | } | ||
| 5568 | |||
| 5569 | static IrInstSrc *astgen_catch_unreachable(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 5570 | AstNode *expr_node, LVal lval, ResultLoc *result_loc) | ||
| 5571 | { | ||
| 5572 | IrInstSrc *err_union_ptr = astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr); | ||
| 5573 | if (err_union_ptr == ag->codegen->invalid_inst_src) | ||
| 5574 | return ag->codegen->invalid_inst_src; | ||
| 5575 | |||
| 5576 | IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(ag, scope, source_node, err_union_ptr, true, false); | ||
| 5577 | if (payload_ptr == ag->codegen->invalid_inst_src) | ||
| 5578 | return ag->codegen->invalid_inst_src; | ||
| 5579 | |||
| 5580 | if (lval == LValPtr) | ||
| 5581 | return payload_ptr; | ||
| 5582 | |||
| 5583 | IrInstSrc *load_ptr = ir_build_load_ptr(ag, scope, source_node, payload_ptr); | ||
| 5584 | return ir_expr_wrap(ag, scope, load_ptr, result_loc); | ||
| 5585 | } | ||
| 5586 | |||
| 5587 | static IrInstSrc *astgen_bool_not(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 5588 | assert(node->type == NodeTypePrefixOpExpr); | ||
| 5589 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | ||
| 5590 | |||
| 5591 | IrInstSrc *value = astgen_node(ag, expr_node, scope); | ||
| 5592 | if (value == ag->codegen->invalid_inst_src) | ||
| 5593 | return ag->codegen->invalid_inst_src; | ||
| 5594 | |||
| 5595 | return ir_build_bool_not(ag, scope, node, value); | ||
| 5596 | } | ||
| 5597 | |||
| 5598 | static IrInstSrc *astgen_prefix_op_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, | ||
| 5599 | ResultLoc *result_loc) | ||
| 5600 | { | ||
| 5601 | assert(node->type == NodeTypePrefixOpExpr); | ||
| 5602 | |||
| 5603 | PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op; | ||
| 5604 | |||
| 5605 | switch (prefix_op) { | ||
| 5606 | case PrefixOpInvalid: | ||
| 5607 | zig_unreachable(); | ||
| 5608 | case PrefixOpBoolNot: | ||
| 5609 | return ir_lval_wrap(ag, scope, astgen_bool_not(ag, scope, node), lval, result_loc); | ||
| 5610 | case PrefixOpBinNot: | ||
| 5611 | return ir_lval_wrap(ag, scope, astgen_prefix_op_id(ag, scope, node, IrUnOpBinNot), lval, result_loc); | ||
| 5612 | case PrefixOpNegation: | ||
| 5613 | return ir_lval_wrap(ag, scope, astgen_prefix_op_id(ag, scope, node, IrUnOpNegation), lval, result_loc); | ||
| 5614 | case PrefixOpNegationWrap: | ||
| 5615 | return ir_lval_wrap(ag, scope, astgen_prefix_op_id(ag, scope, node, IrUnOpNegationWrap), lval, result_loc); | ||
| 5616 | case PrefixOpOptional: | ||
| 5617 | return ir_lval_wrap(ag, scope, astgen_prefix_op_id(ag, scope, node, IrUnOpOptional), lval, result_loc); | ||
| 5618 | case PrefixOpAddrOf: { | ||
| 5619 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | ||
| 5620 | return ir_lval_wrap(ag, scope, astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr), lval, result_loc); | ||
| 5621 | } | ||
| 5622 | } | ||
| 5623 | zig_unreachable(); | ||
| 5624 | } | ||
| 5625 | |||
| 5626 | static IrInstSrc *astgen_union_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *source_node, | ||
| 5627 | IrInstSrc *union_type, IrInstSrc *field_name, AstNode *expr_node, | ||
| 5628 | LVal lval, ResultLoc *parent_result_loc) | ||
| 5629 | { | ||
| 5630 | IrInstSrc *container_ptr = ir_build_resolve_result(ag, scope, source_node, parent_result_loc, union_type); | ||
| 5631 | IrInstSrc *field_ptr = ir_build_field_ptr_instruction(ag, scope, source_node, container_ptr, | ||
| 5632 | field_name, true); | ||
| 5633 | |||
| 5634 | ResultLocInstruction *result_loc_inst = heap::c_allocator.create<ResultLocInstruction>(); | ||
| 5635 | result_loc_inst->base.id = ResultLocIdInstruction; | ||
| 5636 | result_loc_inst->base.source_instruction = field_ptr; | ||
| 5637 | ir_ref_instruction(field_ptr, ag->current_basic_block); | ||
| 5638 | ir_build_reset_result(ag, scope, expr_node, &result_loc_inst->base); | ||
| 5639 | |||
| 5640 | IrInstSrc *expr_value = astgen_node_extra(ag, expr_node, scope, LValNone, | ||
| 5641 | &result_loc_inst->base); | ||
| 5642 | if (expr_value == ag->codegen->invalid_inst_src) | ||
| 5643 | return expr_value; | ||
| 5644 | |||
| 5645 | IrInstSrc *init_union = ir_build_union_init_named_field(ag, scope, source_node, union_type, | ||
| 5646 | field_name, field_ptr, container_ptr); | ||
| 5647 | |||
| 5648 | return ir_lval_wrap(ag, scope, init_union, lval, parent_result_loc); | ||
| 5649 | } | ||
| 5650 | |||
| 5651 | static IrInstSrc *astgen_container_init_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, | ||
| 5652 | ResultLoc *parent_result_loc) | ||
| 5653 | { | ||
| 5654 | assert(node->type == NodeTypeContainerInitExpr); | ||
| 5655 | |||
| 5656 | AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr; | ||
| 5657 | ContainerInitKind kind = container_init_expr->kind; | ||
| 5658 | |||
| 5659 | ResultLocCast *result_loc_cast = nullptr; | ||
| 5660 | ResultLoc *child_result_loc; | ||
| 5661 | AstNode *init_array_type_source_node; | ||
| 5662 | if (container_init_expr->type != nullptr) { | ||
| 5663 | IrInstSrc *container_type; | ||
| 5664 | if (container_init_expr->type->type == NodeTypeInferredArrayType) { | ||
| 5665 | if (kind == ContainerInitKindStruct) { | ||
| 5666 | add_node_error(ag->codegen, container_init_expr->type, | ||
| 5667 | buf_sprintf("initializing array with struct syntax")); | ||
| 5668 | return ag->codegen->invalid_inst_src; | ||
| 5669 | } | ||
| 5670 | IrInstSrc *sentinel; | ||
| 5671 | if (container_init_expr->type->data.inferred_array_type.sentinel != nullptr) { | ||
| 5672 | sentinel = astgen_node(ag, container_init_expr->type->data.inferred_array_type.sentinel, scope); | ||
| 5673 | if (sentinel == ag->codegen->invalid_inst_src) | ||
| 5674 | return sentinel; | ||
| 5675 | } else { | ||
| 5676 | sentinel = nullptr; | ||
| 5677 | } | ||
| 5678 | |||
| 5679 | IrInstSrc *elem_type = astgen_node(ag, | ||
| 5680 | container_init_expr->type->data.inferred_array_type.child_type, scope); | ||
| 5681 | if (elem_type == ag->codegen->invalid_inst_src) | ||
| 5682 | return elem_type; | ||
| 5683 | size_t item_count = container_init_expr->entries.length; | ||
| 5684 | IrInstSrc *item_count_inst = ir_build_const_usize(ag, scope, node, item_count); | ||
| 5685 | container_type = ir_build_array_type(ag, scope, node, item_count_inst, sentinel, elem_type); | ||
| 5686 | } else { | ||
| 5687 | container_type = astgen_node(ag, container_init_expr->type, scope); | ||
| 5688 | if (container_type == ag->codegen->invalid_inst_src) | ||
| 5689 | return container_type; | ||
| 5690 | } | ||
| 5691 | |||
| 5692 | result_loc_cast = ir_build_cast_result_loc(ag, container_type, parent_result_loc); | ||
| 5693 | child_result_loc = &result_loc_cast->base; | ||
| 5694 | init_array_type_source_node = container_type->base.source_node; | ||
| 5695 | } else { | ||
| 5696 | child_result_loc = parent_result_loc; | ||
| 5697 | if (parent_result_loc->source_instruction != nullptr) { | ||
| 5698 | init_array_type_source_node = parent_result_loc->source_instruction->base.source_node; | ||
| 5699 | } else { | ||
| 5700 | init_array_type_source_node = node; | ||
| 5701 | } | ||
| 5702 | } | ||
| 5703 | |||
| 5704 | switch (kind) { | ||
| 5705 | case ContainerInitKindStruct: { | ||
| 5706 | IrInstSrc *container_ptr = ir_build_resolve_result(ag, scope, node, child_result_loc, | ||
| 5707 | nullptr); | ||
| 5708 | |||
| 5709 | size_t field_count = container_init_expr->entries.length; | ||
| 5710 | IrInstSrcContainerInitFieldsField *fields = heap::c_allocator.allocate<IrInstSrcContainerInitFieldsField>(field_count); | ||
| 5711 | for (size_t i = 0; i < field_count; i += 1) { | ||
| 5712 | AstNode *entry_node = container_init_expr->entries.at(i); | ||
| 5713 | assert(entry_node->type == NodeTypeStructValueField); | ||
| 5714 | |||
| 5715 | Buf *name = entry_node->data.struct_val_field.name; | ||
| 5716 | AstNode *expr_node = entry_node->data.struct_val_field.expr; | ||
| 5717 | |||
| 5718 | IrInstSrc *field_ptr = ir_build_field_ptr(ag, scope, entry_node, container_ptr, name, true); | ||
| 5719 | ResultLocInstruction *result_loc_inst = heap::c_allocator.create<ResultLocInstruction>(); | ||
| 5720 | result_loc_inst->base.id = ResultLocIdInstruction; | ||
| 5721 | result_loc_inst->base.source_instruction = field_ptr; | ||
| 5722 | result_loc_inst->base.allow_write_through_const = true; | ||
| 5723 | ir_ref_instruction(field_ptr, ag->current_basic_block); | ||
| 5724 | ir_build_reset_result(ag, scope, expr_node, &result_loc_inst->base); | ||
| 5725 | |||
| 5726 | IrInstSrc *expr_value = astgen_node_extra(ag, expr_node, scope, LValNone, | ||
| 5727 | &result_loc_inst->base); | ||
| 5728 | if (expr_value == ag->codegen->invalid_inst_src) | ||
| 5729 | return expr_value; | ||
| 5730 | |||
| 5731 | fields[i].name = name; | ||
| 5732 | fields[i].source_node = entry_node; | ||
| 5733 | fields[i].result_loc = field_ptr; | ||
| 5734 | } | ||
| 5735 | IrInstSrc *result = ir_build_container_init_fields(ag, scope, node, field_count, | ||
| 5736 | fields, container_ptr); | ||
| 5737 | |||
| 5738 | if (result_loc_cast != nullptr) { | ||
| 5739 | result = ir_build_implicit_cast(ag, scope, node, result, result_loc_cast); | ||
| 5740 | } | ||
| 5741 | return ir_lval_wrap(ag, scope, result, lval, parent_result_loc); | ||
| 5742 | } | ||
| 5743 | case ContainerInitKindArray: { | ||
| 5744 | size_t item_count = container_init_expr->entries.length; | ||
| 5745 | |||
| 5746 | IrInstSrc *container_ptr = ir_build_resolve_result(ag, scope, node, child_result_loc, | ||
| 5747 | nullptr); | ||
| 5748 | |||
| 5749 | IrInstSrc **result_locs = heap::c_allocator.allocate<IrInstSrc *>(item_count); | ||
| 5750 | for (size_t i = 0; i < item_count; i += 1) { | ||
| 5751 | AstNode *expr_node = container_init_expr->entries.at(i); | ||
| 5752 | |||
| 5753 | IrInstSrc *elem_index = ir_build_const_usize(ag, scope, expr_node, i); | ||
| 5754 | IrInstSrc *elem_ptr = ir_build_elem_ptr(ag, scope, expr_node, container_ptr, | ||
| 5755 | elem_index, false, PtrLenSingle, init_array_type_source_node); | ||
| 5756 | ResultLocInstruction *result_loc_inst = heap::c_allocator.create<ResultLocInstruction>(); | ||
| 5757 | result_loc_inst->base.id = ResultLocIdInstruction; | ||
| 5758 | result_loc_inst->base.source_instruction = elem_ptr; | ||
| 5759 | result_loc_inst->base.allow_write_through_const = true; | ||
| 5760 | ir_ref_instruction(elem_ptr, ag->current_basic_block); | ||
| 5761 | ir_build_reset_result(ag, scope, expr_node, &result_loc_inst->base); | ||
| 5762 | |||
| 5763 | IrInstSrc *expr_value = astgen_node_extra(ag, expr_node, scope, LValNone, | ||
| 5764 | &result_loc_inst->base); | ||
| 5765 | if (expr_value == ag->codegen->invalid_inst_src) | ||
| 5766 | return expr_value; | ||
| 5767 | |||
| 5768 | result_locs[i] = elem_ptr; | ||
| 5769 | } | ||
| 5770 | IrInstSrc *result = ir_build_container_init_list(ag, scope, node, item_count, | ||
| 5771 | result_locs, container_ptr, init_array_type_source_node); | ||
| 5772 | if (result_loc_cast != nullptr) { | ||
| 5773 | result = ir_build_implicit_cast(ag, scope, node, result, result_loc_cast); | ||
| 5774 | } | ||
| 5775 | return ir_lval_wrap(ag, scope, result, lval, parent_result_loc); | ||
| 5776 | } | ||
| 5777 | } | ||
| 5778 | zig_unreachable(); | ||
| 5779 | } | ||
| 5780 | |||
| 5781 | static ResultLocVar *ir_build_var_result_loc(Stage1AstGen *ag, IrInstSrc *alloca, ZigVar *var) { | ||
| 5782 | ResultLocVar *result_loc_var = heap::c_allocator.create<ResultLocVar>(); | ||
| 5783 | result_loc_var->base.id = ResultLocIdVar; | ||
| 5784 | result_loc_var->base.source_instruction = alloca; | ||
| 5785 | result_loc_var->base.allow_write_through_const = true; | ||
| 5786 | result_loc_var->var = var; | ||
| 5787 | |||
| 5788 | ir_build_reset_result(ag, alloca->base.scope, alloca->base.source_node, &result_loc_var->base); | ||
| 5789 | |||
| 5790 | return result_loc_var; | ||
| 5791 | } | ||
| 5792 | |||
| 5793 | static ResultLocCast *ir_build_cast_result_loc(Stage1AstGen *ag, IrInstSrc *dest_type, | ||
| 5794 | ResultLoc *parent_result_loc) | ||
| 5795 | { | ||
| 5796 | ResultLocCast *result_loc_cast = heap::c_allocator.create<ResultLocCast>(); | ||
| 5797 | result_loc_cast->base.id = ResultLocIdCast; | ||
| 5798 | result_loc_cast->base.source_instruction = dest_type; | ||
| 5799 | result_loc_cast->base.allow_write_through_const = parent_result_loc->allow_write_through_const; | ||
| 5800 | ir_ref_instruction(dest_type, ag->current_basic_block); | ||
| 5801 | result_loc_cast->parent = parent_result_loc; | ||
| 5802 | |||
| 5803 | ir_build_reset_result(ag, dest_type->base.scope, dest_type->base.source_node, &result_loc_cast->base); | ||
| 5804 | |||
| 5805 | return result_loc_cast; | ||
| 5806 | } | ||
| 5807 | |||
| 5808 | static void build_decl_var_and_init(Stage1AstGen *ag, Scope *scope, AstNode *source_node, ZigVar *var, | ||
| 5809 | IrInstSrc *init, const char *name_hint, IrInstSrc *is_comptime) | ||
| 5810 | { | ||
| 5811 | IrInstSrc *alloca = ir_build_alloca_src(ag, scope, source_node, nullptr, name_hint, is_comptime); | ||
| 5812 | ResultLocVar *var_result_loc = ir_build_var_result_loc(ag, alloca, var); | ||
| 5813 | ir_build_end_expr(ag, scope, source_node, init, &var_result_loc->base); | ||
| 5814 | ir_build_var_decl_src(ag, scope, source_node, var, nullptr, alloca); | ||
| 5815 | } | ||
| 5816 | |||
| 5817 | static IrInstSrc *astgen_var_decl(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 5818 | assert(node->type == NodeTypeVariableDeclaration); | ||
| 5819 | |||
| 5820 | AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration; | ||
| 5821 | |||
| 5822 | if (buf_eql_str(variable_declaration->symbol, "_")) { | ||
| 5823 | add_node_error(ag->codegen, node, buf_sprintf("`_` is not a declarable symbol")); | ||
| 5824 | return ag->codegen->invalid_inst_src; | ||
| 5825 | } | ||
| 5826 | |||
| 5827 | // Used for the type expr and the align expr | ||
| 5828 | Scope *comptime_scope = create_comptime_scope(ag->codegen, node, scope); | ||
| 5829 | |||
| 5830 | IrInstSrc *type_instruction; | ||
| 5831 | if (variable_declaration->type != nullptr) { | ||
| 5832 | type_instruction = astgen_node(ag, variable_declaration->type, comptime_scope); | ||
| 5833 | if (type_instruction == ag->codegen->invalid_inst_src) | ||
| 5834 | return type_instruction; | ||
| 5835 | } else { | ||
| 5836 | type_instruction = nullptr; | ||
| 5837 | } | ||
| 5838 | |||
| 5839 | bool is_shadowable = false; | ||
| 5840 | bool is_const = variable_declaration->is_const; | ||
| 5841 | bool is_extern = variable_declaration->is_extern; | ||
| 5842 | |||
| 5843 | bool is_comptime_scalar = ir_should_inline(ag->exec, scope) || variable_declaration->is_comptime; | ||
| 5844 | IrInstSrc *is_comptime = ir_build_const_bool(ag, scope, node, is_comptime_scalar); | ||
| 5845 | ZigVar *var = ir_create_var(ag, node, scope, variable_declaration->symbol, | ||
| 5846 | is_const, is_const, is_shadowable, is_comptime); | ||
| 5847 | // we detect IrInstSrcDeclVar in gen_block to make sure the next node | ||
| 5848 | // is inside var->child_scope | ||
| 5849 | |||
| 5850 | if (!is_extern && !variable_declaration->expr) { | ||
| 5851 | var->var_type = ag->codegen->builtin_types.entry_invalid; | ||
| 5852 | add_node_error(ag->codegen, node, buf_sprintf("variables must be initialized")); | ||
| 5853 | return ag->codegen->invalid_inst_src; | ||
| 5854 | } | ||
| 5855 | |||
| 5856 | IrInstSrc *align_value = nullptr; | ||
| 5857 | if (variable_declaration->align_expr != nullptr) { | ||
| 5858 | align_value = astgen_node(ag, variable_declaration->align_expr, comptime_scope); | ||
| 5859 | if (align_value == ag->codegen->invalid_inst_src) | ||
| 5860 | return align_value; | ||
| 5861 | } | ||
| 5862 | |||
| 5863 | if (variable_declaration->section_expr != nullptr) { | ||
| 5864 | add_node_error(ag->codegen, variable_declaration->section_expr, | ||
| 5865 | buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol))); | ||
| 5866 | } | ||
| 5867 | |||
| 5868 | // Parser should ensure that this never happens | ||
| 5869 | assert(variable_declaration->threadlocal_tok == 0); | ||
| 5870 | |||
| 5871 | IrInstSrc *alloca = ir_build_alloca_src(ag, scope, node, align_value, | ||
| 5872 | buf_ptr(variable_declaration->symbol), is_comptime); | ||
| 5873 | |||
| 5874 | // Create a result location for the initialization expression. | ||
| 5875 | ResultLocVar *result_loc_var = ir_build_var_result_loc(ag, alloca, var); | ||
| 5876 | ResultLoc *init_result_loc; | ||
| 5877 | ResultLocCast *result_loc_cast; | ||
| 5878 | if (type_instruction != nullptr) { | ||
| 5879 | result_loc_cast = ir_build_cast_result_loc(ag, type_instruction, &result_loc_var->base); | ||
| 5880 | init_result_loc = &result_loc_cast->base; | ||
| 5881 | } else { | ||
| 5882 | result_loc_cast = nullptr; | ||
| 5883 | init_result_loc = &result_loc_var->base; | ||
| 5884 | } | ||
| 5885 | |||
| 5886 | Scope *init_scope = is_comptime_scalar ? | ||
| 5887 | create_comptime_scope(ag->codegen, variable_declaration->expr, scope) : scope; | ||
| 5888 | |||
| 5889 | // Temporarily set the name of the Stage1Zir to the VariableDeclaration | ||
| 5890 | // so that the struct or enum from the init expression inherits the name. | ||
| 5891 | Buf *old_exec_name = ag->exec->name; | ||
| 5892 | ag->exec->name = variable_declaration->symbol; | ||
| 5893 | IrInstSrc *init_value = astgen_node_extra(ag, variable_declaration->expr, init_scope, | ||
| 5894 | LValNone, init_result_loc); | ||
| 5895 | ag->exec->name = old_exec_name; | ||
| 5896 | |||
| 5897 | if (init_value == ag->codegen->invalid_inst_src) | ||
| 5898 | return ag->codegen->invalid_inst_src; | ||
| 5899 | |||
| 5900 | if (result_loc_cast != nullptr) { | ||
| 5901 | IrInstSrc *implicit_cast = ir_build_implicit_cast(ag, scope, init_value->base.source_node, | ||
| 5902 | init_value, result_loc_cast); | ||
| 5903 | ir_build_end_expr(ag, scope, node, implicit_cast, &result_loc_var->base); | ||
| 5904 | } | ||
| 5905 | |||
| 5906 | return ir_build_var_decl_src(ag, scope, node, var, align_value, alloca); | ||
| 5907 | } | ||
| 5908 | |||
| 5909 | static IrInstSrc *astgen_while_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, | ||
| 5910 | ResultLoc *result_loc) | ||
| 5911 | { | ||
| 5912 | assert(node->type == NodeTypeWhileExpr); | ||
| 5913 | |||
| 5914 | AstNode *continue_expr_node = node->data.while_expr.continue_expr; | ||
| 5915 | AstNode *else_node = node->data.while_expr.else_node; | ||
| 5916 | |||
| 5917 | Stage1ZirBasicBlock *cond_block = ir_create_basic_block(ag, scope, "WhileCond"); | ||
| 5918 | Stage1ZirBasicBlock *body_block = ir_create_basic_block(ag, scope, "WhileBody"); | ||
| 5919 | Stage1ZirBasicBlock *continue_block = continue_expr_node ? | ||
| 5920 | ir_create_basic_block(ag, scope, "WhileContinue") : cond_block; | ||
| 5921 | Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, scope, "WhileEnd"); | ||
| 5922 | Stage1ZirBasicBlock *else_block = else_node ? | ||
| 5923 | ir_create_basic_block(ag, scope, "WhileElse") : end_block; | ||
| 5924 | |||
| 5925 | IrInstSrc *is_comptime = ir_build_const_bool(ag, scope, node, | ||
| 5926 | ir_should_inline(ag->exec, scope) || node->data.while_expr.is_inline); | ||
| 5927 | ir_build_br(ag, scope, node, cond_block, is_comptime); | ||
| 5928 | |||
| 5929 | Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime); | ||
| 5930 | Buf *var_symbol = node->data.while_expr.var_symbol; | ||
| 5931 | Buf *err_symbol = node->data.while_expr.err_symbol; | ||
| 5932 | if (err_symbol != nullptr) { | ||
| 5933 | ir_set_cursor_at_end_and_append_block(ag, cond_block); | ||
| 5934 | |||
| 5935 | Scope *payload_scope; | ||
| 5936 | AstNode *symbol_node = node; // TODO make more accurate | ||
| 5937 | ZigVar *payload_var; | ||
| 5938 | if (var_symbol) { | ||
| 5939 | // TODO make it an error to write to payload variable | ||
| 5940 | payload_var = ir_create_var(ag, symbol_node, subexpr_scope, var_symbol, | ||
| 5941 | true, false, false, is_comptime); | ||
| 5942 | payload_scope = payload_var->child_scope; | ||
| 5943 | } else { | ||
| 5944 | payload_scope = subexpr_scope; | ||
| 5945 | } | ||
| 5946 | ScopeExpr *spill_scope = create_expr_scope(ag->codegen, node, payload_scope); | ||
| 5947 | IrInstSrc *err_val_ptr = astgen_node_extra(ag, node->data.while_expr.condition, subexpr_scope, | ||
| 5948 | LValPtr, nullptr); | ||
| 5949 | if (err_val_ptr == ag->codegen->invalid_inst_src) | ||
| 5950 | return err_val_ptr; | ||
| 5951 | IrInstSrc *is_err = ir_build_test_err_src(ag, scope, node->data.while_expr.condition, err_val_ptr, | ||
| 5952 | true, false); | ||
| 5953 | Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block; | ||
| 5954 | IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, scope, node)); | ||
| 5955 | IrInstSrc *cond_br_inst; | ||
| 5956 | if (!instr_is_unreachable(is_err)) { | ||
| 5957 | cond_br_inst = ir_build_cond_br(ag, scope, node->data.while_expr.condition, is_err, | ||
| 5958 | else_block, body_block, is_comptime); | ||
| 5959 | cond_br_inst->is_gen = true; | ||
| 5960 | } else { | ||
| 5961 | // for the purposes of the source instruction to ir_build_result_peers | ||
| 5962 | cond_br_inst = ag->current_basic_block->instruction_list.last(); | ||
| 5963 | } | ||
| 5964 | |||
| 5965 | ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, result_loc, | ||
| 5966 | is_comptime); | ||
| 5967 | |||
| 5968 | ir_set_cursor_at_end_and_append_block(ag, body_block); | ||
| 5969 | if (var_symbol) { | ||
| 5970 | IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(ag, &spill_scope->base, symbol_node, | ||
| 5971 | err_val_ptr, false, false); | ||
| 5972 | IrInstSrc *var_value = node->data.while_expr.var_is_ptr ? | ||
| 5973 | payload_ptr : ir_build_load_ptr(ag, &spill_scope->base, symbol_node, payload_ptr); | ||
| 5974 | build_decl_var_and_init(ag, payload_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); | ||
| 5975 | } | ||
| 5976 | |||
| 5977 | ZigList<IrInstSrc *> incoming_values = {0}; | ||
| 5978 | ZigList<Stage1ZirBasicBlock *> incoming_blocks = {0}; | ||
| 5979 | |||
| 5980 | if (is_duplicate_label(ag->codegen, payload_scope, node, node->data.while_expr.name)) | ||
| 5981 | return ag->codegen->invalid_inst_src; | ||
| 5982 | |||
| 5983 | ScopeLoop *loop_scope = create_loop_scope(ag->codegen, node, payload_scope); | ||
| 5984 | loop_scope->break_block = end_block; | ||
| 5985 | loop_scope->continue_block = continue_block; | ||
| 5986 | loop_scope->is_comptime = is_comptime; | ||
| 5987 | loop_scope->incoming_blocks = &incoming_blocks; | ||
| 5988 | loop_scope->incoming_values = &incoming_values; | ||
| 5989 | loop_scope->lval = lval; | ||
| 5990 | loop_scope->peer_parent = peer_parent; | ||
| 5991 | loop_scope->spill_scope = spill_scope; | ||
| 5992 | |||
| 5993 | // Note the body block of the loop is not the place that lval and result_loc are used - | ||
| 5994 | // it's actually in break statements, handled similarly to return statements. | ||
| 5995 | // That is why we set those values in loop_scope above and not in this astgen_node call. | ||
| 5996 | IrInstSrc *body_result = astgen_node(ag, node->data.while_expr.body, &loop_scope->base); | ||
| 5997 | if (body_result == ag->codegen->invalid_inst_src) | ||
| 5998 | return body_result; | ||
| 5999 | |||
| 6000 | if (loop_scope->name != nullptr && loop_scope->name_used == false) { | ||
| 6001 | add_node_error(ag->codegen, node, buf_sprintf("unused while label")); | ||
| 6002 | } | ||
| 6003 | |||
| 6004 | if (!instr_is_unreachable(body_result)) { | ||
| 6005 | ir_mark_gen(ir_build_check_statement_is_void(ag, payload_scope, node->data.while_expr.body, body_result)); | ||
| 6006 | ir_mark_gen(ir_build_br(ag, payload_scope, node, continue_block, is_comptime)); | ||
| 6007 | } | ||
| 6008 | |||
| 6009 | if (continue_expr_node) { | ||
| 6010 | ir_set_cursor_at_end_and_append_block(ag, continue_block); | ||
| 6011 | IrInstSrc *expr_result = astgen_node(ag, continue_expr_node, payload_scope); | ||
| 6012 | if (expr_result == ag->codegen->invalid_inst_src) | ||
| 6013 | return expr_result; | ||
| 6014 | if (!instr_is_unreachable(expr_result)) { | ||
| 6015 | ir_mark_gen(ir_build_check_statement_is_void(ag, payload_scope, continue_expr_node, expr_result)); | ||
| 6016 | ir_mark_gen(ir_build_br(ag, payload_scope, node, cond_block, is_comptime)); | ||
| 6017 | } | ||
| 6018 | } | ||
| 6019 | |||
| 6020 | ir_set_cursor_at_end_and_append_block(ag, else_block); | ||
| 6021 | assert(else_node != nullptr); | ||
| 6022 | |||
| 6023 | // TODO make it an error to write to error variable | ||
| 6024 | AstNode *err_symbol_node = else_node; // TODO make more accurate | ||
| 6025 | ZigVar *err_var = ir_create_var(ag, err_symbol_node, scope, err_symbol, | ||
| 6026 | true, false, false, is_comptime); | ||
| 6027 | Scope *err_scope = err_var->child_scope; | ||
| 6028 | IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(ag, err_scope, err_symbol_node, err_val_ptr); | ||
| 6029 | IrInstSrc *err_value = ir_build_load_ptr(ag, err_scope, err_symbol_node, err_ptr); | ||
| 6030 | build_decl_var_and_init(ag, err_scope, err_symbol_node, err_var, err_value, buf_ptr(err_symbol), is_comptime); | ||
| 6031 | |||
| 6032 | if (peer_parent->peers.length != 0) { | ||
| 6033 | peer_parent->peers.last()->next_bb = else_block; | ||
| 6034 | } | ||
| 6035 | ResultLocPeer *peer_result = create_peer_result(peer_parent); | ||
| 6036 | peer_parent->peers.append(peer_result); | ||
| 6037 | IrInstSrc *else_result = astgen_node_extra(ag, else_node, err_scope, lval, &peer_result->base); | ||
| 6038 | if (else_result == ag->codegen->invalid_inst_src) | ||
| 6039 | return else_result; | ||
| 6040 | if (!instr_is_unreachable(else_result)) | ||
| 6041 | ir_mark_gen(ir_build_br(ag, scope, node, end_block, is_comptime)); | ||
| 6042 | Stage1ZirBasicBlock *after_else_block = ag->current_basic_block; | ||
| 6043 | ir_set_cursor_at_end_and_append_block(ag, end_block); | ||
| 6044 | if (else_result) { | ||
| 6045 | incoming_blocks.append(after_else_block); | ||
| 6046 | incoming_values.append(else_result); | ||
| 6047 | } else { | ||
| 6048 | incoming_blocks.append(after_cond_block); | ||
| 6049 | incoming_values.append(void_else_result); | ||
| 6050 | } | ||
| 6051 | if (peer_parent->peers.length != 0) { | ||
| 6052 | peer_parent->peers.last()->next_bb = end_block; | ||
| 6053 | } | ||
| 6054 | |||
| 6055 | IrInstSrc *phi = ir_build_phi(ag, scope, node, incoming_blocks.length, | ||
| 6056 | incoming_blocks.items, incoming_values.items, peer_parent); | ||
| 6057 | return ir_expr_wrap(ag, scope, phi, result_loc); | ||
| 6058 | } else if (var_symbol != nullptr) { | ||
| 6059 | ir_set_cursor_at_end_and_append_block(ag, cond_block); | ||
| 6060 | Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime); | ||
| 6061 | // TODO make it an error to write to payload variable | ||
| 6062 | AstNode *symbol_node = node; // TODO make more accurate | ||
| 6063 | |||
| 6064 | ZigVar *payload_var = ir_create_var(ag, symbol_node, subexpr_scope, var_symbol, | ||
| 6065 | true, false, false, is_comptime); | ||
| 6066 | Scope *child_scope = payload_var->child_scope; | ||
| 6067 | ScopeExpr *spill_scope = create_expr_scope(ag->codegen, node, child_scope); | ||
| 6068 | IrInstSrc *maybe_val_ptr = astgen_node_extra(ag, node->data.while_expr.condition, subexpr_scope, | ||
| 6069 | LValPtr, nullptr); | ||
| 6070 | if (maybe_val_ptr == ag->codegen->invalid_inst_src) | ||
| 6071 | return maybe_val_ptr; | ||
| 6072 | IrInstSrc *maybe_val = ir_build_load_ptr(ag, scope, node->data.while_expr.condition, maybe_val_ptr); | ||
| 6073 | IrInstSrc *is_non_null = ir_build_test_non_null_src(ag, scope, node->data.while_expr.condition, maybe_val); | ||
| 6074 | Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block; | ||
| 6075 | IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, scope, node)); | ||
| 6076 | IrInstSrc *cond_br_inst; | ||
| 6077 | if (!instr_is_unreachable(is_non_null)) { | ||
| 6078 | cond_br_inst = ir_build_cond_br(ag, scope, node->data.while_expr.condition, is_non_null, | ||
| 6079 | body_block, else_block, is_comptime); | ||
| 6080 | cond_br_inst->is_gen = true; | ||
| 6081 | } else { | ||
| 6082 | // for the purposes of the source instruction to ir_build_result_peers | ||
| 6083 | cond_br_inst = ag->current_basic_block->instruction_list.last(); | ||
| 6084 | } | ||
| 6085 | |||
| 6086 | ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, result_loc, | ||
| 6087 | is_comptime); | ||
| 6088 | |||
| 6089 | ir_set_cursor_at_end_and_append_block(ag, body_block); | ||
| 6090 | IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(ag, &spill_scope->base, symbol_node, maybe_val_ptr, false); | ||
| 6091 | IrInstSrc *var_value = node->data.while_expr.var_is_ptr ? | ||
| 6092 | payload_ptr : ir_build_load_ptr(ag, &spill_scope->base, symbol_node, payload_ptr); | ||
| 6093 | build_decl_var_and_init(ag, child_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); | ||
| 6094 | |||
| 6095 | ZigList<IrInstSrc *> incoming_values = {0}; | ||
| 6096 | ZigList<Stage1ZirBasicBlock *> incoming_blocks = {0}; | ||
| 6097 | |||
| 6098 | if (is_duplicate_label(ag->codegen, child_scope, node, node->data.while_expr.name)) | ||
| 6099 | return ag->codegen->invalid_inst_src; | ||
| 6100 | |||
| 6101 | ScopeLoop *loop_scope = create_loop_scope(ag->codegen, node, child_scope); | ||
| 6102 | loop_scope->break_block = end_block; | ||
| 6103 | loop_scope->continue_block = continue_block; | ||
| 6104 | loop_scope->is_comptime = is_comptime; | ||
| 6105 | loop_scope->incoming_blocks = &incoming_blocks; | ||
| 6106 | loop_scope->incoming_values = &incoming_values; | ||
| 6107 | loop_scope->lval = lval; | ||
| 6108 | loop_scope->peer_parent = peer_parent; | ||
| 6109 | loop_scope->spill_scope = spill_scope; | ||
| 6110 | |||
| 6111 | // Note the body block of the loop is not the place that lval and result_loc are used - | ||
| 6112 | // it's actually in break statements, handled similarly to return statements. | ||
| 6113 | // That is why we set those values in loop_scope above and not in this astgen_node call. | ||
| 6114 | IrInstSrc *body_result = astgen_node(ag, node->data.while_expr.body, &loop_scope->base); | ||
| 6115 | if (body_result == ag->codegen->invalid_inst_src) | ||
| 6116 | return body_result; | ||
| 6117 | |||
| 6118 | if (loop_scope->name != nullptr && loop_scope->name_used == false) { | ||
| 6119 | add_node_error(ag->codegen, node, buf_sprintf("unused while label")); | ||
| 6120 | } | ||
| 6121 | |||
| 6122 | if (!instr_is_unreachable(body_result)) { | ||
| 6123 | ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, node->data.while_expr.body, body_result)); | ||
| 6124 | ir_mark_gen(ir_build_br(ag, child_scope, node, continue_block, is_comptime)); | ||
| 6125 | } | ||
| 6126 | |||
| 6127 | if (continue_expr_node) { | ||
| 6128 | ir_set_cursor_at_end_and_append_block(ag, continue_block); | ||
| 6129 | IrInstSrc *expr_result = astgen_node(ag, continue_expr_node, child_scope); | ||
| 6130 | if (expr_result == ag->codegen->invalid_inst_src) | ||
| 6131 | return expr_result; | ||
| 6132 | if (!instr_is_unreachable(expr_result)) { | ||
| 6133 | ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, continue_expr_node, expr_result)); | ||
| 6134 | ir_mark_gen(ir_build_br(ag, child_scope, node, cond_block, is_comptime)); | ||
| 6135 | } | ||
| 6136 | } | ||
| 6137 | |||
| 6138 | IrInstSrc *else_result = nullptr; | ||
| 6139 | if (else_node) { | ||
| 6140 | ir_set_cursor_at_end_and_append_block(ag, else_block); | ||
| 6141 | |||
| 6142 | if (peer_parent->peers.length != 0) { | ||
| 6143 | peer_parent->peers.last()->next_bb = else_block; | ||
| 6144 | } | ||
| 6145 | ResultLocPeer *peer_result = create_peer_result(peer_parent); | ||
| 6146 | peer_parent->peers.append(peer_result); | ||
| 6147 | else_result = astgen_node_extra(ag, else_node, scope, lval, &peer_result->base); | ||
| 6148 | if (else_result == ag->codegen->invalid_inst_src) | ||
| 6149 | return else_result; | ||
| 6150 | if (!instr_is_unreachable(else_result)) | ||
| 6151 | ir_mark_gen(ir_build_br(ag, scope, node, end_block, is_comptime)); | ||
| 6152 | } | ||
| 6153 | Stage1ZirBasicBlock *after_else_block = ag->current_basic_block; | ||
| 6154 | ir_set_cursor_at_end_and_append_block(ag, end_block); | ||
| 6155 | if (else_result) { | ||
| 6156 | incoming_blocks.append(after_else_block); | ||
| 6157 | incoming_values.append(else_result); | ||
| 6158 | } else { | ||
| 6159 | incoming_blocks.append(after_cond_block); | ||
| 6160 | incoming_values.append(void_else_result); | ||
| 6161 | } | ||
| 6162 | if (peer_parent->peers.length != 0) { | ||
| 6163 | peer_parent->peers.last()->next_bb = end_block; | ||
| 6164 | } | ||
| 6165 | |||
| 6166 | IrInstSrc *phi = ir_build_phi(ag, scope, node, incoming_blocks.length, | ||
| 6167 | incoming_blocks.items, incoming_values.items, peer_parent); | ||
| 6168 | return ir_expr_wrap(ag, scope, phi, result_loc); | ||
| 6169 | } else { | ||
| 6170 | ir_set_cursor_at_end_and_append_block(ag, cond_block); | ||
| 6171 | IrInstSrc *cond_val = astgen_node(ag, node->data.while_expr.condition, scope); | ||
| 6172 | if (cond_val == ag->codegen->invalid_inst_src) | ||
| 6173 | return cond_val; | ||
| 6174 | Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block; | ||
| 6175 | IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, scope, node)); | ||
| 6176 | IrInstSrc *cond_br_inst; | ||
| 6177 | if (!instr_is_unreachable(cond_val)) { | ||
| 6178 | cond_br_inst = ir_build_cond_br(ag, scope, node->data.while_expr.condition, cond_val, | ||
| 6179 | body_block, else_block, is_comptime); | ||
| 6180 | cond_br_inst->is_gen = true; | ||
| 6181 | } else { | ||
| 6182 | // for the purposes of the source instruction to ir_build_result_peers | ||
| 6183 | cond_br_inst = ag->current_basic_block->instruction_list.last(); | ||
| 6184 | } | ||
| 6185 | |||
| 6186 | ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, result_loc, | ||
| 6187 | is_comptime); | ||
| 6188 | ir_set_cursor_at_end_and_append_block(ag, body_block); | ||
| 6189 | |||
| 6190 | ZigList<IrInstSrc *> incoming_values = {0}; | ||
| 6191 | ZigList<Stage1ZirBasicBlock *> incoming_blocks = {0}; | ||
| 6192 | |||
| 6193 | Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime); | ||
| 6194 | |||
| 6195 | if (is_duplicate_label(ag->codegen, subexpr_scope, node, node->data.while_expr.name)) | ||
| 6196 | return ag->codegen->invalid_inst_src; | ||
| 6197 | |||
| 6198 | ScopeLoop *loop_scope = create_loop_scope(ag->codegen, node, subexpr_scope); | ||
| 6199 | loop_scope->break_block = end_block; | ||
| 6200 | loop_scope->continue_block = continue_block; | ||
| 6201 | loop_scope->is_comptime = is_comptime; | ||
| 6202 | loop_scope->incoming_blocks = &incoming_blocks; | ||
| 6203 | loop_scope->incoming_values = &incoming_values; | ||
| 6204 | loop_scope->lval = lval; | ||
| 6205 | loop_scope->peer_parent = peer_parent; | ||
| 6206 | |||
| 6207 | // Note the body block of the loop is not the place that lval and result_loc are used - | ||
| 6208 | // it's actually in break statements, handled similarly to return statements. | ||
| 6209 | // That is why we set those values in loop_scope above and not in this astgen_node call. | ||
| 6210 | IrInstSrc *body_result = astgen_node(ag, node->data.while_expr.body, &loop_scope->base); | ||
| 6211 | if (body_result == ag->codegen->invalid_inst_src) | ||
| 6212 | return body_result; | ||
| 6213 | |||
| 6214 | if (loop_scope->name != nullptr && loop_scope->name_used == false) { | ||
| 6215 | add_node_error(ag->codegen, node, buf_sprintf("unused while label")); | ||
| 6216 | } | ||
| 6217 | |||
| 6218 | if (!instr_is_unreachable(body_result)) { | ||
| 6219 | ir_mark_gen(ir_build_check_statement_is_void(ag, scope, node->data.while_expr.body, body_result)); | ||
| 6220 | ir_mark_gen(ir_build_br(ag, scope, node, continue_block, is_comptime)); | ||
| 6221 | } | ||
| 6222 | |||
| 6223 | if (continue_expr_node) { | ||
| 6224 | ir_set_cursor_at_end_and_append_block(ag, continue_block); | ||
| 6225 | IrInstSrc *expr_result = astgen_node(ag, continue_expr_node, subexpr_scope); | ||
| 6226 | if (expr_result == ag->codegen->invalid_inst_src) | ||
| 6227 | return expr_result; | ||
| 6228 | if (!instr_is_unreachable(expr_result)) { | ||
| 6229 | ir_mark_gen(ir_build_check_statement_is_void(ag, scope, continue_expr_node, expr_result)); | ||
| 6230 | ir_mark_gen(ir_build_br(ag, scope, node, cond_block, is_comptime)); | ||
| 6231 | } | ||
| 6232 | } | ||
| 6233 | |||
| 6234 | IrInstSrc *else_result = nullptr; | ||
| 6235 | if (else_node) { | ||
| 6236 | ir_set_cursor_at_end_and_append_block(ag, else_block); | ||
| 6237 | |||
| 6238 | if (peer_parent->peers.length != 0) { | ||
| 6239 | peer_parent->peers.last()->next_bb = else_block; | ||
| 6240 | } | ||
| 6241 | ResultLocPeer *peer_result = create_peer_result(peer_parent); | ||
| 6242 | peer_parent->peers.append(peer_result); | ||
| 6243 | |||
| 6244 | else_result = astgen_node_extra(ag, else_node, subexpr_scope, lval, &peer_result->base); | ||
| 6245 | if (else_result == ag->codegen->invalid_inst_src) | ||
| 6246 | return else_result; | ||
| 6247 | if (!instr_is_unreachable(else_result)) | ||
| 6248 | ir_mark_gen(ir_build_br(ag, scope, node, end_block, is_comptime)); | ||
| 6249 | } | ||
| 6250 | Stage1ZirBasicBlock *after_else_block = ag->current_basic_block; | ||
| 6251 | ir_set_cursor_at_end_and_append_block(ag, end_block); | ||
| 6252 | if (else_result) { | ||
| 6253 | incoming_blocks.append(after_else_block); | ||
| 6254 | incoming_values.append(else_result); | ||
| 6255 | } else { | ||
| 6256 | incoming_blocks.append(after_cond_block); | ||
| 6257 | incoming_values.append(void_else_result); | ||
| 6258 | } | ||
| 6259 | if (peer_parent->peers.length != 0) { | ||
| 6260 | peer_parent->peers.last()->next_bb = end_block; | ||
| 6261 | } | ||
| 6262 | |||
| 6263 | IrInstSrc *phi = ir_build_phi(ag, scope, node, incoming_blocks.length, | ||
| 6264 | incoming_blocks.items, incoming_values.items, peer_parent); | ||
| 6265 | return ir_expr_wrap(ag, scope, phi, result_loc); | ||
| 6266 | } | ||
| 6267 | } | ||
| 6268 | |||
| 6269 | static IrInstSrc *astgen_for_expr(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval, | ||
| 6270 | ResultLoc *result_loc) | ||
| 6271 | { | ||
| 6272 | assert(node->type == NodeTypeForExpr); | ||
| 6273 | |||
| 6274 | AstNode *array_node = node->data.for_expr.array_expr; | ||
| 6275 | AstNode *elem_node = node->data.for_expr.elem_node; | ||
| 6276 | AstNode *index_node = node->data.for_expr.index_node; | ||
| 6277 | AstNode *body_node = node->data.for_expr.body; | ||
| 6278 | AstNode *else_node = node->data.for_expr.else_node; | ||
| 6279 | |||
| 6280 | if (!elem_node) { | ||
| 6281 | add_node_error(ag->codegen, node, buf_sprintf("for loop expression missing element parameter")); | ||
| 6282 | return ag->codegen->invalid_inst_src; | ||
| 6283 | } | ||
| 6284 | assert(elem_node->type == NodeTypeIdentifier); | ||
| 6285 | |||
| 6286 | ScopeExpr *spill_scope = create_expr_scope(ag->codegen, node, parent_scope); | ||
| 6287 | |||
| 6288 | IrInstSrc *array_val_ptr = astgen_node_extra(ag, array_node, &spill_scope->base, LValPtr, nullptr); | ||
| 6289 | if (array_val_ptr == ag->codegen->invalid_inst_src) | ||
| 6290 | return array_val_ptr; | ||
| 6291 | |||
| 6292 | IrInstSrc *is_comptime = ir_build_const_bool(ag, parent_scope, node, | ||
| 6293 | ir_should_inline(ag->exec, parent_scope) || node->data.for_expr.is_inline); | ||
| 6294 | |||
| 6295 | AstNode *index_var_source_node; | ||
| 6296 | ZigVar *index_var; | ||
| 6297 | const char *index_var_name; | ||
| 6298 | if (index_node) { | ||
| 6299 | index_var_source_node = index_node; | ||
| 6300 | Buf *index_var_name_buf = node_identifier_buf(index_node); | ||
| 6301 | index_var = ir_create_var(ag, index_node, parent_scope, index_var_name_buf, true, false, false, is_comptime); | ||
| 6302 | index_var_name = buf_ptr(index_var_name_buf); | ||
| 6303 | } else { | ||
| 6304 | index_var_source_node = node; | ||
| 6305 | index_var = ir_create_var(ag, node, parent_scope, nullptr, true, false, true, is_comptime); | ||
| 6306 | index_var_name = "i"; | ||
| 6307 | } | ||
| 6308 | |||
| 6309 | IrInstSrc *zero = ir_build_const_usize(ag, parent_scope, node, 0); | ||
| 6310 | build_decl_var_and_init(ag, parent_scope, index_var_source_node, index_var, zero, index_var_name, is_comptime); | ||
| 6311 | parent_scope = index_var->child_scope; | ||
| 6312 | |||
| 6313 | IrInstSrc *one = ir_build_const_usize(ag, parent_scope, node, 1); | ||
| 6314 | IrInstSrc *index_ptr = ir_build_var_ptr(ag, parent_scope, node, index_var); | ||
| 6315 | |||
| 6316 | |||
| 6317 | Stage1ZirBasicBlock *cond_block = ir_create_basic_block(ag, parent_scope, "ForCond"); | ||
| 6318 | Stage1ZirBasicBlock *body_block = ir_create_basic_block(ag, parent_scope, "ForBody"); | ||
| 6319 | Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, parent_scope, "ForEnd"); | ||
| 6320 | Stage1ZirBasicBlock *else_block = else_node ? ir_create_basic_block(ag, parent_scope, "ForElse") : end_block; | ||
| 6321 | Stage1ZirBasicBlock *continue_block = ir_create_basic_block(ag, parent_scope, "ForContinue"); | ||
| 6322 | |||
| 6323 | Buf *len_field_name = buf_create_from_str("len"); | ||
| 6324 | IrInstSrc *len_ref = ir_build_field_ptr(ag, parent_scope, node, array_val_ptr, len_field_name, false); | ||
| 6325 | IrInstSrc *len_val = ir_build_load_ptr(ag, &spill_scope->base, node, len_ref); | ||
| 6326 | ir_build_br(ag, parent_scope, node, cond_block, is_comptime); | ||
| 6327 | |||
| 6328 | ir_set_cursor_at_end_and_append_block(ag, cond_block); | ||
| 6329 | IrInstSrc *index_val = ir_build_load_ptr(ag, &spill_scope->base, node, index_ptr); | ||
| 6330 | IrInstSrc *cond = ir_build_bin_op(ag, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false); | ||
| 6331 | Stage1ZirBasicBlock *after_cond_block = ag->current_basic_block; | ||
| 6332 | IrInstSrc *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(ag, parent_scope, node)); | ||
| 6333 | IrInstSrc *cond_br_inst = ir_mark_gen(ir_build_cond_br(ag, parent_scope, node, cond, | ||
| 6334 | body_block, else_block, is_comptime)); | ||
| 6335 | |||
| 6336 | ResultLocPeerParent *peer_parent = ir_build_result_peers(ag, cond_br_inst, end_block, result_loc, is_comptime); | ||
| 6337 | |||
| 6338 | ir_set_cursor_at_end_and_append_block(ag, body_block); | ||
| 6339 | IrInstSrc *elem_ptr = ir_build_elem_ptr(ag, &spill_scope->base, node, array_val_ptr, index_val, | ||
| 6340 | false, PtrLenSingle, nullptr); | ||
| 6341 | // TODO make it an error to write to element variable or i variable. | ||
| 6342 | Buf *elem_var_name = node_identifier_buf(elem_node); | ||
| 6343 | ZigVar *elem_var = ir_create_var(ag, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime); | ||
| 6344 | Scope *child_scope = elem_var->child_scope; | ||
| 6345 | |||
| 6346 | IrInstSrc *elem_value = node->data.for_expr.elem_is_ptr ? | ||
| 6347 | elem_ptr : ir_build_load_ptr(ag, &spill_scope->base, elem_node, elem_ptr); | ||
| 6348 | build_decl_var_and_init(ag, parent_scope, elem_node, elem_var, elem_value, buf_ptr(elem_var_name), is_comptime); | ||
| 6349 | |||
| 6350 | if (is_duplicate_label(ag->codegen, child_scope, node, node->data.for_expr.name)) | ||
| 6351 | return ag->codegen->invalid_inst_src; | ||
| 6352 | |||
| 6353 | ZigList<IrInstSrc *> incoming_values = {0}; | ||
| 6354 | ZigList<Stage1ZirBasicBlock *> incoming_blocks = {0}; | ||
| 6355 | ScopeLoop *loop_scope = create_loop_scope(ag->codegen, node, child_scope); | ||
| 6356 | loop_scope->break_block = end_block; | ||
| 6357 | loop_scope->continue_block = continue_block; | ||
| 6358 | loop_scope->is_comptime = is_comptime; | ||
| 6359 | loop_scope->incoming_blocks = &incoming_blocks; | ||
| 6360 | loop_scope->incoming_values = &incoming_values; | ||
| 6361 | loop_scope->lval = LValNone; | ||
| 6362 | loop_scope->peer_parent = peer_parent; | ||
| 6363 | loop_scope->spill_scope = spill_scope; | ||
| 6364 | |||
| 6365 | // Note the body block of the loop is not the place that lval and result_loc are used - | ||
| 6366 | // it's actually in break statements, handled similarly to return statements. | ||
| 6367 | // That is why we set those values in loop_scope above and not in this astgen_node call. | ||
| 6368 | IrInstSrc *body_result = astgen_node(ag, body_node, &loop_scope->base); | ||
| 6369 | if (body_result == ag->codegen->invalid_inst_src) | ||
| 6370 | return ag->codegen->invalid_inst_src; | ||
| 6371 | |||
| 6372 | if (loop_scope->name != nullptr && loop_scope->name_used == false) { | ||
| 6373 | add_node_error(ag->codegen, node, buf_sprintf("unused for label")); | ||
| 6374 | } | ||
| 6375 | |||
| 6376 | if (!instr_is_unreachable(body_result)) { | ||
| 6377 | ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, node->data.for_expr.body, body_result)); | ||
| 6378 | ir_mark_gen(ir_build_br(ag, child_scope, node, continue_block, is_comptime)); | ||
| 6379 | } | ||
| 6380 | |||
| 6381 | ir_set_cursor_at_end_and_append_block(ag, continue_block); | ||
| 6382 | IrInstSrc *new_index_val = ir_build_bin_op(ag, child_scope, node, IrBinOpAdd, index_val, one, false); | ||
| 6383 | ir_build_store_ptr(ag, child_scope, node, index_ptr, new_index_val)->allow_write_through_const = true; | ||
| 6384 | ir_build_br(ag, child_scope, node, cond_block, is_comptime); | ||
| 6385 | |||
| 6386 | IrInstSrc *else_result = nullptr; | ||
| 6387 | if (else_node) { | ||
| 6388 | ir_set_cursor_at_end_and_append_block(ag, else_block); | ||
| 6389 | |||
| 6390 | if (peer_parent->peers.length != 0) { | ||
| 6391 | peer_parent->peers.last()->next_bb = else_block; | ||
| 6392 | } | ||
| 6393 | ResultLocPeer *peer_result = create_peer_result(peer_parent); | ||
| 6394 | peer_parent->peers.append(peer_result); | ||
| 6395 | else_result = astgen_node_extra(ag, else_node, parent_scope, LValNone, &peer_result->base); | ||
| 6396 | if (else_result == ag->codegen->invalid_inst_src) | ||
| 6397 | return else_result; | ||
| 6398 | if (!instr_is_unreachable(else_result)) | ||
| 6399 | ir_mark_gen(ir_build_br(ag, parent_scope, node, end_block, is_comptime)); | ||
| 6400 | } | ||
| 6401 | Stage1ZirBasicBlock *after_else_block = ag->current_basic_block; | ||
| 6402 | ir_set_cursor_at_end_and_append_block(ag, end_block); | ||
| 6403 | |||
| 6404 | if (else_result) { | ||
| 6405 | incoming_blocks.append(after_else_block); | ||
| 6406 | incoming_values.append(else_result); | ||
| 6407 | } else { | ||
| 6408 | incoming_blocks.append(after_cond_block); | ||
| 6409 | incoming_values.append(void_else_value); | ||
| 6410 | } | ||
| 6411 | if (peer_parent->peers.length != 0) { | ||
| 6412 | peer_parent->peers.last()->next_bb = end_block; | ||
| 6413 | } | ||
| 6414 | |||
| 6415 | IrInstSrc *phi = ir_build_phi(ag, parent_scope, node, incoming_blocks.length, | ||
| 6416 | incoming_blocks.items, incoming_values.items, peer_parent); | ||
| 6417 | return ir_lval_wrap(ag, parent_scope, phi, lval, result_loc); | ||
| 6418 | } | ||
| 6419 | |||
| 6420 | static IrInstSrc *astgen_bool_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 6421 | assert(node->type == NodeTypeBoolLiteral); | ||
| 6422 | return ir_build_const_bool(ag, scope, node, node->data.bool_literal.value); | ||
| 6423 | } | ||
| 6424 | |||
| 6425 | static IrInstSrc *astgen_enum_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 6426 | assert(node->type == NodeTypeEnumLiteral); | ||
| 6427 | // Currently, stage1 runs astgen for every comptime function call, | ||
| 6428 | // resulting the allocation here wasting memory. As a workaround until | ||
| 6429 | // the code is adjusted to make astgen run only once per source node, | ||
| 6430 | // we memoize the result into the AST here. | ||
| 6431 | if (node->data.enum_literal.name == nullptr) { | ||
| 6432 | RootStruct *root_struct = node->owner->data.structure.root_struct; | ||
| 6433 | node->data.enum_literal.name = token_identifier_buf(root_struct, node->main_token + 1); | ||
| 6434 | } | ||
| 6435 | return ir_build_const_enum_literal(ag, scope, node, node->data.enum_literal.name); | ||
| 6436 | } | ||
| 6437 | |||
| 6438 | static IrInstSrc *astgen_string_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 6439 | Error err; | ||
| 6440 | assert(node->type == NodeTypeStringLiteral); | ||
| 6441 | |||
| 6442 | RootStruct *root_struct = node->owner->data.structure.root_struct; | ||
| 6443 | const char *source = buf_ptr(root_struct->source_code); | ||
| 6444 | |||
| 6445 | TokenId *token_ids = root_struct->token_ids; | ||
| 6446 | |||
| 6447 | Buf *str = buf_alloc(); | ||
| 6448 | if (token_ids[node->main_token] == TokenIdStringLiteral) { | ||
| 6449 | size_t byte_offset = root_struct->token_locs[node->main_token].offset; | ||
| 6450 | size_t bad_index; | ||
| 6451 | if ((err = source_string_literal_buf(source + byte_offset, str, &bad_index))) { | ||
| 6452 | add_token_error_offset(ag->codegen, node->owner, node->main_token, | ||
| 6453 | buf_create_from_str("invalid string literal character"), bad_index); | ||
| 6454 | } | ||
| 6455 | src_assert(source[byte_offset] == '"', node); | ||
| 6456 | byte_offset += 1; | ||
| 6457 | } else if (token_ids[node->main_token] == TokenIdMultilineStringLiteralLine) { | ||
| 6458 | TokenIndex tok_index = node->main_token; | ||
| 6459 | bool first = true; | ||
| 6460 | for (;token_ids[tok_index] == TokenIdMultilineStringLiteralLine; tok_index += 1) { | ||
| 6461 | size_t byte_offset = root_struct->token_locs[tok_index].offset; | ||
| 6462 | size_t end = byte_offset; | ||
| 6463 | while (source[end] != 0 && source[end] != '\n') { | ||
| 6464 | end += 1; | ||
| 6465 | } | ||
| 6466 | if (!first) { | ||
| 6467 | buf_append_char(str, '\n'); | ||
| 6468 | } else { | ||
| 6469 | first = false; | ||
| 6470 | } | ||
| 6471 | buf_append_mem(str, source + byte_offset + 2, end - byte_offset - 2); | ||
| 6472 | } | ||
| 6473 | } else { | ||
| 6474 | zig_unreachable(); | ||
| 6475 | } | ||
| 6476 | |||
| 6477 | return ir_build_const_str_lit(ag, scope, node, str); | ||
| 6478 | } | ||
| 6479 | |||
| 6480 | static IrInstSrc *astgen_array_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 6481 | assert(node->type == NodeTypeArrayType); | ||
| 6482 | |||
| 6483 | AstNode *size_node = node->data.array_type.size; | ||
| 6484 | AstNode *child_type_node = node->data.array_type.child_type; | ||
| 6485 | bool is_const = node->data.array_type.is_const; | ||
| 6486 | bool is_volatile = node->data.array_type.is_volatile; | ||
| 6487 | bool is_allow_zero = node->data.array_type.allow_zero_token != 0; | ||
| 6488 | AstNode *sentinel_expr = node->data.array_type.sentinel; | ||
| 6489 | AstNode *align_expr = node->data.array_type.align_expr; | ||
| 6490 | |||
| 6491 | Scope *comptime_scope = create_comptime_scope(ag->codegen, node, scope); | ||
| 6492 | |||
| 6493 | IrInstSrc *sentinel; | ||
| 6494 | if (sentinel_expr != nullptr) { | ||
| 6495 | sentinel = astgen_node(ag, sentinel_expr, comptime_scope); | ||
| 6496 | if (sentinel == ag->codegen->invalid_inst_src) | ||
| 6497 | return sentinel; | ||
| 6498 | } else { | ||
| 6499 | sentinel = nullptr; | ||
| 6500 | } | ||
| 6501 | |||
| 6502 | if (size_node) { | ||
| 6503 | if (is_const) { | ||
| 6504 | add_node_error(ag->codegen, node, buf_create_from_str("const qualifier invalid on array type")); | ||
| 6505 | return ag->codegen->invalid_inst_src; | ||
| 6506 | } | ||
| 6507 | if (is_volatile) { | ||
| 6508 | add_node_error(ag->codegen, node, buf_create_from_str("volatile qualifier invalid on array type")); | ||
| 6509 | return ag->codegen->invalid_inst_src; | ||
| 6510 | } | ||
| 6511 | if (is_allow_zero) { | ||
| 6512 | add_node_error(ag->codegen, node, buf_create_from_str("allowzero qualifier invalid on array type")); | ||
| 6513 | return ag->codegen->invalid_inst_src; | ||
| 6514 | } | ||
| 6515 | if (align_expr != nullptr) { | ||
| 6516 | add_node_error(ag->codegen, node, buf_create_from_str("align qualifier invalid on array type")); | ||
| 6517 | return ag->codegen->invalid_inst_src; | ||
| 6518 | } | ||
| 6519 | |||
| 6520 | IrInstSrc *size_value = astgen_node(ag, size_node, comptime_scope); | ||
| 6521 | if (size_value == ag->codegen->invalid_inst_src) | ||
| 6522 | return size_value; | ||
| 6523 | |||
| 6524 | IrInstSrc *child_type = astgen_node(ag, child_type_node, comptime_scope); | ||
| 6525 | if (child_type == ag->codegen->invalid_inst_src) | ||
| 6526 | return child_type; | ||
| 6527 | |||
| 6528 | return ir_build_array_type(ag, scope, node, size_value, sentinel, child_type); | ||
| 6529 | } else { | ||
| 6530 | IrInstSrc *align_value; | ||
| 6531 | if (align_expr != nullptr) { | ||
| 6532 | align_value = astgen_node(ag, align_expr, comptime_scope); | ||
| 6533 | if (align_value == ag->codegen->invalid_inst_src) | ||
| 6534 | return align_value; | ||
| 6535 | } else { | ||
| 6536 | align_value = nullptr; | ||
| 6537 | } | ||
| 6538 | |||
| 6539 | IrInstSrc *child_type = astgen_node(ag, child_type_node, comptime_scope); | ||
| 6540 | if (child_type == ag->codegen->invalid_inst_src) | ||
| 6541 | return child_type; | ||
| 6542 | |||
| 6543 | return ir_build_slice_type(ag, scope, node, child_type, is_const, is_volatile, sentinel, | ||
| 6544 | align_value, is_allow_zero); | ||
| 6545 | } | ||
| 6546 | } | ||
| 6547 | |||
| 6548 | static IrInstSrc *astgen_anyframe_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 6549 | assert(node->type == NodeTypeAnyFrameType); | ||
| 6550 | |||
| 6551 | AstNode *payload_type_node = node->data.anyframe_type.payload_type; | ||
| 6552 | IrInstSrc *payload_type_value = nullptr; | ||
| 6553 | |||
| 6554 | if (payload_type_node != nullptr) { | ||
| 6555 | payload_type_value = astgen_node(ag, payload_type_node, scope); | ||
| 6556 | if (payload_type_value == ag->codegen->invalid_inst_src) | ||
| 6557 | return payload_type_value; | ||
| 6558 | |||
| 6559 | } | ||
| 6560 | |||
| 6561 | return ir_build_anyframe_type(ag, scope, node, payload_type_value); | ||
| 6562 | } | ||
| 6563 | |||
| 6564 | static IrInstSrc *astgen_undefined_literal(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 6565 | assert(node->type == NodeTypeUndefinedLiteral); | ||
| 6566 | return ir_build_const_undefined(ag, scope, node); | ||
| 6567 | } | ||
| 6568 | |||
| 6569 | static IrInstSrc *astgen_asm_expr(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 6570 | assert(node->type == NodeTypeAsmExpr); | ||
| 6571 | AstNodeAsmExpr *asm_expr = &node->data.asm_expr; | ||
| 6572 | |||
| 6573 | IrInstSrc *asm_template = astgen_node(ag, asm_expr->asm_template, scope); | ||
| 6574 | if (asm_template == ag->codegen->invalid_inst_src) | ||
| 6575 | return ag->codegen->invalid_inst_src; | ||
| 6576 | |||
| 6577 | bool is_volatile = asm_expr->volatile_token != 0; | ||
| 6578 | bool in_fn_scope = (scope_fn_entry(scope) != nullptr); | ||
| 6579 | |||
| 6580 | if (!in_fn_scope) { | ||
| 6581 | if (is_volatile) { | ||
| 6582 | add_token_error(ag->codegen, node->owner, asm_expr->volatile_token, | ||
| 6583 | buf_sprintf("volatile is meaningless on global assembly")); | ||
| 6584 | return ag->codegen->invalid_inst_src; | ||
| 6585 | } | ||
| 6586 | |||
| 6587 | if (asm_expr->output_list.length != 0 || asm_expr->input_list.length != 0 || | ||
| 6588 | asm_expr->clobber_list.length != 0) | ||
| 6589 | { | ||
| 6590 | add_node_error(ag->codegen, node, | ||
| 6591 | buf_sprintf("global assembly cannot have inputs, outputs, or clobbers")); | ||
| 6592 | return ag->codegen->invalid_inst_src; | ||
| 6593 | } | ||
| 6594 | |||
| 6595 | return ir_build_asm_src(ag, scope, node, asm_template, nullptr, nullptr, | ||
| 6596 | nullptr, 0, is_volatile, true); | ||
| 6597 | } | ||
| 6598 | |||
| 6599 | IrInstSrc **input_list = heap::c_allocator.allocate<IrInstSrc *>(asm_expr->input_list.length); | ||
| 6600 | IrInstSrc **output_types = heap::c_allocator.allocate<IrInstSrc *>(asm_expr->output_list.length); | ||
| 6601 | ZigVar **output_vars = heap::c_allocator.allocate<ZigVar *>(asm_expr->output_list.length); | ||
| 6602 | size_t return_count = 0; | ||
| 6603 | if (!is_volatile && asm_expr->output_list.length == 0) { | ||
| 6604 | add_node_error(ag->codegen, node, | ||
| 6605 | buf_sprintf("assembly expression with no output must be marked volatile")); | ||
| 6606 | return ag->codegen->invalid_inst_src; | ||
| 6607 | } | ||
| 6608 | for (size_t i = 0; i < asm_expr->output_list.length; i += 1) { | ||
| 6609 | AsmOutput *asm_output = asm_expr->output_list.at(i); | ||
| 6610 | if (asm_output->return_type) { | ||
| 6611 | return_count += 1; | ||
| 6612 | |||
| 6613 | IrInstSrc *return_type = astgen_node(ag, asm_output->return_type, scope); | ||
| 6614 | if (return_type == ag->codegen->invalid_inst_src) | ||
| 6615 | return ag->codegen->invalid_inst_src; | ||
| 6616 | if (return_count > 1) { | ||
| 6617 | add_node_error(ag->codegen, node, | ||
| 6618 | buf_sprintf("inline assembly allows up to one output value")); | ||
| 6619 | return ag->codegen->invalid_inst_src; | ||
| 6620 | } | ||
| 6621 | output_types[i] = return_type; | ||
| 6622 | } else { | ||
| 6623 | Buf *variable_name = asm_output->variable_name; | ||
| 6624 | // TODO there is some duplication here with astgen_identifier. I need to do a full audit of how | ||
| 6625 | // inline assembly works. https://github.com/ziglang/zig/issues/215 | ||
| 6626 | ZigVar *var = find_variable(ag->codegen, scope, variable_name, nullptr); | ||
| 6627 | if (var) { | ||
| 6628 | output_vars[i] = var; | ||
| 6629 | } else { | ||
| 6630 | add_node_error(ag->codegen, node, | ||
| 6631 | buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); | ||
| 6632 | return ag->codegen->invalid_inst_src; | ||
| 6633 | } | ||
| 6634 | } | ||
| 6635 | |||
| 6636 | const char modifier = *buf_ptr(asm_output->constraint); | ||
| 6637 | if (modifier != '=') { | ||
| 6638 | add_node_error(ag->codegen, node, | ||
| 6639 | buf_sprintf("invalid modifier starting output constraint for '%s': '%c', only '=' is supported." | ||
| 6640 | " Compiler TODO: see https://github.com/ziglang/zig/issues/215", | ||
| 6641 | buf_ptr(asm_output->asm_symbolic_name), modifier)); | ||
| 6642 | return ag->codegen->invalid_inst_src; | ||
| 6643 | } | ||
| 6644 | } | ||
| 6645 | for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { | ||
| 6646 | AsmInput *asm_input = asm_expr->input_list.at(i); | ||
| 6647 | IrInstSrc *input_value = astgen_node(ag, asm_input->expr, scope); | ||
| 6648 | if (input_value == ag->codegen->invalid_inst_src) | ||
| 6649 | return ag->codegen->invalid_inst_src; | ||
| 6650 | |||
| 6651 | input_list[i] = input_value; | ||
| 6652 | } | ||
| 6653 | |||
| 6654 | return ir_build_asm_src(ag, scope, node, asm_template, input_list, output_types, | ||
| 6655 | output_vars, return_count, is_volatile, false); | ||
| 6656 | } | ||
| 6657 | |||
| 6658 | static IrInstSrc *astgen_if_optional_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, | ||
| 6659 | ResultLoc *result_loc) | ||
| 6660 | { | ||
| 6661 | assert(node->type == NodeTypeIfOptional); | ||
| 6662 | |||
| 6663 | Buf *var_symbol = node->data.test_expr.var_symbol; | ||
| 6664 | AstNode *expr_node = node->data.test_expr.target_node; | ||
| 6665 | AstNode *then_node = node->data.test_expr.then_node; | ||
| 6666 | AstNode *else_node = node->data.test_expr.else_node; | ||
| 6667 | bool var_is_ptr = node->data.test_expr.var_is_ptr; | ||
| 6668 | |||
| 6669 | ScopeExpr *spill_scope = create_expr_scope(ag->codegen, expr_node, scope); | ||
| 6670 | spill_scope->spill_harder = true; | ||
| 6671 | |||
| 6672 | IrInstSrc *maybe_val_ptr = astgen_node_extra(ag, expr_node, &spill_scope->base, LValPtr, nullptr); | ||
| 6673 | if (maybe_val_ptr == ag->codegen->invalid_inst_src) | ||
| 6674 | return maybe_val_ptr; | ||
| 6675 | |||
| 6676 | IrInstSrc *maybe_val = ir_build_load_ptr(ag, scope, node, maybe_val_ptr); | ||
| 6677 | IrInstSrc *is_non_null = ir_build_test_non_null_src(ag, scope, node, maybe_val); | ||
| 6678 | |||
| 6679 | Stage1ZirBasicBlock *then_block = ir_create_basic_block(ag, scope, "OptionalThen"); | ||
| 6680 | Stage1ZirBasicBlock *else_block = ir_create_basic_block(ag, scope, "OptionalElse"); | ||
| 6681 | Stage1ZirBasicBlock *endif_block = ir_create_basic_block(ag, scope, "OptionalEndIf"); | ||
| 6682 | |||
| 6683 | IrInstSrc *is_comptime; | ||
| 6684 | if (ir_should_inline(ag->exec, scope)) { | ||
| 6685 | is_comptime = ir_build_const_bool(ag, scope, node, true); | ||
| 6686 | } else { | ||
| 6687 | is_comptime = ir_build_test_comptime(ag, scope, node, is_non_null); | ||
| 6688 | } | ||
| 6689 | IrInstSrc *cond_br_inst = ir_build_cond_br(ag, scope, node, is_non_null, | ||
| 6690 | then_block, else_block, is_comptime); | ||
| 6691 | |||
| 6692 | ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, else_block, endif_block, | ||
| 6693 | result_loc, is_comptime); | ||
| 6694 | |||
| 6695 | ir_set_cursor_at_end_and_append_block(ag, then_block); | ||
| 6696 | |||
| 6697 | Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, &spill_scope->base, is_comptime); | ||
| 6698 | Scope *var_scope; | ||
| 6699 | if (var_symbol) { | ||
| 6700 | bool is_shadowable = false; | ||
| 6701 | bool is_const = true; | ||
| 6702 | ZigVar *var = ir_create_var(ag, node, subexpr_scope, | ||
| 6703 | var_symbol, is_const, is_const, is_shadowable, is_comptime); | ||
| 6704 | |||
| 6705 | IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(ag, subexpr_scope, node, maybe_val_ptr, false); | ||
| 6706 | IrInstSrc *var_value = var_is_ptr ? | ||
| 6707 | payload_ptr : ir_build_load_ptr(ag, &spill_scope->base, node, payload_ptr); | ||
| 6708 | build_decl_var_and_init(ag, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), is_comptime); | ||
| 6709 | var_scope = var->child_scope; | ||
| 6710 | } else { | ||
| 6711 | var_scope = subexpr_scope; | ||
| 6712 | } | ||
| 6713 | IrInstSrc *then_expr_result = astgen_node_extra(ag, then_node, var_scope, lval, | ||
| 6714 | &peer_parent->peers.at(0)->base); | ||
| 6715 | if (then_expr_result == ag->codegen->invalid_inst_src) | ||
| 6716 | return then_expr_result; | ||
| 6717 | Stage1ZirBasicBlock *after_then_block = ag->current_basic_block; | ||
| 6718 | if (!instr_is_unreachable(then_expr_result)) | ||
| 6719 | ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); | ||
| 6720 | |||
| 6721 | ir_set_cursor_at_end_and_append_block(ag, else_block); | ||
| 6722 | IrInstSrc *else_expr_result; | ||
| 6723 | if (else_node) { | ||
| 6724 | else_expr_result = astgen_node_extra(ag, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); | ||
| 6725 | if (else_expr_result == ag->codegen->invalid_inst_src) | ||
| 6726 | return else_expr_result; | ||
| 6727 | } else { | ||
| 6728 | else_expr_result = ir_build_const_void(ag, scope, node); | ||
| 6729 | ir_build_end_expr(ag, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); | ||
| 6730 | } | ||
| 6731 | Stage1ZirBasicBlock *after_else_block = ag->current_basic_block; | ||
| 6732 | if (!instr_is_unreachable(else_expr_result)) | ||
| 6733 | ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); | ||
| 6734 | |||
| 6735 | ir_set_cursor_at_end_and_append_block(ag, endif_block); | ||
| 6736 | IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2); | ||
| 6737 | incoming_values[0] = then_expr_result; | ||
| 6738 | incoming_values[1] = else_expr_result; | ||
| 6739 | Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate<Stage1ZirBasicBlock *>(2); | ||
| 6740 | incoming_blocks[0] = after_then_block; | ||
| 6741 | incoming_blocks[1] = after_else_block; | ||
| 6742 | |||
| 6743 | IrInstSrc *phi = ir_build_phi(ag, scope, node, 2, incoming_blocks, incoming_values, peer_parent); | ||
| 6744 | return ir_expr_wrap(ag, scope, phi, result_loc); | ||
| 6745 | } | ||
| 6746 | |||
| 6747 | static IrInstSrc *astgen_if_err_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, | ||
| 6748 | ResultLoc *result_loc) | ||
| 6749 | { | ||
| 6750 | assert(node->type == NodeTypeIfErrorExpr); | ||
| 6751 | |||
| 6752 | AstNode *target_node = node->data.if_err_expr.target_node; | ||
| 6753 | AstNode *then_node = node->data.if_err_expr.then_node; | ||
| 6754 | AstNode *else_node = node->data.if_err_expr.else_node; | ||
| 6755 | bool var_is_ptr = node->data.if_err_expr.var_is_ptr; | ||
| 6756 | bool var_is_const = true; | ||
| 6757 | Buf *var_symbol = node->data.if_err_expr.var_symbol; | ||
| 6758 | Buf *err_symbol = node->data.if_err_expr.err_symbol; | ||
| 6759 | |||
| 6760 | IrInstSrc *err_val_ptr = astgen_node_extra(ag, target_node, scope, LValPtr, nullptr); | ||
| 6761 | if (err_val_ptr == ag->codegen->invalid_inst_src) | ||
| 6762 | return err_val_ptr; | ||
| 6763 | |||
| 6764 | IrInstSrc *err_val = ir_build_load_ptr(ag, scope, node, err_val_ptr); | ||
| 6765 | IrInstSrc *is_err = ir_build_test_err_src(ag, scope, node, err_val_ptr, true, false); | ||
| 6766 | |||
| 6767 | Stage1ZirBasicBlock *ok_block = ir_create_basic_block(ag, scope, "TryOk"); | ||
| 6768 | Stage1ZirBasicBlock *else_block = ir_create_basic_block(ag, scope, "TryElse"); | ||
| 6769 | Stage1ZirBasicBlock *endif_block = ir_create_basic_block(ag, scope, "TryEnd"); | ||
| 6770 | |||
| 6771 | bool force_comptime = ir_should_inline(ag->exec, scope); | ||
| 6772 | IrInstSrc *is_comptime = force_comptime ? ir_build_const_bool(ag, scope, node, true) : ir_build_test_comptime(ag, scope, node, is_err); | ||
| 6773 | IrInstSrc *cond_br_inst = ir_build_cond_br(ag, scope, node, is_err, else_block, ok_block, is_comptime); | ||
| 6774 | |||
| 6775 | ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, else_block, endif_block, | ||
| 6776 | result_loc, is_comptime); | ||
| 6777 | |||
| 6778 | ir_set_cursor_at_end_and_append_block(ag, ok_block); | ||
| 6779 | |||
| 6780 | Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime); | ||
| 6781 | Scope *var_scope; | ||
| 6782 | if (var_symbol) { | ||
| 6783 | bool is_shadowable = false; | ||
| 6784 | IrInstSrc *var_is_comptime = force_comptime ? ir_build_const_bool(ag, subexpr_scope, node, true) : ir_build_test_comptime(ag, subexpr_scope, node, err_val); | ||
| 6785 | ZigVar *var = ir_create_var(ag, node, subexpr_scope, | ||
| 6786 | var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime); | ||
| 6787 | |||
| 6788 | IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(ag, subexpr_scope, node, err_val_ptr, false, false); | ||
| 6789 | IrInstSrc *var_value = var_is_ptr ? | ||
| 6790 | payload_ptr : ir_build_load_ptr(ag, subexpr_scope, node, payload_ptr); | ||
| 6791 | build_decl_var_and_init(ag, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), var_is_comptime); | ||
| 6792 | var_scope = var->child_scope; | ||
| 6793 | } else { | ||
| 6794 | var_scope = subexpr_scope; | ||
| 6795 | } | ||
| 6796 | IrInstSrc *then_expr_result = astgen_node_extra(ag, then_node, var_scope, lval, | ||
| 6797 | &peer_parent->peers.at(0)->base); | ||
| 6798 | if (then_expr_result == ag->codegen->invalid_inst_src) | ||
| 6799 | return then_expr_result; | ||
| 6800 | Stage1ZirBasicBlock *after_then_block = ag->current_basic_block; | ||
| 6801 | if (!instr_is_unreachable(then_expr_result)) | ||
| 6802 | ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); | ||
| 6803 | |||
| 6804 | ir_set_cursor_at_end_and_append_block(ag, else_block); | ||
| 6805 | |||
| 6806 | IrInstSrc *else_expr_result; | ||
| 6807 | if (else_node) { | ||
| 6808 | Scope *err_var_scope; | ||
| 6809 | if (err_symbol) { | ||
| 6810 | bool is_shadowable = false; | ||
| 6811 | bool is_const = true; | ||
| 6812 | ZigVar *var = ir_create_var(ag, node, subexpr_scope, | ||
| 6813 | err_symbol, is_const, is_const, is_shadowable, is_comptime); | ||
| 6814 | |||
| 6815 | IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(ag, subexpr_scope, node, err_val_ptr); | ||
| 6816 | IrInstSrc *err_value = ir_build_load_ptr(ag, subexpr_scope, node, err_ptr); | ||
| 6817 | build_decl_var_and_init(ag, subexpr_scope, node, var, err_value, buf_ptr(err_symbol), is_comptime); | ||
| 6818 | err_var_scope = var->child_scope; | ||
| 6819 | } else { | ||
| 6820 | err_var_scope = subexpr_scope; | ||
| 6821 | } | ||
| 6822 | else_expr_result = astgen_node_extra(ag, else_node, err_var_scope, lval, &peer_parent->peers.at(1)->base); | ||
| 6823 | if (else_expr_result == ag->codegen->invalid_inst_src) | ||
| 6824 | return else_expr_result; | ||
| 6825 | } else { | ||
| 6826 | else_expr_result = ir_build_const_void(ag, scope, node); | ||
| 6827 | ir_build_end_expr(ag, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); | ||
| 6828 | } | ||
| 6829 | Stage1ZirBasicBlock *after_else_block = ag->current_basic_block; | ||
| 6830 | if (!instr_is_unreachable(else_expr_result)) | ||
| 6831 | ir_mark_gen(ir_build_br(ag, scope, node, endif_block, is_comptime)); | ||
| 6832 | |||
| 6833 | ir_set_cursor_at_end_and_append_block(ag, endif_block); | ||
| 6834 | IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2); | ||
| 6835 | incoming_values[0] = then_expr_result; | ||
| 6836 | incoming_values[1] = else_expr_result; | ||
| 6837 | Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate<Stage1ZirBasicBlock *>(2); | ||
| 6838 | incoming_blocks[0] = after_then_block; | ||
| 6839 | incoming_blocks[1] = after_else_block; | ||
| 6840 | |||
| 6841 | IrInstSrc *phi = ir_build_phi(ag, scope, node, 2, incoming_blocks, incoming_values, peer_parent); | ||
| 6842 | return ir_expr_wrap(ag, scope, phi, result_loc); | ||
| 6843 | } | ||
| 6844 | |||
| 6845 | static bool astgen_switch_prong_expr(Stage1AstGen *ag, Scope *scope, AstNode *switch_node, AstNode *prong_node, | ||
| 6846 | Stage1ZirBasicBlock *end_block, IrInstSrc *is_comptime, IrInstSrc *var_is_comptime, | ||
| 6847 | IrInstSrc *target_value_ptr, IrInstSrc **prong_values, size_t prong_values_len, | ||
| 6848 | ZigList<Stage1ZirBasicBlock *> *incoming_blocks, ZigList<IrInstSrc *> *incoming_values, | ||
| 6849 | IrInstSrcSwitchElseVar **out_switch_else_var, LVal lval, ResultLoc *result_loc) | ||
| 6850 | { | ||
| 6851 | assert(switch_node->type == NodeTypeSwitchExpr); | ||
| 6852 | assert(prong_node->type == NodeTypeSwitchProng); | ||
| 6853 | |||
| 6854 | AstNode *expr_node = prong_node->data.switch_prong.expr; | ||
| 6855 | AstNode *var_symbol_node = prong_node->data.switch_prong.var_symbol; | ||
| 6856 | Scope *child_scope; | ||
| 6857 | if (var_symbol_node) { | ||
| 6858 | assert(var_symbol_node->type == NodeTypeIdentifier); | ||
| 6859 | Buf *var_name = node_identifier_buf(var_symbol_node); | ||
| 6860 | bool var_is_ptr = prong_node->data.switch_prong.var_is_ptr; | ||
| 6861 | |||
| 6862 | bool is_shadowable = false; | ||
| 6863 | bool is_const = true; | ||
| 6864 | ZigVar *var = ir_create_var(ag, var_symbol_node, scope, | ||
| 6865 | var_name, is_const, is_const, is_shadowable, var_is_comptime); | ||
| 6866 | child_scope = var->child_scope; | ||
| 6867 | IrInstSrc *var_value; | ||
| 6868 | if (out_switch_else_var != nullptr) { | ||
| 6869 | IrInstSrcSwitchElseVar *switch_else_var = ir_build_switch_else_var(ag, scope, var_symbol_node, | ||
| 6870 | target_value_ptr); | ||
| 6871 | *out_switch_else_var = switch_else_var; | ||
| 6872 | IrInstSrc *payload_ptr = &switch_else_var->base; | ||
| 6873 | var_value = var_is_ptr ? | ||
| 6874 | payload_ptr : ir_build_load_ptr(ag, scope, var_symbol_node, payload_ptr); | ||
| 6875 | } else if (prong_values != nullptr) { | ||
| 6876 | IrInstSrc *payload_ptr = ir_build_switch_var(ag, scope, var_symbol_node, target_value_ptr, | ||
| 6877 | prong_values, prong_values_len); | ||
| 6878 | var_value = var_is_ptr ? | ||
| 6879 | payload_ptr : ir_build_load_ptr(ag, scope, var_symbol_node, payload_ptr); | ||
| 6880 | } else { | ||
| 6881 | var_value = var_is_ptr ? | ||
| 6882 | target_value_ptr : ir_build_load_ptr(ag, scope, var_symbol_node, target_value_ptr); | ||
| 6883 | } | ||
| 6884 | build_decl_var_and_init(ag, scope, var_symbol_node, var, var_value, buf_ptr(var_name), var_is_comptime); | ||
| 6885 | } else { | ||
| 6886 | child_scope = scope; | ||
| 6887 | } | ||
| 6888 | |||
| 6889 | IrInstSrc *expr_result = astgen_node_extra(ag, expr_node, child_scope, lval, result_loc); | ||
| 6890 | if (expr_result == ag->codegen->invalid_inst_src) | ||
| 6891 | return false; | ||
| 6892 | if (!instr_is_unreachable(expr_result)) | ||
| 6893 | ir_mark_gen(ir_build_br(ag, scope, switch_node, end_block, is_comptime)); | ||
| 6894 | incoming_blocks->append(ag->current_basic_block); | ||
| 6895 | incoming_values->append(expr_result); | ||
| 6896 | return true; | ||
| 6897 | } | ||
| 6898 | |||
| 6899 | static IrInstSrc *astgen_switch_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, | ||
| 6900 | ResultLoc *result_loc) | ||
| 6901 | { | ||
| 6902 | assert(node->type == NodeTypeSwitchExpr); | ||
| 6903 | |||
| 6904 | AstNode *target_node = node->data.switch_expr.expr; | ||
| 6905 | IrInstSrc *target_value_ptr = astgen_node_extra(ag, target_node, scope, LValPtr, nullptr); | ||
| 6906 | if (target_value_ptr == ag->codegen->invalid_inst_src) | ||
| 6907 | return target_value_ptr; | ||
| 6908 | IrInstSrc *target_value = ir_build_switch_target(ag, scope, node, target_value_ptr); | ||
| 6909 | |||
| 6910 | Stage1ZirBasicBlock *else_block = ir_create_basic_block(ag, scope, "SwitchElse"); | ||
| 6911 | Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, scope, "SwitchEnd"); | ||
| 6912 | |||
| 6913 | size_t prong_count = node->data.switch_expr.prongs.length; | ||
| 6914 | ZigList<IrInstSrcSwitchBrCase> cases = {0}; | ||
| 6915 | |||
| 6916 | IrInstSrc *is_comptime; | ||
| 6917 | IrInstSrc *var_is_comptime; | ||
| 6918 | if (ir_should_inline(ag->exec, scope)) { | ||
| 6919 | is_comptime = ir_build_const_bool(ag, scope, node, true); | ||
| 6920 | var_is_comptime = is_comptime; | ||
| 6921 | } else { | ||
| 6922 | is_comptime = ir_build_test_comptime(ag, scope, node, target_value); | ||
| 6923 | var_is_comptime = ir_build_test_comptime(ag, scope, node, target_value_ptr); | ||
| 6924 | } | ||
| 6925 | |||
| 6926 | ZigList<IrInstSrc *> incoming_values = {0}; | ||
| 6927 | ZigList<Stage1ZirBasicBlock *> incoming_blocks = {0}; | ||
| 6928 | ZigList<IrInstSrcCheckSwitchProngsRange> check_ranges = {0}; | ||
| 6929 | |||
| 6930 | IrInstSrcSwitchElseVar *switch_else_var = nullptr; | ||
| 6931 | |||
| 6932 | ResultLocPeerParent *peer_parent = heap::c_allocator.create<ResultLocPeerParent>(); | ||
| 6933 | peer_parent->base.id = ResultLocIdPeerParent; | ||
| 6934 | peer_parent->base.allow_write_through_const = result_loc->allow_write_through_const; | ||
| 6935 | peer_parent->end_bb = end_block; | ||
| 6936 | peer_parent->is_comptime = is_comptime; | ||
| 6937 | peer_parent->parent = result_loc; | ||
| 6938 | |||
| 6939 | ir_build_reset_result(ag, scope, node, &peer_parent->base); | ||
| 6940 | |||
| 6941 | // First do the else and the ranges | ||
| 6942 | Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, scope, is_comptime); | ||
| 6943 | Scope *comptime_scope = create_comptime_scope(ag->codegen, node, scope); | ||
| 6944 | AstNode *else_prong = nullptr; | ||
| 6945 | AstNode *underscore_prong = nullptr; | ||
| 6946 | for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { | ||
| 6947 | AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); | ||
| 6948 | size_t prong_item_count = prong_node->data.switch_prong.items.length; | ||
| 6949 | if (prong_node->data.switch_prong.any_items_are_range) { | ||
| 6950 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); | ||
| 6951 | |||
| 6952 | IrInstSrc *ok_bit = nullptr; | ||
| 6953 | AstNode *last_item_node = nullptr; | ||
| 6954 | for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { | ||
| 6955 | AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); | ||
| 6956 | last_item_node = item_node; | ||
| 6957 | if (item_node->type == NodeTypeSwitchRange) { | ||
| 6958 | AstNode *start_node = item_node->data.switch_range.start; | ||
| 6959 | AstNode *end_node = item_node->data.switch_range.end; | ||
| 6960 | |||
| 6961 | IrInstSrc *start_value = astgen_node(ag, start_node, comptime_scope); | ||
| 6962 | if (start_value == ag->codegen->invalid_inst_src) | ||
| 6963 | return ag->codegen->invalid_inst_src; | ||
| 6964 | |||
| 6965 | IrInstSrc *end_value = astgen_node(ag, end_node, comptime_scope); | ||
| 6966 | if (end_value == ag->codegen->invalid_inst_src) | ||
| 6967 | return ag->codegen->invalid_inst_src; | ||
| 6968 | |||
| 6969 | IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); | ||
| 6970 | check_range->start = start_value; | ||
| 6971 | check_range->end = end_value; | ||
| 6972 | |||
| 6973 | IrInstSrc *lower_range_ok = ir_build_bin_op(ag, scope, item_node, IrBinOpCmpGreaterOrEq, | ||
| 6974 | target_value, start_value, false); | ||
| 6975 | IrInstSrc *upper_range_ok = ir_build_bin_op(ag, scope, item_node, IrBinOpCmpLessOrEq, | ||
| 6976 | target_value, end_value, false); | ||
| 6977 | IrInstSrc *both_ok = ir_build_bin_op(ag, scope, item_node, IrBinOpBoolAnd, | ||
| 6978 | lower_range_ok, upper_range_ok, false); | ||
| 6979 | if (ok_bit) { | ||
| 6980 | ok_bit = ir_build_bin_op(ag, scope, item_node, IrBinOpBoolOr, both_ok, ok_bit, false); | ||
| 6981 | } else { | ||
| 6982 | ok_bit = both_ok; | ||
| 6983 | } | ||
| 6984 | } else { | ||
| 6985 | IrInstSrc *item_value = astgen_node(ag, item_node, comptime_scope); | ||
| 6986 | if (item_value == ag->codegen->invalid_inst_src) | ||
| 6987 | return ag->codegen->invalid_inst_src; | ||
| 6988 | |||
| 6989 | IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); | ||
| 6990 | check_range->start = item_value; | ||
| 6991 | check_range->end = item_value; | ||
| 6992 | |||
| 6993 | IrInstSrc *cmp_ok = ir_build_bin_op(ag, scope, item_node, IrBinOpCmpEq, | ||
| 6994 | item_value, target_value, false); | ||
| 6995 | if (ok_bit) { | ||
| 6996 | ok_bit = ir_build_bin_op(ag, scope, item_node, IrBinOpBoolOr, cmp_ok, ok_bit, false); | ||
| 6997 | } else { | ||
| 6998 | ok_bit = cmp_ok; | ||
| 6999 | } | ||
| 7000 | } | ||
| 7001 | } | ||
| 7002 | |||
| 7003 | Stage1ZirBasicBlock *range_block_yes = ir_create_basic_block(ag, scope, "SwitchRangeYes"); | ||
| 7004 | Stage1ZirBasicBlock *range_block_no = ir_create_basic_block(ag, scope, "SwitchRangeNo"); | ||
| 7005 | |||
| 7006 | assert(ok_bit); | ||
| 7007 | assert(last_item_node); | ||
| 7008 | IrInstSrc *br_inst = ir_mark_gen(ir_build_cond_br(ag, scope, last_item_node, ok_bit, | ||
| 7009 | range_block_yes, range_block_no, is_comptime)); | ||
| 7010 | if (peer_parent->base.source_instruction == nullptr) { | ||
| 7011 | peer_parent->base.source_instruction = br_inst; | ||
| 7012 | } | ||
| 7013 | |||
| 7014 | if (peer_parent->peers.length > 0) { | ||
| 7015 | peer_parent->peers.last()->next_bb = range_block_yes; | ||
| 7016 | } | ||
| 7017 | peer_parent->peers.append(this_peer_result_loc); | ||
| 7018 | ir_set_cursor_at_end_and_append_block(ag, range_block_yes); | ||
| 7019 | if (!astgen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block, | ||
| 7020 | is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, | ||
| 7021 | &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base)) | ||
| 7022 | { | ||
| 7023 | return ag->codegen->invalid_inst_src; | ||
| 7024 | } | ||
| 7025 | |||
| 7026 | ir_set_cursor_at_end_and_append_block(ag, range_block_no); | ||
| 7027 | } else { | ||
| 7028 | if (prong_item_count == 0) { | ||
| 7029 | if (else_prong) { | ||
| 7030 | ErrorMsg *msg = add_node_error(ag->codegen, prong_node, | ||
| 7031 | buf_sprintf("multiple else prongs in switch expression")); | ||
| 7032 | add_error_note(ag->codegen, msg, else_prong, | ||
| 7033 | buf_sprintf("previous else prong is here")); | ||
| 7034 | return ag->codegen->invalid_inst_src; | ||
| 7035 | } | ||
| 7036 | else_prong = prong_node; | ||
| 7037 | } else if (prong_item_count == 1 && | ||
| 7038 | prong_node->data.switch_prong.items.at(0)->type == NodeTypeIdentifier && | ||
| 7039 | buf_eql_str(node_identifier_buf(prong_node->data.switch_prong.items.at(0)), "_")) { | ||
| 7040 | if (underscore_prong) { | ||
| 7041 | ErrorMsg *msg = add_node_error(ag->codegen, prong_node, | ||
| 7042 | buf_sprintf("multiple '_' prongs in switch expression")); | ||
| 7043 | add_error_note(ag->codegen, msg, underscore_prong, | ||
| 7044 | buf_sprintf("previous '_' prong is here")); | ||
| 7045 | return ag->codegen->invalid_inst_src; | ||
| 7046 | } | ||
| 7047 | underscore_prong = prong_node; | ||
| 7048 | } else { | ||
| 7049 | continue; | ||
| 7050 | } | ||
| 7051 | if (underscore_prong && else_prong) { | ||
| 7052 | ErrorMsg *msg = add_node_error(ag->codegen, prong_node, | ||
| 7053 | buf_sprintf("else and '_' prong in switch expression")); | ||
| 7054 | if (underscore_prong == prong_node) | ||
| 7055 | add_error_note(ag->codegen, msg, else_prong, | ||
| 7056 | buf_sprintf("else prong is here")); | ||
| 7057 | else | ||
| 7058 | add_error_note(ag->codegen, msg, underscore_prong, | ||
| 7059 | buf_sprintf("'_' prong is here")); | ||
| 7060 | return ag->codegen->invalid_inst_src; | ||
| 7061 | } | ||
| 7062 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); | ||
| 7063 | |||
| 7064 | Stage1ZirBasicBlock *prev_block = ag->current_basic_block; | ||
| 7065 | if (peer_parent->peers.length > 0) { | ||
| 7066 | peer_parent->peers.last()->next_bb = else_block; | ||
| 7067 | } | ||
| 7068 | peer_parent->peers.append(this_peer_result_loc); | ||
| 7069 | ir_set_cursor_at_end_and_append_block(ag, else_block); | ||
| 7070 | if (!astgen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block, | ||
| 7071 | is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values, | ||
| 7072 | &switch_else_var, LValNone, &this_peer_result_loc->base)) | ||
| 7073 | { | ||
| 7074 | return ag->codegen->invalid_inst_src; | ||
| 7075 | } | ||
| 7076 | ir_set_cursor_at_end(ag, prev_block); | ||
| 7077 | } | ||
| 7078 | } | ||
| 7079 | |||
| 7080 | // next do the non-else non-ranges | ||
| 7081 | for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { | ||
| 7082 | AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); | ||
| 7083 | size_t prong_item_count = prong_node->data.switch_prong.items.length; | ||
| 7084 | if (prong_item_count == 0) | ||
| 7085 | continue; | ||
| 7086 | if (prong_node->data.switch_prong.any_items_are_range) | ||
| 7087 | continue; | ||
| 7088 | if (underscore_prong == prong_node) | ||
| 7089 | continue; | ||
| 7090 | |||
| 7091 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); | ||
| 7092 | |||
| 7093 | Stage1ZirBasicBlock *prong_block = ir_create_basic_block(ag, scope, "SwitchProng"); | ||
| 7094 | IrInstSrc **items = heap::c_allocator.allocate<IrInstSrc *>(prong_item_count); | ||
| 7095 | |||
| 7096 | for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { | ||
| 7097 | AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); | ||
| 7098 | assert(item_node->type != NodeTypeSwitchRange); | ||
| 7099 | |||
| 7100 | IrInstSrc *item_value = astgen_node(ag, item_node, comptime_scope); | ||
| 7101 | if (item_value == ag->codegen->invalid_inst_src) | ||
| 7102 | return ag->codegen->invalid_inst_src; | ||
| 7103 | |||
| 7104 | IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); | ||
| 7105 | check_range->start = item_value; | ||
| 7106 | check_range->end = item_value; | ||
| 7107 | |||
| 7108 | IrInstSrcSwitchBrCase *this_case = cases.add_one(); | ||
| 7109 | this_case->value = item_value; | ||
| 7110 | this_case->block = prong_block; | ||
| 7111 | |||
| 7112 | items[item_i] = item_value; | ||
| 7113 | } | ||
| 7114 | |||
| 7115 | Stage1ZirBasicBlock *prev_block = ag->current_basic_block; | ||
| 7116 | if (peer_parent->peers.length > 0) { | ||
| 7117 | peer_parent->peers.last()->next_bb = prong_block; | ||
| 7118 | } | ||
| 7119 | peer_parent->peers.append(this_peer_result_loc); | ||
| 7120 | ir_set_cursor_at_end_and_append_block(ag, prong_block); | ||
| 7121 | if (!astgen_switch_prong_expr(ag, subexpr_scope, node, prong_node, end_block, | ||
| 7122 | is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count, | ||
| 7123 | &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base)) | ||
| 7124 | { | ||
| 7125 | return ag->codegen->invalid_inst_src; | ||
| 7126 | } | ||
| 7127 | |||
| 7128 | ir_set_cursor_at_end(ag, prev_block); | ||
| 7129 | |||
| 7130 | } | ||
| 7131 | |||
| 7132 | IrInstSrc *switch_prongs_void = ir_build_check_switch_prongs(ag, scope, node, target_value, | ||
| 7133 | check_ranges.items, check_ranges.length, else_prong, underscore_prong != nullptr); | ||
| 7134 | |||
| 7135 | IrInstSrc *br_instruction; | ||
| 7136 | if (cases.length == 0) { | ||
| 7137 | br_instruction = ir_build_br(ag, scope, node, else_block, is_comptime); | ||
| 7138 | } else { | ||
| 7139 | IrInstSrcSwitchBr *switch_br = ir_build_switch_br_src(ag, scope, node, target_value, else_block, | ||
| 7140 | cases.length, cases.items, is_comptime, switch_prongs_void); | ||
| 7141 | if (switch_else_var != nullptr) { | ||
| 7142 | switch_else_var->switch_br = switch_br; | ||
| 7143 | } | ||
| 7144 | br_instruction = &switch_br->base; | ||
| 7145 | } | ||
| 7146 | if (peer_parent->base.source_instruction == nullptr) { | ||
| 7147 | peer_parent->base.source_instruction = br_instruction; | ||
| 7148 | } | ||
| 7149 | for (size_t i = 0; i < peer_parent->peers.length; i += 1) { | ||
| 7150 | peer_parent->peers.at(i)->base.source_instruction = peer_parent->base.source_instruction; | ||
| 7151 | } | ||
| 7152 | |||
| 7153 | if (!else_prong && !underscore_prong) { | ||
| 7154 | if (peer_parent->peers.length != 0) { | ||
| 7155 | peer_parent->peers.last()->next_bb = else_block; | ||
| 7156 | } | ||
| 7157 | ir_set_cursor_at_end_and_append_block(ag, else_block); | ||
| 7158 | ir_build_unreachable(ag, scope, node); | ||
| 7159 | } else { | ||
| 7160 | if (peer_parent->peers.length != 0) { | ||
| 7161 | peer_parent->peers.last()->next_bb = end_block; | ||
| 7162 | } | ||
| 7163 | } | ||
| 7164 | |||
| 7165 | ir_set_cursor_at_end_and_append_block(ag, end_block); | ||
| 7166 | assert(incoming_blocks.length == incoming_values.length); | ||
| 7167 | IrInstSrc *result_instruction; | ||
| 7168 | if (incoming_blocks.length == 0) { | ||
| 7169 | result_instruction = ir_build_const_void(ag, scope, node); | ||
| 7170 | } else { | ||
| 7171 | result_instruction = ir_build_phi(ag, scope, node, incoming_blocks.length, | ||
| 7172 | incoming_blocks.items, incoming_values.items, peer_parent); | ||
| 7173 | } | ||
| 7174 | return ir_lval_wrap(ag, scope, result_instruction, lval, result_loc); | ||
| 7175 | } | ||
| 7176 | |||
| 7177 | static IrInstSrc *astgen_comptime(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval) { | ||
| 7178 | assert(node->type == NodeTypeCompTime); | ||
| 7179 | |||
| 7180 | Scope *child_scope = create_comptime_scope(ag->codegen, node, parent_scope); | ||
| 7181 | // purposefully pass null for result_loc and let EndExpr handle it | ||
| 7182 | return astgen_node_extra(ag, node->data.comptime_expr.expr, child_scope, lval, nullptr); | ||
| 7183 | } | ||
| 7184 | |||
| 7185 | static IrInstSrc *astgen_nosuspend(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval) { | ||
| 7186 | assert(node->type == NodeTypeNoSuspend); | ||
| 7187 | |||
| 7188 | Scope *child_scope = create_nosuspend_scope(ag->codegen, node, parent_scope); | ||
| 7189 | // purposefully pass null for result_loc and let EndExpr handle it | ||
| 7190 | return astgen_node_extra(ag, node->data.nosuspend_expr.expr, child_scope, lval, nullptr); | ||
| 7191 | } | ||
| 7192 | |||
| 7193 | static IrInstSrc *astgen_return_from_block(Stage1AstGen *ag, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) { | ||
| 7194 | IrInstSrc *is_comptime; | ||
| 7195 | if (ir_should_inline(ag->exec, break_scope)) { | ||
| 7196 | is_comptime = ir_build_const_bool(ag, break_scope, node, true); | ||
| 7197 | } else { | ||
| 7198 | is_comptime = block_scope->is_comptime; | ||
| 7199 | } | ||
| 7200 | |||
| 7201 | IrInstSrc *result_value; | ||
| 7202 | if (node->data.break_expr.expr) { | ||
| 7203 | ResultLocPeer *peer_result = create_peer_result(block_scope->peer_parent); | ||
| 7204 | block_scope->peer_parent->peers.append(peer_result); | ||
| 7205 | |||
| 7206 | result_value = astgen_node_extra(ag, node->data.break_expr.expr, break_scope, block_scope->lval, | ||
| 7207 | &peer_result->base); | ||
| 7208 | if (result_value == ag->codegen->invalid_inst_src) | ||
| 7209 | return ag->codegen->invalid_inst_src; | ||
| 7210 | } else { | ||
| 7211 | result_value = ir_build_const_void(ag, break_scope, node); | ||
| 7212 | } | ||
| 7213 | |||
| 7214 | Stage1ZirBasicBlock *dest_block = block_scope->end_block; | ||
| 7215 | if (!astgen_defers_for_block(ag, break_scope, dest_block->scope, nullptr, nullptr)) | ||
| 7216 | return ag->codegen->invalid_inst_src; | ||
| 7217 | |||
| 7218 | block_scope->incoming_blocks->append(ag->current_basic_block); | ||
| 7219 | block_scope->incoming_values->append(result_value); | ||
| 7220 | return ir_build_br(ag, break_scope, node, dest_block, is_comptime); | ||
| 7221 | } | ||
| 7222 | |||
| 7223 | static IrInstSrc *astgen_break(Stage1AstGen *ag, Scope *break_scope, AstNode *node) { | ||
| 7224 | assert(node->type == NodeTypeBreak); | ||
| 7225 | |||
| 7226 | // Search up the scope. We'll find one of these things first: | ||
| 7227 | // * function definition scope or global scope => error, break outside loop | ||
| 7228 | // * defer expression scope => error, cannot break out of defer expression | ||
| 7229 | // * loop scope => OK | ||
| 7230 | // * (if it's a labeled break) labeled block => OK | ||
| 7231 | |||
| 7232 | Scope *search_scope = break_scope; | ||
| 7233 | ScopeLoop *loop_scope; | ||
| 7234 | for (;;) { | ||
| 7235 | if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) { | ||
| 7236 | if (node->data.break_expr.name != nullptr) { | ||
| 7237 | add_node_error(ag->codegen, node, buf_sprintf("label not found: '%s'", buf_ptr(node->data.break_expr.name))); | ||
| 7238 | return ag->codegen->invalid_inst_src; | ||
| 7239 | } else { | ||
| 7240 | add_node_error(ag->codegen, node, buf_sprintf("break expression outside loop")); | ||
| 7241 | return ag->codegen->invalid_inst_src; | ||
| 7242 | } | ||
| 7243 | } else if (search_scope->id == ScopeIdDeferExpr) { | ||
| 7244 | add_node_error(ag->codegen, node, buf_sprintf("cannot break out of defer expression")); | ||
| 7245 | return ag->codegen->invalid_inst_src; | ||
| 7246 | } else if (search_scope->id == ScopeIdLoop) { | ||
| 7247 | ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope; | ||
| 7248 | if (node->data.break_expr.name == nullptr || | ||
| 7249 | (this_loop_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_loop_scope->name))) | ||
| 7250 | { | ||
| 7251 | this_loop_scope->name_used = true; | ||
| 7252 | loop_scope = this_loop_scope; | ||
| 7253 | break; | ||
| 7254 | } | ||
| 7255 | } else if (search_scope->id == ScopeIdBlock) { | ||
| 7256 | ScopeBlock *this_block_scope = (ScopeBlock *)search_scope; | ||
| 7257 | if (node->data.break_expr.name != nullptr && | ||
| 7258 | (this_block_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_block_scope->name))) | ||
| 7259 | { | ||
| 7260 | assert(this_block_scope->end_block != nullptr); | ||
| 7261 | this_block_scope->name_used = true; | ||
| 7262 | return astgen_return_from_block(ag, break_scope, node, this_block_scope); | ||
| 7263 | } | ||
| 7264 | } else if (search_scope->id == ScopeIdSuspend) { | ||
| 7265 | add_node_error(ag->codegen, node, buf_sprintf("cannot break out of suspend block")); | ||
| 7266 | return ag->codegen->invalid_inst_src; | ||
| 7267 | } | ||
| 7268 | search_scope = search_scope->parent; | ||
| 7269 | } | ||
| 7270 | |||
| 7271 | IrInstSrc *is_comptime; | ||
| 7272 | if (ir_should_inline(ag->exec, break_scope)) { | ||
| 7273 | is_comptime = ir_build_const_bool(ag, break_scope, node, true); | ||
| 7274 | } else { | ||
| 7275 | is_comptime = loop_scope->is_comptime; | ||
| 7276 | } | ||
| 7277 | |||
| 7278 | IrInstSrc *result_value; | ||
| 7279 | if (node->data.break_expr.expr) { | ||
| 7280 | ResultLocPeer *peer_result = create_peer_result(loop_scope->peer_parent); | ||
| 7281 | loop_scope->peer_parent->peers.append(peer_result); | ||
| 7282 | |||
| 7283 | result_value = astgen_node_extra(ag, node->data.break_expr.expr, break_scope, | ||
| 7284 | loop_scope->lval, &peer_result->base); | ||
| 7285 | if (result_value == ag->codegen->invalid_inst_src) | ||
| 7286 | return ag->codegen->invalid_inst_src; | ||
| 7287 | } else { | ||
| 7288 | result_value = ir_build_const_void(ag, break_scope, node); | ||
| 7289 | } | ||
| 7290 | |||
| 7291 | Stage1ZirBasicBlock *dest_block = loop_scope->break_block; | ||
| 7292 | if (!astgen_defers_for_block(ag, break_scope, dest_block->scope, nullptr, nullptr)) | ||
| 7293 | return ag->codegen->invalid_inst_src; | ||
| 7294 | |||
| 7295 | loop_scope->incoming_blocks->append(ag->current_basic_block); | ||
| 7296 | loop_scope->incoming_values->append(result_value); | ||
| 7297 | return ir_build_br(ag, break_scope, node, dest_block, is_comptime); | ||
| 7298 | } | ||
| 7299 | |||
| 7300 | static IrInstSrc *astgen_continue(Stage1AstGen *ag, Scope *continue_scope, AstNode *node) { | ||
| 7301 | assert(node->type == NodeTypeContinue); | ||
| 7302 | |||
| 7303 | // Search up the scope. We'll find one of these things first: | ||
| 7304 | // * function definition scope or global scope => error, break outside loop | ||
| 7305 | // * defer expression scope => error, cannot break out of defer expression | ||
| 7306 | // * loop scope => OK | ||
| 7307 | |||
| 7308 | ZigList<ScopeRuntime *> runtime_scopes = {}; | ||
| 7309 | |||
| 7310 | Scope *search_scope = continue_scope; | ||
| 7311 | ScopeLoop *loop_scope; | ||
| 7312 | for (;;) { | ||
| 7313 | if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) { | ||
| 7314 | if (node->data.continue_expr.name != nullptr) { | ||
| 7315 | add_node_error(ag->codegen, node, buf_sprintf("labeled loop not found: '%s'", buf_ptr(node->data.continue_expr.name))); | ||
| 7316 | return ag->codegen->invalid_inst_src; | ||
| 7317 | } else { | ||
| 7318 | add_node_error(ag->codegen, node, buf_sprintf("continue expression outside loop")); | ||
| 7319 | return ag->codegen->invalid_inst_src; | ||
| 7320 | } | ||
| 7321 | } else if (search_scope->id == ScopeIdDeferExpr) { | ||
| 7322 | add_node_error(ag->codegen, node, buf_sprintf("cannot continue out of defer expression")); | ||
| 7323 | return ag->codegen->invalid_inst_src; | ||
| 7324 | } else if (search_scope->id == ScopeIdLoop) { | ||
| 7325 | ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope; | ||
| 7326 | if (node->data.continue_expr.name == nullptr || | ||
| 7327 | (this_loop_scope->name != nullptr && buf_eql_buf(node->data.continue_expr.name, this_loop_scope->name))) | ||
| 7328 | { | ||
| 7329 | this_loop_scope->name_used = true; | ||
| 7330 | loop_scope = this_loop_scope; | ||
| 7331 | break; | ||
| 7332 | } | ||
| 7333 | } else if (search_scope->id == ScopeIdRuntime) { | ||
| 7334 | ScopeRuntime *scope_runtime = (ScopeRuntime *)search_scope; | ||
| 7335 | runtime_scopes.append(scope_runtime); | ||
| 7336 | } | ||
| 7337 | search_scope = search_scope->parent; | ||
| 7338 | } | ||
| 7339 | |||
| 7340 | IrInstSrc *is_comptime; | ||
| 7341 | if (ir_should_inline(ag->exec, continue_scope)) { | ||
| 7342 | is_comptime = ir_build_const_bool(ag, continue_scope, node, true); | ||
| 7343 | } else { | ||
| 7344 | is_comptime = loop_scope->is_comptime; | ||
| 7345 | } | ||
| 7346 | |||
| 7347 | for (size_t i = 0; i < runtime_scopes.length; i += 1) { | ||
| 7348 | ScopeRuntime *scope_runtime = runtime_scopes.at(i); | ||
| 7349 | ir_mark_gen(ir_build_check_runtime_scope(ag, continue_scope, node, scope_runtime->is_comptime, is_comptime)); | ||
| 7350 | } | ||
| 7351 | runtime_scopes.deinit(); | ||
| 7352 | |||
| 7353 | Stage1ZirBasicBlock *dest_block = loop_scope->continue_block; | ||
| 7354 | if (!astgen_defers_for_block(ag, continue_scope, dest_block->scope, nullptr, nullptr)) | ||
| 7355 | return ag->codegen->invalid_inst_src; | ||
| 7356 | return ir_mark_gen(ir_build_br(ag, continue_scope, node, dest_block, is_comptime)); | ||
| 7357 | } | ||
| 7358 | |||
| 7359 | static IrInstSrc *astgen_error_type(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 7360 | assert(node->type == NodeTypeErrorType); | ||
| 7361 | return ir_build_const_type(ag, scope, node, ag->codegen->builtin_types.entry_global_error_set); | ||
| 7362 | } | ||
| 7363 | |||
| 7364 | static IrInstSrc *astgen_defer(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { | ||
| 7365 | assert(node->type == NodeTypeDefer); | ||
| 7366 | |||
| 7367 | ScopeDefer *defer_child_scope = create_defer_scope(ag->codegen, node, parent_scope); | ||
| 7368 | node->data.defer.child_scope = &defer_child_scope->base; | ||
| 7369 | |||
| 7370 | ScopeDeferExpr *defer_expr_scope = create_defer_expr_scope(ag->codegen, node, parent_scope); | ||
| 7371 | node->data.defer.expr_scope = &defer_expr_scope->base; | ||
| 7372 | |||
| 7373 | return ir_build_const_void(ag, parent_scope, node); | ||
| 7374 | } | ||
| 7375 | |||
| 7376 | static IrInstSrc *astgen_slice(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { | ||
| 7377 | assert(node->type == NodeTypeSliceExpr); | ||
| 7378 | |||
| 7379 | AstNodeSliceExpr *slice_expr = &node->data.slice_expr; | ||
| 7380 | AstNode *array_node = slice_expr->array_ref_expr; | ||
| 7381 | AstNode *start_node = slice_expr->start; | ||
| 7382 | AstNode *end_node = slice_expr->end; | ||
| 7383 | AstNode *sentinel_node = slice_expr->sentinel; | ||
| 7384 | |||
| 7385 | IrInstSrc *ptr_value = astgen_node_extra(ag, array_node, scope, LValPtr, nullptr); | ||
| 7386 | if (ptr_value == ag->codegen->invalid_inst_src) | ||
| 7387 | return ag->codegen->invalid_inst_src; | ||
| 7388 | |||
| 7389 | IrInstSrc *start_value = astgen_node(ag, start_node, scope); | ||
| 7390 | if (start_value == ag->codegen->invalid_inst_src) | ||
| 7391 | return ag->codegen->invalid_inst_src; | ||
| 7392 | |||
| 7393 | IrInstSrc *end_value; | ||
| 7394 | if (end_node) { | ||
| 7395 | end_value = astgen_node(ag, end_node, scope); | ||
| 7396 | if (end_value == ag->codegen->invalid_inst_src) | ||
| 7397 | return ag->codegen->invalid_inst_src; | ||
| 7398 | } else { | ||
| 7399 | end_value = nullptr; | ||
| 7400 | } | ||
| 7401 | |||
| 7402 | IrInstSrc *sentinel_value; | ||
| 7403 | if (sentinel_node) { | ||
| 7404 | sentinel_value = astgen_node(ag, sentinel_node, scope); | ||
| 7405 | if (sentinel_value == ag->codegen->invalid_inst_src) | ||
| 7406 | return ag->codegen->invalid_inst_src; | ||
| 7407 | } else { | ||
| 7408 | sentinel_value = nullptr; | ||
| 7409 | } | ||
| 7410 | |||
| 7411 | IrInstSrc *slice = ir_build_slice_src(ag, scope, node, ptr_value, start_value, end_value, | ||
| 7412 | sentinel_value, true, result_loc); | ||
| 7413 | return ir_lval_wrap(ag, scope, slice, lval, result_loc); | ||
| 7414 | } | ||
| 7415 | |||
| 7416 | static IrInstSrc *astgen_catch(Stage1AstGen *ag, Scope *parent_scope, AstNode *node, LVal lval, | ||
| 7417 | ResultLoc *result_loc) | ||
| 7418 | { | ||
| 7419 | assert(node->type == NodeTypeCatchExpr); | ||
| 7420 | |||
| 7421 | AstNode *op1_node = node->data.unwrap_err_expr.op1; | ||
| 7422 | AstNode *op2_node = node->data.unwrap_err_expr.op2; | ||
| 7423 | AstNode *var_node = node->data.unwrap_err_expr.symbol; | ||
| 7424 | |||
| 7425 | if (op2_node->type == NodeTypeUnreachable) { | ||
| 7426 | if (var_node != nullptr) { | ||
| 7427 | assert(var_node->type == NodeTypeIdentifier); | ||
| 7428 | Buf *var_name = node_identifier_buf(var_node); | ||
| 7429 | add_node_error(ag->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); | ||
| 7430 | return ag->codegen->invalid_inst_src; | ||
| 7431 | } | ||
| 7432 | return astgen_catch_unreachable(ag, parent_scope, node, op1_node, lval, result_loc); | ||
| 7433 | } | ||
| 7434 | |||
| 7435 | |||
| 7436 | ScopeExpr *spill_scope = create_expr_scope(ag->codegen, op1_node, parent_scope); | ||
| 7437 | spill_scope->spill_harder = true; | ||
| 7438 | |||
| 7439 | IrInstSrc *err_union_ptr = astgen_node_extra(ag, op1_node, &spill_scope->base, LValPtr, nullptr); | ||
| 7440 | if (err_union_ptr == ag->codegen->invalid_inst_src) | ||
| 7441 | return ag->codegen->invalid_inst_src; | ||
| 7442 | |||
| 7443 | IrInstSrc *is_err = ir_build_test_err_src(ag, parent_scope, node, err_union_ptr, true, false); | ||
| 7444 | |||
| 7445 | IrInstSrc *is_comptime; | ||
| 7446 | if (ir_should_inline(ag->exec, parent_scope)) { | ||
| 7447 | is_comptime = ir_build_const_bool(ag, parent_scope, node, true); | ||
| 7448 | } else { | ||
| 7449 | is_comptime = ir_build_test_comptime(ag, parent_scope, node, is_err); | ||
| 7450 | } | ||
| 7451 | |||
| 7452 | Stage1ZirBasicBlock *ok_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrOk"); | ||
| 7453 | Stage1ZirBasicBlock *err_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrError"); | ||
| 7454 | Stage1ZirBasicBlock *end_block = ir_create_basic_block(ag, parent_scope, "UnwrapErrEnd"); | ||
| 7455 | IrInstSrc *cond_br_inst = ir_build_cond_br(ag, parent_scope, node, is_err, err_block, ok_block, is_comptime); | ||
| 7456 | |||
| 7457 | ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(ag, cond_br_inst, ok_block, end_block, result_loc, | ||
| 7458 | is_comptime); | ||
| 7459 | |||
| 7460 | ir_set_cursor_at_end_and_append_block(ag, err_block); | ||
| 7461 | Scope *subexpr_scope = create_runtime_scope(ag->codegen, node, &spill_scope->base, is_comptime); | ||
| 7462 | Scope *err_scope; | ||
| 7463 | if (var_node) { | ||
| 7464 | assert(var_node->type == NodeTypeIdentifier); | ||
| 7465 | Buf *var_name = node_identifier_buf(var_node); | ||
| 7466 | bool is_const = true; | ||
| 7467 | bool is_shadowable = false; | ||
| 7468 | ZigVar *var = ir_create_var(ag, node, subexpr_scope, var_name, | ||
| 7469 | is_const, is_const, is_shadowable, is_comptime); | ||
| 7470 | err_scope = var->child_scope; | ||
| 7471 | IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(ag, err_scope, node, err_union_ptr); | ||
| 7472 | IrInstSrc *err_value = ir_build_load_ptr(ag, err_scope, var_node, err_ptr); | ||
| 7473 | build_decl_var_and_init(ag, err_scope, var_node, var, err_value, buf_ptr(var_name), is_comptime); | ||
| 7474 | } else { | ||
| 7475 | err_scope = subexpr_scope; | ||
| 7476 | } | ||
| 7477 | IrInstSrc *err_result = astgen_node_extra(ag, op2_node, err_scope, LValNone, &peer_parent->peers.at(0)->base); | ||
| 7478 | if (err_result == ag->codegen->invalid_inst_src) | ||
| 7479 | return ag->codegen->invalid_inst_src; | ||
| 7480 | Stage1ZirBasicBlock *after_err_block = ag->current_basic_block; | ||
| 7481 | if (!instr_is_unreachable(err_result)) | ||
| 7482 | ir_mark_gen(ir_build_br(ag, parent_scope, node, end_block, is_comptime)); | ||
| 7483 | |||
| 7484 | ir_set_cursor_at_end_and_append_block(ag, ok_block); | ||
| 7485 | IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(ag, parent_scope, node, err_union_ptr, false, false); | ||
| 7486 | IrInstSrc *unwrapped_payload = ir_build_load_ptr(ag, parent_scope, node, unwrapped_ptr); | ||
| 7487 | ir_build_end_expr(ag, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); | ||
| 7488 | Stage1ZirBasicBlock *after_ok_block = ag->current_basic_block; | ||
| 7489 | ir_build_br(ag, parent_scope, node, end_block, is_comptime); | ||
| 7490 | |||
| 7491 | ir_set_cursor_at_end_and_append_block(ag, end_block); | ||
| 7492 | IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2); | ||
| 7493 | incoming_values[0] = err_result; | ||
| 7494 | incoming_values[1] = unwrapped_payload; | ||
| 7495 | Stage1ZirBasicBlock **incoming_blocks = heap::c_allocator.allocate<Stage1ZirBasicBlock *>(2); | ||
| 7496 | incoming_blocks[0] = after_err_block; | ||
| 7497 | incoming_blocks[1] = after_ok_block; | ||
| 7498 | IrInstSrc *phi = ir_build_phi(ag, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); | ||
| 7499 | return ir_lval_wrap(ag, parent_scope, phi, lval, result_loc); | ||
| 7500 | } | ||
| 7501 | |||
| 7502 | static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *outer_scope, Scope *inner_scope) { | ||
| 7503 | if (inner_scope == nullptr || inner_scope == outer_scope) return false; | ||
| 7504 | bool need_comma = render_instance_name_recursive(codegen, name, outer_scope, inner_scope->parent); | ||
| 7505 | if (inner_scope->id != ScopeIdVarDecl) | ||
| 7506 | return need_comma; | ||
| 7507 | |||
| 7508 | ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope; | ||
| 7509 | if (need_comma) | ||
| 7510 | buf_append_char(name, ','); | ||
| 7511 | // TODO: const ptr reinterpret here to make the var type agree with the value? | ||
| 7512 | render_const_value(codegen, name, var_scope->var->const_value); | ||
| 7513 | return true; | ||
| 7514 | } | ||
| 7515 | |||
| 7516 | Buf *get_anon_type_name(CodeGen *codegen, Stage1Zir *exec, const char *kind_name, | ||
| 7517 | Scope *scope, AstNode *source_node, Buf *out_bare_name) | ||
| 7518 | { | ||
| 7519 | if (exec != nullptr && exec->name) { | ||
| 7520 | ZigType *import = get_scope_import(scope); | ||
| 7521 | Buf *namespace_name = buf_alloc(); | ||
| 7522 | append_namespace_qualification(codegen, namespace_name, import); | ||
| 7523 | buf_append_buf(namespace_name, exec->name); | ||
| 7524 | buf_init_from_buf(out_bare_name, exec->name); | ||
| 7525 | return namespace_name; | ||
| 7526 | } else if (exec != nullptr && exec->name_fn != nullptr) { | ||
| 7527 | Buf *name = buf_alloc(); | ||
| 7528 | buf_append_buf(name, &exec->name_fn->symbol_name); | ||
| 7529 | buf_appendf(name, "("); | ||
| 7530 | render_instance_name_recursive(codegen, name, &exec->name_fn->fndef_scope->base, exec->begin_scope); | ||
| 7531 | buf_appendf(name, ")"); | ||
| 7532 | buf_init_from_buf(out_bare_name, name); | ||
| 7533 | return name; | ||
| 7534 | } else { | ||
| 7535 | ZigType *import = get_scope_import(scope); | ||
| 7536 | Buf *namespace_name = buf_alloc(); | ||
| 7537 | append_namespace_qualification(codegen, namespace_name, import); | ||
| 7538 | RootStruct *root_struct = source_node->owner->data.structure.root_struct; | ||
| 7539 | TokenLoc tok_loc = root_struct->token_locs[source_node->main_token]; | ||
| 7540 | buf_appendf(namespace_name, "%s:%u:%u", kind_name, | ||
| 7541 | tok_loc.line + 1, tok_loc.column + 1); | ||
| 7542 | buf_init_from_buf(out_bare_name, namespace_name); | ||
| 7543 | return namespace_name; | ||
| 7544 | } | ||
| 7545 | } | ||
| 7546 | |||
| 7547 | static IrInstSrc *astgen_container_decl(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { | ||
| 7548 | assert(node->type == NodeTypeContainerDecl); | ||
| 7549 | |||
| 7550 | ContainerKind kind = node->data.container_decl.kind; | ||
| 7551 | Buf *bare_name = buf_alloc(); | ||
| 7552 | Buf *name = get_anon_type_name(ag->codegen, ag->exec, container_string(kind), parent_scope, node, bare_name); | ||
| 7553 | |||
| 7554 | ContainerLayout layout = node->data.container_decl.layout; | ||
| 7555 | ZigType *container_type = get_partial_container_type(ag->codegen, parent_scope, | ||
| 7556 | kind, node, buf_ptr(name), bare_name, layout); | ||
| 7557 | ScopeDecls *child_scope = get_container_scope(container_type); | ||
| 7558 | |||
| 7559 | for (size_t i = 0; i < node->data.container_decl.decls.length; i += 1) { | ||
| 7560 | AstNode *child_node = node->data.container_decl.decls.at(i); | ||
| 7561 | scan_decls(ag->codegen, child_scope, child_node); | ||
| 7562 | } | ||
| 7563 | |||
| 7564 | TldContainer *tld_container = heap::c_allocator.create<TldContainer>(); | ||
| 7565 | init_tld(&tld_container->base, TldIdContainer, bare_name, VisibModPub, node, parent_scope); | ||
| 7566 | tld_container->type_entry = container_type; | ||
| 7567 | tld_container->decls_scope = child_scope; | ||
| 7568 | ag->codegen->resolve_queue.append(&tld_container->base); | ||
| 7569 | |||
| 7570 | // Add this to the list to mark as invalid if analyzing this exec fails. | ||
| 7571 | ag->exec->tld_list.append(&tld_container->base); | ||
| 7572 | |||
| 7573 | return ir_build_const_type(ag, parent_scope, node, container_type); | ||
| 7574 | } | ||
| 7575 | |||
| 7576 | static IrInstSrc *astgen_err_set_decl(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { | ||
| 7577 | assert(node->type == NodeTypeErrorSetDecl); | ||
| 7578 | |||
| 7579 | uint32_t err_count = node->data.err_set_decl.decls.length; | ||
| 7580 | |||
| 7581 | Buf bare_name = BUF_INIT; | ||
| 7582 | Buf *type_name = get_anon_type_name(ag->codegen, ag->exec, "error", parent_scope, node, &bare_name); | ||
| 7583 | ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); | ||
| 7584 | buf_init_from_buf(&err_set_type->name, type_name); | ||
| 7585 | err_set_type->data.error_set.err_count = err_count; | ||
| 7586 | err_set_type->size_in_bits = ag->codegen->builtin_types.entry_global_error_set->size_in_bits; | ||
| 7587 | err_set_type->abi_align = ag->codegen->builtin_types.entry_global_error_set->abi_align; | ||
| 7588 | err_set_type->abi_size = ag->codegen->builtin_types.entry_global_error_set->abi_size; | ||
| 7589 | err_set_type->data.error_set.errors = heap::c_allocator.allocate<ErrorTableEntry *>(err_count); | ||
| 7590 | |||
| 7591 | size_t errors_count = ag->codegen->errors_by_index.length + err_count; | ||
| 7592 | ErrorTableEntry **errors = heap::c_allocator.allocate<ErrorTableEntry *>(errors_count); | ||
| 7593 | |||
| 7594 | for (uint32_t i = 0; i < err_count; i += 1) { | ||
| 7595 | AstNode *field_node = node->data.err_set_decl.decls.at(i); | ||
| 7596 | AstNode *symbol_node = ast_field_to_symbol_node(field_node); | ||
| 7597 | Buf *err_name = node_identifier_buf(symbol_node); | ||
| 7598 | ErrorTableEntry *err = heap::c_allocator.create<ErrorTableEntry>(); | ||
| 7599 | err->decl_node = field_node; | ||
| 7600 | buf_init_from_buf(&err->name, err_name); | ||
| 7601 | |||
| 7602 | auto existing_entry = ag->codegen->error_table.put_unique(err_name, err); | ||
| 7603 | if (existing_entry) { | ||
| 7604 | err->value = existing_entry->value->value; | ||
| 7605 | } else { | ||
| 7606 | size_t error_value_count = ag->codegen->errors_by_index.length; | ||
| 7607 | assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)ag->codegen->err_tag_type->data.integral.bit_count)); | ||
| 7608 | err->value = error_value_count; | ||
| 7609 | ag->codegen->errors_by_index.append(err); | ||
| 7610 | } | ||
| 7611 | err_set_type->data.error_set.errors[i] = err; | ||
| 7612 | |||
| 7613 | ErrorTableEntry *prev_err = errors[err->value]; | ||
| 7614 | if (prev_err != nullptr) { | ||
| 7615 | ErrorMsg *msg = add_node_error(ag->codegen, ast_field_to_symbol_node(err->decl_node), | ||
| 7616 | buf_sprintf("duplicate error: '%s'", buf_ptr(&err->name))); | ||
| 7617 | add_error_note(ag->codegen, msg, ast_field_to_symbol_node(prev_err->decl_node), | ||
| 7618 | buf_sprintf("other error here")); | ||
| 7619 | return ag->codegen->invalid_inst_src; | ||
| 7620 | } | ||
| 7621 | errors[err->value] = err; | ||
| 7622 | } | ||
| 7623 | heap::c_allocator.deallocate(errors, errors_count); | ||
| 7624 | return ir_build_const_type(ag, parent_scope, node, err_set_type); | ||
| 7625 | } | ||
| 7626 | |||
| 7627 | static IrInstSrc *astgen_fn_proto(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { | ||
| 7628 | assert(node->type == NodeTypeFnProto); | ||
| 7629 | |||
| 7630 | size_t param_count = node->data.fn_proto.params.length; | ||
| 7631 | IrInstSrc **param_types = heap::c_allocator.allocate<IrInstSrc*>(param_count); | ||
| 7632 | |||
| 7633 | bool is_var_args = false; | ||
| 7634 | for (size_t i = 0; i < param_count; i += 1) { | ||
| 7635 | AstNode *param_node = node->data.fn_proto.params.at(i); | ||
| 7636 | if (param_node->data.param_decl.is_var_args) { | ||
| 7637 | is_var_args = true; | ||
| 7638 | break; | ||
| 7639 | } | ||
| 7640 | if (param_node->data.param_decl.anytype_token == 0) { | ||
| 7641 | AstNode *type_node = param_node->data.param_decl.type; | ||
| 7642 | IrInstSrc *type_value = astgen_node(ag, type_node, parent_scope); | ||
| 7643 | if (type_value == ag->codegen->invalid_inst_src) | ||
| 7644 | return ag->codegen->invalid_inst_src; | ||
| 7645 | param_types[i] = type_value; | ||
| 7646 | } else { | ||
| 7647 | param_types[i] = nullptr; | ||
| 7648 | } | ||
| 7649 | } | ||
| 7650 | |||
| 7651 | IrInstSrc *align_value = nullptr; | ||
| 7652 | if (node->data.fn_proto.align_expr != nullptr) { | ||
| 7653 | align_value = astgen_node(ag, node->data.fn_proto.align_expr, parent_scope); | ||
| 7654 | if (align_value == ag->codegen->invalid_inst_src) | ||
| 7655 | return ag->codegen->invalid_inst_src; | ||
| 7656 | } | ||
| 7657 | |||
| 7658 | IrInstSrc *callconv_value = nullptr; | ||
| 7659 | if (node->data.fn_proto.callconv_expr != nullptr) { | ||
| 7660 | callconv_value = astgen_node(ag, node->data.fn_proto.callconv_expr, parent_scope); | ||
| 7661 | if (callconv_value == ag->codegen->invalid_inst_src) | ||
| 7662 | return ag->codegen->invalid_inst_src; | ||
| 7663 | } | ||
| 7664 | |||
| 7665 | IrInstSrc *return_type; | ||
| 7666 | if (node->data.fn_proto.return_type == nullptr) { | ||
| 7667 | return_type = ir_build_const_type(ag, parent_scope, node, ag->codegen->builtin_types.entry_void); | ||
| 7668 | } else { | ||
| 7669 | return_type = astgen_node(ag, node->data.fn_proto.return_type, parent_scope); | ||
| 7670 | if (return_type == ag->codegen->invalid_inst_src) | ||
| 7671 | return ag->codegen->invalid_inst_src; | ||
| 7672 | } | ||
| 7673 | |||
| 7674 | return ir_build_fn_proto(ag, parent_scope, node, param_types, align_value, callconv_value, return_type, is_var_args); | ||
| 7675 | } | ||
| 7676 | |||
| 7677 | static IrInstSrc *astgen_resume(Stage1AstGen *ag, Scope *scope, AstNode *node) { | ||
| 7678 | assert(node->type == NodeTypeResume); | ||
| 7679 | |||
| 7680 | IrInstSrc *target_inst = astgen_node_extra(ag, node->data.resume_expr.expr, scope, LValPtr, nullptr); | ||
| 7681 | if (target_inst == ag->codegen->invalid_inst_src) | ||
| 7682 | return ag->codegen->invalid_inst_src; | ||
| 7683 | |||
| 7684 | return ir_build_resume_src(ag, scope, node, target_inst); | ||
| 7685 | } | ||
| 7686 | |||
| 7687 | static IrInstSrc *astgen_await_expr(Stage1AstGen *ag, Scope *scope, AstNode *node, LVal lval, | ||
| 7688 | ResultLoc *result_loc) | ||
| 7689 | { | ||
| 7690 | assert(node->type == NodeTypeAwaitExpr); | ||
| 7691 | |||
| 7692 | bool is_nosuspend = get_scope_nosuspend(scope) != nullptr; | ||
| 7693 | |||
| 7694 | AstNode *expr_node = node->data.await_expr.expr; | ||
| 7695 | if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) { | ||
| 7696 | AstNode *fn_ref_expr = expr_node->data.fn_call_expr.fn_ref_expr; | ||
| 7697 | Buf *name = node_identifier_buf(fn_ref_expr); | ||
| 7698 | auto entry = ag->codegen->builtin_fn_table.maybe_get(name); | ||
| 7699 | if (entry != nullptr) { | ||
| 7700 | BuiltinFnEntry *builtin_fn = entry->value; | ||
| 7701 | if (builtin_fn->id == BuiltinFnIdAsyncCall) { | ||
| 7702 | return astgen_async_call(ag, scope, node, expr_node, lval, result_loc); | ||
| 7703 | } | ||
| 7704 | } | ||
| 7705 | } | ||
| 7706 | |||
| 7707 | if (!ag->fn) { | ||
| 7708 | add_node_error(ag->codegen, node, buf_sprintf("await outside function definition")); | ||
| 7709 | return ag->codegen->invalid_inst_src; | ||
| 7710 | } | ||
| 7711 | ScopeSuspend *existing_suspend_scope = get_scope_suspend(scope); | ||
| 7712 | if (existing_suspend_scope) { | ||
| 7713 | if (!existing_suspend_scope->reported_err) { | ||
| 7714 | ErrorMsg *msg = add_node_error(ag->codegen, node, buf_sprintf("cannot await inside suspend block")); | ||
| 7715 | add_error_note(ag->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("suspend block here")); | ||
| 7716 | existing_suspend_scope->reported_err = true; | ||
| 7717 | } | ||
| 7718 | return ag->codegen->invalid_inst_src; | ||
| 7719 | } | ||
| 7720 | |||
| 7721 | IrInstSrc *target_inst = astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr); | ||
| 7722 | if (target_inst == ag->codegen->invalid_inst_src) | ||
| 7723 | return ag->codegen->invalid_inst_src; | ||
| 7724 | |||
| 7725 | IrInstSrc *await_inst = ir_build_await_src(ag, scope, node, target_inst, result_loc, is_nosuspend); | ||
| 7726 | return ir_lval_wrap(ag, scope, await_inst, lval, result_loc); | ||
| 7727 | } | ||
| 7728 | |||
| 7729 | static IrInstSrc *astgen_suspend(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) { | ||
| 7730 | assert(node->type == NodeTypeSuspend); | ||
| 7731 | |||
| 7732 | if (!ag->fn) { | ||
| 7733 | add_node_error(ag->codegen, node, buf_sprintf("suspend outside function definition")); | ||
| 7734 | return ag->codegen->invalid_inst_src; | ||
| 7735 | } | ||
| 7736 | if (get_scope_nosuspend(parent_scope) != nullptr) { | ||
| 7737 | add_node_error(ag->codegen, node, buf_sprintf("suspend in nosuspend scope")); | ||
| 7738 | return ag->codegen->invalid_inst_src; | ||
| 7739 | } | ||
| 7740 | |||
| 7741 | ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope); | ||
| 7742 | if (existing_suspend_scope) { | ||
| 7743 | if (!existing_suspend_scope->reported_err) { | ||
| 7744 | ErrorMsg *msg = add_node_error(ag->codegen, node, buf_sprintf("cannot suspend inside suspend block")); | ||
| 7745 | add_error_note(ag->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("other suspend block here")); | ||
| 7746 | existing_suspend_scope->reported_err = true; | ||
| 7747 | } | ||
| 7748 | return ag->codegen->invalid_inst_src; | ||
| 7749 | } | ||
| 7750 | |||
| 7751 | IrInstSrcSuspendBegin *begin = ir_build_suspend_begin_src(ag, parent_scope, node); | ||
| 7752 | ScopeSuspend *suspend_scope = create_suspend_scope(ag->codegen, node, parent_scope); | ||
| 7753 | Scope *child_scope = &suspend_scope->base; | ||
| 7754 | IrInstSrc *susp_res = astgen_node(ag, node->data.suspend.block, child_scope); | ||
| 7755 | if (susp_res == ag->codegen->invalid_inst_src) | ||
| 7756 | return ag->codegen->invalid_inst_src; | ||
| 7757 | ir_mark_gen(ir_build_check_statement_is_void(ag, child_scope, node->data.suspend.block, susp_res)); | ||
| 7758 | |||
| 7759 | return ir_mark_gen(ir_build_suspend_finish_src(ag, parent_scope, node, begin)); | ||
| 7760 | } | ||
| 7761 | |||
| 7762 | static IrInstSrc *astgen_node_raw(Stage1AstGen *ag, AstNode *node, Scope *scope, | ||
| 7763 | LVal lval, ResultLoc *result_loc) | ||
| 7764 | { | ||
| 7765 | assert(scope); | ||
| 7766 | switch (node->type) { | ||
| 7767 | case NodeTypeStructValueField: | ||
| 7768 | case NodeTypeParamDecl: | ||
| 7769 | case NodeTypeUsingNamespace: | ||
| 7770 | case NodeTypeSwitchProng: | ||
| 7771 | case NodeTypeSwitchRange: | ||
| 7772 | case NodeTypeStructField: | ||
| 7773 | case NodeTypeErrorSetField: | ||
| 7774 | case NodeTypeFnDef: | ||
| 7775 | case NodeTypeTestDecl: | ||
| 7776 | zig_unreachable(); | ||
| 7777 | case NodeTypeBlock: | ||
| 7778 | return astgen_block(ag, scope, node, lval, result_loc); | ||
| 7779 | case NodeTypeGroupedExpr: | ||
| 7780 | return astgen_node_raw(ag, node->data.grouped_expr, scope, lval, result_loc); | ||
| 7781 | case NodeTypeBinOpExpr: | ||
| 7782 | return astgen_bin_op(ag, scope, node, lval, result_loc); | ||
| 7783 | case NodeTypeIntLiteral: | ||
| 7784 | return ir_lval_wrap(ag, scope, astgen_int_lit(ag, scope, node), lval, result_loc); | ||
| 7785 | case NodeTypeFloatLiteral: | ||
| 7786 | return ir_lval_wrap(ag, scope, astgen_float_lit(ag, scope, node), lval, result_loc); | ||
| 7787 | case NodeTypeCharLiteral: | ||
| 7788 | return ir_lval_wrap(ag, scope, astgen_char_lit(ag, scope, node), lval, result_loc); | ||
| 7789 | case NodeTypeIdentifier: | ||
| 7790 | return astgen_identifier(ag, scope, node, lval, result_loc); | ||
| 7791 | case NodeTypeFnCallExpr: | ||
| 7792 | return astgen_fn_call(ag, scope, node, lval, result_loc); | ||
| 7793 | case NodeTypeIfBoolExpr: | ||
| 7794 | return astgen_if_bool_expr(ag, scope, node, lval, result_loc); | ||
| 7795 | case NodeTypePrefixOpExpr: | ||
| 7796 | return astgen_prefix_op_expr(ag, scope, node, lval, result_loc); | ||
| 7797 | case NodeTypeContainerInitExpr: | ||
| 7798 | return astgen_container_init_expr(ag, scope, node, lval, result_loc); | ||
| 7799 | case NodeTypeVariableDeclaration: | ||
| 7800 | return astgen_var_decl(ag, scope, node); | ||
| 7801 | case NodeTypeWhileExpr: | ||
| 7802 | return astgen_while_expr(ag, scope, node, lval, result_loc); | ||
| 7803 | case NodeTypeForExpr: | ||
| 7804 | return astgen_for_expr(ag, scope, node, lval, result_loc); | ||
| 7805 | case NodeTypeArrayAccessExpr: | ||
| 7806 | return astgen_array_access(ag, scope, node, lval, result_loc); | ||
| 7807 | case NodeTypeReturnExpr: | ||
| 7808 | return astgen_return(ag, scope, node, lval, result_loc); | ||
| 7809 | case NodeTypeFieldAccessExpr: | ||
| 7810 | { | ||
| 7811 | IrInstSrc *ptr_instruction = astgen_field_access(ag, scope, node); | ||
| 7812 | if (ptr_instruction == ag->codegen->invalid_inst_src) | ||
| 7813 | return ptr_instruction; | ||
| 7814 | if (lval == LValPtr || lval == LValAssign) | ||
| 7815 | return ptr_instruction; | ||
| 7816 | |||
| 7817 | IrInstSrc *load_ptr = ir_build_load_ptr(ag, scope, node, ptr_instruction); | ||
| 7818 | return ir_expr_wrap(ag, scope, load_ptr, result_loc); | ||
| 7819 | } | ||
| 7820 | case NodeTypePtrDeref: { | ||
| 7821 | AstNode *expr_node = node->data.ptr_deref_expr.target; | ||
| 7822 | |||
| 7823 | LVal child_lval = lval; | ||
| 7824 | if (child_lval == LValAssign) | ||
| 7825 | child_lval = LValPtr; | ||
| 7826 | |||
| 7827 | IrInstSrc *value = astgen_node_extra(ag, expr_node, scope, child_lval, nullptr); | ||
| 7828 | if (value == ag->codegen->invalid_inst_src) | ||
| 7829 | return value; | ||
| 7830 | |||
| 7831 | // We essentially just converted any lvalue from &(x.*) to (&x).*; | ||
| 7832 | // this inhibits checking that x is a pointer later, so we directly | ||
| 7833 | // record whether the pointer check is needed | ||
| 7834 | IrInstSrc *un_op = ir_build_un_op_lval(ag, scope, node, IrUnOpDereference, value, lval, result_loc); | ||
| 7835 | return ir_expr_wrap(ag, scope, un_op, result_loc); | ||
| 7836 | } | ||
| 7837 | case NodeTypeUnwrapOptional: { | ||
| 7838 | AstNode *expr_node = node->data.unwrap_optional.expr; | ||
| 7839 | |||
| 7840 | IrInstSrc *maybe_ptr = astgen_node_extra(ag, expr_node, scope, LValPtr, nullptr); | ||
| 7841 | if (maybe_ptr == ag->codegen->invalid_inst_src) | ||
| 7842 | return ag->codegen->invalid_inst_src; | ||
| 7843 | |||
| 7844 | IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(ag, scope, node, maybe_ptr, true ); | ||
| 7845 | if (lval == LValPtr || lval == LValAssign) | ||
| 7846 | return unwrapped_ptr; | ||
| 7847 | |||
| 7848 | IrInstSrc *load_ptr = ir_build_load_ptr(ag, scope, node, unwrapped_ptr); | ||
| 7849 | return ir_expr_wrap(ag, scope, load_ptr, result_loc); | ||
| 7850 | } | ||
| 7851 | case NodeTypeBoolLiteral: | ||
| 7852 | return ir_lval_wrap(ag, scope, astgen_bool_literal(ag, scope, node), lval, result_loc); | ||
| 7853 | case NodeTypeArrayType: | ||
| 7854 | return ir_lval_wrap(ag, scope, astgen_array_type(ag, scope, node), lval, result_loc); | ||
| 7855 | case NodeTypePointerType: | ||
| 7856 | return ir_lval_wrap(ag, scope, astgen_pointer_type(ag, scope, node), lval, result_loc); | ||
| 7857 | case NodeTypeAnyFrameType: | ||
| 7858 | return ir_lval_wrap(ag, scope, astgen_anyframe_type(ag, scope, node), lval, result_loc); | ||
| 7859 | case NodeTypeStringLiteral: | ||
| 7860 | return ir_lval_wrap(ag, scope, astgen_string_literal(ag, scope, node), lval, result_loc); | ||
| 7861 | case NodeTypeUndefinedLiteral: | ||
| 7862 | return ir_lval_wrap(ag, scope, astgen_undefined_literal(ag, scope, node), lval, result_loc); | ||
| 7863 | case NodeTypeAsmExpr: | ||
| 7864 | return ir_lval_wrap(ag, scope, astgen_asm_expr(ag, scope, node), lval, result_loc); | ||
| 7865 | case NodeTypeNullLiteral: | ||
| 7866 | return ir_lval_wrap(ag, scope, astgen_null_literal(ag, scope, node), lval, result_loc); | ||
| 7867 | case NodeTypeIfErrorExpr: | ||
| 7868 | return astgen_if_err_expr(ag, scope, node, lval, result_loc); | ||
| 7869 | case NodeTypeIfOptional: | ||
| 7870 | return astgen_if_optional_expr(ag, scope, node, lval, result_loc); | ||
| 7871 | case NodeTypeSwitchExpr: | ||
| 7872 | return astgen_switch_expr(ag, scope, node, lval, result_loc); | ||
| 7873 | case NodeTypeCompTime: | ||
| 7874 | return ir_expr_wrap(ag, scope, astgen_comptime(ag, scope, node, lval), result_loc); | ||
| 7875 | case NodeTypeNoSuspend: | ||
| 7876 | return ir_expr_wrap(ag, scope, astgen_nosuspend(ag, scope, node, lval), result_loc); | ||
| 7877 | case NodeTypeErrorType: | ||
| 7878 | return ir_lval_wrap(ag, scope, astgen_error_type(ag, scope, node), lval, result_loc); | ||
| 7879 | case NodeTypeBreak: | ||
| 7880 | return ir_lval_wrap(ag, scope, astgen_break(ag, scope, node), lval, result_loc); | ||
| 7881 | case NodeTypeContinue: | ||
| 7882 | return ir_lval_wrap(ag, scope, astgen_continue(ag, scope, node), lval, result_loc); | ||
| 7883 | case NodeTypeUnreachable: | ||
| 7884 | return ir_build_unreachable(ag, scope, node); | ||
| 7885 | case NodeTypeDefer: | ||
| 7886 | return ir_lval_wrap(ag, scope, astgen_defer(ag, scope, node), lval, result_loc); | ||
| 7887 | case NodeTypeSliceExpr: | ||
| 7888 | return astgen_slice(ag, scope, node, lval, result_loc); | ||
| 7889 | case NodeTypeCatchExpr: | ||
| 7890 | return astgen_catch(ag, scope, node, lval, result_loc); | ||
| 7891 | case NodeTypeContainerDecl: | ||
| 7892 | return ir_lval_wrap(ag, scope, astgen_container_decl(ag, scope, node), lval, result_loc); | ||
| 7893 | case NodeTypeFnProto: | ||
| 7894 | return ir_lval_wrap(ag, scope, astgen_fn_proto(ag, scope, node), lval, result_loc); | ||
| 7895 | case NodeTypeErrorSetDecl: | ||
| 7896 | return ir_lval_wrap(ag, scope, astgen_err_set_decl(ag, scope, node), lval, result_loc); | ||
| 7897 | case NodeTypeResume: | ||
| 7898 | return ir_lval_wrap(ag, scope, astgen_resume(ag, scope, node), lval, result_loc); | ||
| 7899 | case NodeTypeAwaitExpr: | ||
| 7900 | return astgen_await_expr(ag, scope, node, lval, result_loc); | ||
| 7901 | case NodeTypeSuspend: | ||
| 7902 | return ir_lval_wrap(ag, scope, astgen_suspend(ag, scope, node), lval, result_loc); | ||
| 7903 | case NodeTypeEnumLiteral: | ||
| 7904 | return ir_lval_wrap(ag, scope, astgen_enum_literal(ag, scope, node), lval, result_loc); | ||
| 7905 | case NodeTypeInferredArrayType: | ||
| 7906 | add_node_error(ag->codegen, node, | ||
| 7907 | buf_sprintf("inferred array size invalid here")); | ||
| 7908 | return ag->codegen->invalid_inst_src; | ||
| 7909 | case NodeTypeAnyTypeField: | ||
| 7910 | return ir_lval_wrap(ag, scope, | ||
| 7911 | ir_build_const_type(ag, scope, node, ag->codegen->builtin_types.entry_anytype), lval, result_loc); | ||
| 7912 | } | ||
| 7913 | zig_unreachable(); | ||
| 7914 | } | ||
| 7915 | |||
| 7916 | ResultLoc *no_result_loc(void) { | ||
| 7917 | ResultLocNone *result_loc_none = heap::c_allocator.create<ResultLocNone>(); | ||
| 7918 | result_loc_none->base.id = ResultLocIdNone; | ||
| 7919 | return &result_loc_none->base; | ||
| 7920 | } | ||
| 7921 | |||
| 7922 | static IrInstSrc *astgen_node_extra(Stage1AstGen *ag, AstNode *node, Scope *scope, LVal lval, | ||
| 7923 | ResultLoc *result_loc) | ||
| 7924 | { | ||
| 7925 | if (lval == LValAssign) { | ||
| 7926 | switch (node->type) { | ||
| 7927 | case NodeTypeStructValueField: | ||
| 7928 | case NodeTypeParamDecl: | ||
| 7929 | case NodeTypeUsingNamespace: | ||
| 7930 | case NodeTypeSwitchProng: | ||
| 7931 | case NodeTypeSwitchRange: | ||
| 7932 | case NodeTypeStructField: | ||
| 7933 | case NodeTypeErrorSetField: | ||
| 7934 | case NodeTypeFnDef: | ||
| 7935 | case NodeTypeTestDecl: | ||
| 7936 | zig_unreachable(); | ||
| 7937 | |||
| 7938 | // cannot be assigned to | ||
| 7939 | case NodeTypeBlock: | ||
| 7940 | case NodeTypeGroupedExpr: | ||
| 7941 | case NodeTypeBinOpExpr: | ||
| 7942 | case NodeTypeIntLiteral: | ||
| 7943 | case NodeTypeFloatLiteral: | ||
| 7944 | case NodeTypeCharLiteral: | ||
| 7945 | case NodeTypeIfBoolExpr: | ||
| 7946 | case NodeTypeContainerInitExpr: | ||
| 7947 | case NodeTypeVariableDeclaration: | ||
| 7948 | case NodeTypeWhileExpr: | ||
| 7949 | case NodeTypeForExpr: | ||
| 7950 | case NodeTypeReturnExpr: | ||
| 7951 | case NodeTypeBoolLiteral: | ||
| 7952 | case NodeTypeArrayType: | ||
| 7953 | case NodeTypePointerType: | ||
| 7954 | case NodeTypeAnyFrameType: | ||
| 7955 | case NodeTypeStringLiteral: | ||
| 7956 | case NodeTypeUndefinedLiteral: | ||
| 7957 | case NodeTypeAsmExpr: | ||
| 7958 | case NodeTypeNullLiteral: | ||
| 7959 | case NodeTypeIfErrorExpr: | ||
| 7960 | case NodeTypeIfOptional: | ||
| 7961 | case NodeTypeSwitchExpr: | ||
| 7962 | case NodeTypeCompTime: | ||
| 7963 | case NodeTypeNoSuspend: | ||
| 7964 | case NodeTypeErrorType: | ||
| 7965 | case NodeTypeBreak: | ||
| 7966 | case NodeTypeContinue: | ||
| 7967 | case NodeTypeUnreachable: | ||
| 7968 | case NodeTypeDefer: | ||
| 7969 | case NodeTypeSliceExpr: | ||
| 7970 | case NodeTypeCatchExpr: | ||
| 7971 | case NodeTypeContainerDecl: | ||
| 7972 | case NodeTypeFnProto: | ||
| 7973 | case NodeTypeErrorSetDecl: | ||
| 7974 | case NodeTypeResume: | ||
| 7975 | case NodeTypeAwaitExpr: | ||
| 7976 | case NodeTypeSuspend: | ||
| 7977 | case NodeTypeEnumLiteral: | ||
| 7978 | case NodeTypeInferredArrayType: | ||
| 7979 | case NodeTypeAnyTypeField: | ||
| 7980 | case NodeTypePrefixOpExpr: | ||
| 7981 | add_node_error(ag->codegen, node, | ||
| 7982 | buf_sprintf("invalid left-hand side to assignment")); | ||
| 7983 | return ag->codegen->invalid_inst_src; | ||
| 7984 | |||
| 7985 | // @field can be assigned to | ||
| 7986 | case NodeTypeFnCallExpr: | ||
| 7987 | if (node->data.fn_call_expr.modifier == CallModifierBuiltin) { | ||
| 7988 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; | ||
| 7989 | Buf *name = node_identifier_buf(fn_ref_expr); | ||
| 7990 | auto entry = ag->codegen->builtin_fn_table.maybe_get(name); | ||
| 7991 | |||
| 7992 | if (!entry) { | ||
| 7993 | add_node_error(ag->codegen, node, | ||
| 7994 | buf_sprintf("invalid builtin function: '%s'", buf_ptr(name))); | ||
| 7995 | return ag->codegen->invalid_inst_src; | ||
| 7996 | } | ||
| 7997 | |||
| 7998 | if (entry->value->id == BuiltinFnIdField) { | ||
| 7999 | break; | ||
| 8000 | } | ||
| 8001 | } | ||
| 8002 | add_node_error(ag->codegen, node, | ||
| 8003 | buf_sprintf("invalid left-hand side to assignment")); | ||
| 8004 | return ag->codegen->invalid_inst_src; | ||
| 8005 | |||
| 8006 | |||
| 8007 | // can be assigned to | ||
| 8008 | case NodeTypeUnwrapOptional: | ||
| 8009 | case NodeTypePtrDeref: | ||
| 8010 | case NodeTypeFieldAccessExpr: | ||
| 8011 | case NodeTypeArrayAccessExpr: | ||
| 8012 | case NodeTypeIdentifier: | ||
| 8013 | break; | ||
| 8014 | } | ||
| 8015 | } | ||
| 8016 | if (result_loc == nullptr) { | ||
| 8017 | // Create a result location indicating there is none - but if one gets created | ||
| 8018 | // it will be properly distributed. | ||
| 8019 | result_loc = no_result_loc(); | ||
| 8020 | ir_build_reset_result(ag, scope, node, result_loc); | ||
| 8021 | } | ||
| 8022 | Scope *child_scope; | ||
| 8023 | if (ag->exec->is_inline || | ||
| 8024 | (ag->fn != nullptr && ag->fn->child_scope == scope)) | ||
| 8025 | { | ||
| 8026 | child_scope = scope; | ||
| 8027 | } else { | ||
| 8028 | child_scope = &create_expr_scope(ag->codegen, node, scope)->base; | ||
| 8029 | } | ||
| 8030 | IrInstSrc *result = astgen_node_raw(ag, node, child_scope, lval, result_loc); | ||
| 8031 | if (result == ag->codegen->invalid_inst_src) { | ||
| 8032 | if (ag->exec->first_err_trace_msg == nullptr) { | ||
| 8033 | ag->exec->first_err_trace_msg = ag->codegen->trace_err; | ||
| 8034 | } | ||
| 8035 | } | ||
| 8036 | return result; | ||
| 8037 | } | ||
| 8038 | |||
| 8039 | static IrInstSrc *astgen_node(Stage1AstGen *ag, AstNode *node, Scope *scope) { | ||
| 8040 | return astgen_node_extra(ag, node, scope, LValNone, nullptr); | ||
| 8041 | } | ||
| 8042 | |||
| 8043 | bool stage1_astgen(CodeGen *codegen, AstNode *node, Scope *scope, Stage1Zir *stage1_zir, | ||
| 8044 | ZigFn *fn, bool in_c_import_scope) | ||
| 8045 | { | ||
| 8046 | assert(node->owner); | ||
| 8047 | |||
| 8048 | Stage1AstGen ir_builder = {0}; | ||
| 8049 | Stage1AstGen *ag = &ir_builder; | ||
| 8050 | |||
| 8051 | ag->codegen = codegen; | ||
| 8052 | ag->fn = fn; | ||
| 8053 | ag->in_c_import_scope = in_c_import_scope; | ||
| 8054 | ag->exec = stage1_zir; | ||
| 8055 | ag->main_block_node = node; | ||
| 8056 | |||
| 8057 | Stage1ZirBasicBlock *entry_block = ir_create_basic_block(ag, scope, "Entry"); | ||
| 8058 | ir_set_cursor_at_end_and_append_block(ag, entry_block); | ||
| 8059 | // Entry block gets a reference because we enter it to begin. | ||
| 8060 | ir_ref_bb(ag->current_basic_block); | ||
| 8061 | |||
| 8062 | IrInstSrc *result = astgen_node_extra(ag, node, scope, LValNone, nullptr); | ||
| 8063 | |||
| 8064 | if (result == ag->codegen->invalid_inst_src) | ||
| 8065 | return false; | ||
| 8066 | |||
| 8067 | if (ag->exec->first_err_trace_msg != nullptr) { | ||
| 8068 | codegen->trace_err = ag->exec->first_err_trace_msg; | ||
| 8069 | return false; | ||
| 8070 | } | ||
| 8071 | |||
| 8072 | if (!instr_is_unreachable(result)) { | ||
| 8073 | ir_mark_gen(ir_build_add_implicit_return_type(ag, scope, result->base.source_node, result, nullptr)); | ||
| 8074 | // no need for save_err_ret_addr because this cannot return error | ||
| 8075 | ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>(); | ||
| 8076 | result_loc_ret->base.id = ResultLocIdReturn; | ||
| 8077 | ir_build_reset_result(ag, scope, node, &result_loc_ret->base); | ||
| 8078 | ir_mark_gen(ir_build_end_expr(ag, scope, node, result, &result_loc_ret->base)); | ||
| 8079 | ir_mark_gen(ir_build_return_src(ag, scope, result->base.source_node, result)); | ||
| 8080 | } | ||
| 8081 | |||
| 8082 | return true; | ||
| 8083 | } | ||
| 8084 | |||
| 8085 | bool stage1_astgen_fn(CodeGen *codegen, ZigFn *fn) { | ||
| 8086 | assert(fn != nullptr); | ||
| 8087 | assert(fn->child_scope != nullptr); | ||
| 8088 | return stage1_astgen(codegen, fn->body_node, fn->child_scope, fn->stage1_zir, fn, false); | ||
| 8089 | } | ||
| 8090 | |||
| 8091 | void invalidate_exec(Stage1Zir *exec, ErrorMsg *msg) { | ||
| 8092 | if (exec->first_err_trace_msg != nullptr) | ||
| 8093 | return; | ||
| 8094 | |||
| 8095 | exec->first_err_trace_msg = msg; | ||
| 8096 | |||
| 8097 | for (size_t i = 0; i < exec->tld_list.length; i += 1) { | ||
| 8098 | exec->tld_list.items[i]->resolution = TldResolutionInvalid; | ||
| 8099 | } | ||
| 8100 | } | ||
| 8101 | |||
| 8102 | AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node) { | ||
| 8103 | if (err_set_field_node->type == NodeTypeIdentifier) { | ||
| 8104 | return err_set_field_node; | ||
| 8105 | } else if (err_set_field_node->type == NodeTypeErrorSetField) { | ||
| 8106 | assert(err_set_field_node->data.err_set_field.field_name->type == NodeTypeIdentifier); | ||
| 8107 | return err_set_field_node->data.err_set_field.field_name; | ||
| 8108 | } else { | ||
| 8109 | return err_set_field_node; | ||
| 8110 | } | ||
| 8111 | } | ||
| 8112 | |||
| 8113 | void ir_add_call_stack_errors_gen(CodeGen *codegen, Stage1Air *exec, ErrorMsg *err_msg, int limit) { | ||
| 8114 | if (!exec || !exec->source_node || limit < 0) return; | ||
| 8115 | add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); | ||
| 8116 | |||
| 8117 | ir_add_call_stack_errors_gen(codegen, exec->parent_exec, err_msg, limit - 1); | ||
| 8118 | } | ||
| 8119 | |||
src/stage1/astgen.hpp created+37| ... | @@ -0,0 +1,37 @@ | ||
| 1 | /* | ||
| 2 | * Copyright (c) 2021 Andrew Kelley | ||
| 3 | * | ||
| 4 | * This file is part of zig, which is MIT licensed. | ||
| 5 | * See http://opensource.org/licenses/MIT | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef ZIG_ASTGEN_HPP | ||
| 9 | #define ZIG_ASTGEN_HPP | ||
| 10 | |||
| 11 | #include "all_types.hpp" | ||
| 12 | |||
| 13 | bool stage1_astgen(CodeGen *g, AstNode *node, Scope *scope, Stage1Zir *stage1_zir, | ||
| 14 | ZigFn *fn, bool in_c_import_scope); | ||
| 15 | bool stage1_astgen_fn(CodeGen *g, ZigFn *fn_entry); | ||
| 16 | |||
| 17 | bool ir_inst_src_has_side_effects(IrInstSrc *inst); | ||
| 18 | |||
| 19 | ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope, | ||
| 20 | Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime, | ||
| 21 | bool skip_name_check); | ||
| 22 | |||
| 23 | ResultLoc *no_result_loc(void); | ||
| 24 | |||
| 25 | void invalidate_exec(Stage1Zir *exec, ErrorMsg *msg); | ||
| 26 | |||
| 27 | AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node); | ||
| 28 | void ir_add_call_stack_errors_gen(CodeGen *codegen, Stage1Air *exec, ErrorMsg *err_msg, | ||
| 29 | int limit); | ||
| 30 | |||
| 31 | void destroy_instruction_src(IrInstSrc *inst); | ||
| 32 | |||
| 33 | bool ir_should_inline(Stage1Zir *exec, Scope *scope); | ||
| 34 | Buf *get_anon_type_name(CodeGen *codegen, Stage1Zir *exec, const char *kind_name, | ||
| 35 | Scope *scope, AstNode *source_node, Buf *out_bare_name); | ||
| 36 | |||
| 37 | #endif | ||
src/stage1/bigfloat.cpp+1-2| ... | @@ -69,7 +69,7 @@ void bigfloat_init_bigint(BigFloat *dest, const BigInt *op) { | ... | @@ -69,7 +69,7 @@ void bigfloat_init_bigint(BigFloat *dest, const BigInt *op) { |
| 69 | } | 69 | } |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len) { | 72 | Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr) { |
| 73 | char *str_begin = (char *)buf_ptr; | 73 | char *str_begin = (char *)buf_ptr; |
| 74 | char *str_end; | 74 | char *str_end; |
| 75 | 75 | ||
| ... | @@ -79,7 +79,6 @@ Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len) | ... | @@ -79,7 +79,6 @@ Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len) |
| 79 | return ErrorOverflow; | 79 | return ErrorOverflow; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | assert(str_end <= ((char*)buf_ptr) + buf_len); | ||
| 83 | return ErrorNone; | 82 | return ErrorNone; |
| 84 | } | 83 | } |
| 85 | 84 |
src/stage1/bigfloat.hpp+1-1| ... | @@ -28,7 +28,7 @@ void bigfloat_init_64(BigFloat *dest, double x); | ... | @@ -28,7 +28,7 @@ void bigfloat_init_64(BigFloat *dest, double x); |
| 28 | void bigfloat_init_128(BigFloat *dest, float128_t x); | 28 | void bigfloat_init_128(BigFloat *dest, float128_t x); |
| 29 | void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x); | 29 | void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x); |
| 30 | void bigfloat_init_bigint(BigFloat *dest, const BigInt *op); | 30 | void bigfloat_init_bigint(BigFloat *dest, const BigInt *op); |
| 31 | Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr, size_t buf_len); | 31 | Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr); |
| 32 | 32 | ||
| 33 | float16_t bigfloat_to_f16(const BigFloat *bigfloat); | 33 | float16_t bigfloat_to_f16(const BigFloat *bigfloat); |
| 34 | float bigfloat_to_f32(const BigFloat *bigfloat); | 34 | float bigfloat_to_f32(const BigFloat *bigfloat); |
src/stage1/codegen.cpp+119-107| ... | @@ -6,7 +6,6 @@ | ... | @@ -6,7 +6,6 @@ |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include "analyze.hpp" | 8 | #include "analyze.hpp" |
| 9 | #include "ast_render.hpp" | ||
| 10 | #include "codegen.hpp" | 9 | #include "codegen.hpp" |
| 11 | #include "errmsg.hpp" | 10 | #include "errmsg.hpp" |
| 12 | #include "error.hpp" | 11 | #include "error.hpp" |
| ... | @@ -642,6 +641,18 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn) { | ... | @@ -642,6 +641,18 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn) { |
| 642 | return fn->llvm_value; | 641 | return fn->llvm_value; |
| 643 | } | 642 | } |
| 644 | 643 | ||
| 644 | static uint32_t node_line_onebased(AstNode *node) { | ||
| 645 | RootStruct *root_struct = node->owner->data.structure.root_struct; | ||
| 646 | assert(node->main_token < root_struct->token_count); | ||
| 647 | return root_struct->token_locs[node->main_token].line + 1; | ||
| 648 | } | ||
| 649 | |||
| 650 | static uint32_t node_column_onebased(AstNode *node) { | ||
| 651 | RootStruct *root_struct = node->owner->data.structure.root_struct; | ||
| 652 | assert(node->main_token < root_struct->token_count); | ||
| 653 | return root_struct->token_locs[node->main_token].column + 1; | ||
| 654 | } | ||
| 655 | |||
| 645 | static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { | 656 | static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { |
| 646 | if (scope->di_scope) | 657 | if (scope->di_scope) |
| 647 | return scope->di_scope; | 658 | return scope->di_scope; |
| ... | @@ -657,8 +668,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { | ... | @@ -657,8 +668,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { |
| 657 | ZigFn *fn_table_entry = fn_scope->fn_entry; | 668 | ZigFn *fn_table_entry = fn_scope->fn_entry; |
| 658 | if (!fn_table_entry->proto_node) | 669 | if (!fn_table_entry->proto_node) |
| 659 | return get_di_scope(g, scope->parent); | 670 | return get_di_scope(g, scope->parent); |
| 660 | unsigned line_number = (unsigned)(fn_table_entry->proto_node->line == 0) ? | 671 | unsigned line_number = node_line_onebased(fn_table_entry->proto_node); |
| 661 | 0 : (fn_table_entry->proto_node->line + 1); | ||
| 662 | unsigned scope_line = line_number; | 672 | unsigned scope_line = line_number; |
| 663 | bool is_definition = fn_table_entry->body_node != nullptr; | 673 | bool is_definition = fn_table_entry->body_node != nullptr; |
| 664 | bool is_optimized = g->build_mode != BuildModeDebug; | 674 | bool is_optimized = g->build_mode != BuildModeDebug; |
| ... | @@ -696,8 +706,8 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { | ... | @@ -696,8 +706,8 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { |
| 696 | ZigLLVMDILexicalBlock *di_block = ZigLLVMCreateLexicalBlock(g->dbuilder, | 706 | ZigLLVMDILexicalBlock *di_block = ZigLLVMCreateLexicalBlock(g->dbuilder, |
| 697 | get_di_scope(g, scope->parent), | 707 | get_di_scope(g, scope->parent), |
| 698 | import->data.structure.root_struct->di_file, | 708 | import->data.structure.root_struct->di_file, |
| 699 | (unsigned)scope->source_node->line + 1, | 709 | node_line_onebased(scope->source_node), |
| 700 | (unsigned)scope->source_node->column + 1); | 710 | node_column_onebased(scope->source_node)); |
| 701 | scope->di_scope = ZigLLVMLexicalBlockToScope(di_block); | 711 | scope->di_scope = ZigLLVMLexicalBlockToScope(di_block); |
| 702 | return scope->di_scope; | 712 | return scope->di_scope; |
| 703 | } | 713 | } |
| ... | @@ -1798,8 +1808,8 @@ static void gen_var_debug_decl(CodeGen *g, ZigVar *var) { | ... | @@ -1798,8 +1808,8 @@ static void gen_var_debug_decl(CodeGen *g, ZigVar *var) { |
| 1798 | if (g->strip_debug_symbols) return; | 1808 | if (g->strip_debug_symbols) return; |
| 1799 | assert(var->di_loc_var != nullptr); | 1809 | assert(var->di_loc_var != nullptr); |
| 1800 | AstNode *source_node = var->decl_node; | 1810 | AstNode *source_node = var->decl_node; |
| 1801 | ZigLLVMDILocation *debug_loc = ZigLLVMGetDebugLoc((unsigned)source_node->line + 1, | 1811 | ZigLLVMDILocation *debug_loc = ZigLLVMGetDebugLoc(node_line_onebased(source_node), |
| 1802 | (unsigned)source_node->column + 1, get_di_scope(g, var->parent_scope)); | 1812 | node_column_onebased(source_node), get_di_scope(g, var->parent_scope)); |
| 1803 | ZigLLVMInsertDeclareAtEnd(g->dbuilder, var->value_ref, var->di_loc_var, debug_loc, | 1813 | ZigLLVMInsertDeclareAtEnd(g->dbuilder, var->value_ref, var->di_loc_var, debug_loc, |
| 1804 | LLVMGetInsertBlock(g->builder)); | 1814 | LLVMGetInsertBlock(g->builder)); |
| 1805 | } | 1815 | } |
| ... | @@ -2198,7 +2208,7 @@ var_ok: | ... | @@ -2198,7 +2208,7 @@ var_ok: |
| 2198 | // arg index + 1 because the 0 index is return value | 2208 | // arg index + 1 because the 0 index is return value |
| 2199 | var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), | 2209 | var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| 2200 | var->name, fn_walk->data.vars.import->data.structure.root_struct->di_file, | 2210 | var->name, fn_walk->data.vars.import->data.structure.root_struct->di_file, |
| 2201 | (unsigned)(var->decl_node->line + 1), | 2211 | node_line_onebased(var->decl_node), |
| 2202 | get_llvm_di_type(g, dest_ty), !g->strip_debug_symbols, 0, di_arg_index + 1); | 2212 | get_llvm_di_type(g, dest_ty), !g->strip_debug_symbols, 0, di_arg_index + 1); |
| 2203 | } | 2213 | } |
| 2204 | return true; | 2214 | return true; |
| ... | @@ -2433,7 +2443,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { | ... | @@ -2433,7 +2443,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { |
| 2433 | return fn_val; | 2443 | return fn_val; |
| 2434 | 2444 | ||
| 2435 | } | 2445 | } |
| 2436 | static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutableGen *executable, | 2446 | static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, Stage1Air *executable, |
| 2437 | IrInstGenSaveErrRetAddr *save_err_ret_addr_instruction) | 2447 | IrInstGenSaveErrRetAddr *save_err_ret_addr_instruction) |
| 2438 | { | 2448 | { |
| 2439 | assert(g->have_err_ret_tracing); | 2449 | assert(g->have_err_ret_tracing); |
| ... | @@ -2626,7 +2636,7 @@ static void gen_async_return(CodeGen *g, IrInstGenReturn *instruction) { | ... | @@ -2626,7 +2636,7 @@ static void gen_async_return(CodeGen *g, IrInstGenReturn *instruction) { |
| 2626 | LLVMBuildRetVoid(g->builder); | 2636 | LLVMBuildRetVoid(g->builder); |
| 2627 | } | 2637 | } |
| 2628 | 2638 | ||
| 2629 | static LLVMValueRef ir_render_return(CodeGen *g, IrExecutableGen *executable, IrInstGenReturn *instruction) { | 2639 | static LLVMValueRef ir_render_return(CodeGen *g, Stage1Air *executable, IrInstGenReturn *instruction) { |
| 2630 | if (fn_is_async(g->cur_fn)) { | 2640 | if (fn_is_async(g->cur_fn)) { |
| 2631 | gen_async_return(g, instruction); | 2641 | gen_async_return(g, instruction); |
| 2632 | return nullptr; | 2642 | return nullptr; |
| ... | @@ -3051,7 +3061,7 @@ static void gen_shift_rhs_check(CodeGen *g, ZigType *lhs_type, ZigType *rhs_type | ... | @@ -3051,7 +3061,7 @@ static void gen_shift_rhs_check(CodeGen *g, ZigType *lhs_type, ZigType *rhs_type |
| 3051 | } | 3061 | } |
| 3052 | } | 3062 | } |
| 3053 | 3063 | ||
| 3054 | static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutableGen *executable, | 3064 | static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable, |
| 3055 | IrInstGenBinOp *bin_op_instruction) | 3065 | IrInstGenBinOp *bin_op_instruction) |
| 3056 | { | 3066 | { |
| 3057 | IrBinOp op_id = bin_op_instruction->op_id; | 3067 | IrBinOp op_id = bin_op_instruction->op_id; |
| ... | @@ -3273,7 +3283,7 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in | ... | @@ -3273,7 +3283,7 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in |
| 3273 | } | 3283 | } |
| 3274 | } | 3284 | } |
| 3275 | 3285 | ||
| 3276 | static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutableGen *executable, | 3286 | static LLVMValueRef ir_render_cast(CodeGen *g, Stage1Air *executable, |
| 3277 | IrInstGenCast *cast_instruction) | 3287 | IrInstGenCast *cast_instruction) |
| 3278 | { | 3288 | { |
| 3279 | Error err; | 3289 | Error err; |
| ... | @@ -3357,7 +3367,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutableGen *executable, | ... | @@ -3357,7 +3367,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutableGen *executable, |
| 3357 | zig_unreachable(); | 3367 | zig_unreachable(); |
| 3358 | } | 3368 | } |
| 3359 | 3369 | ||
| 3360 | static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutableGen *executable, | 3370 | static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, Stage1Air *executable, |
| 3361 | IrInstGenPtrOfArrayToSlice *instruction) | 3371 | IrInstGenPtrOfArrayToSlice *instruction) |
| 3362 | { | 3372 | { |
| 3363 | ZigType *actual_type = instruction->operand->value->type; | 3373 | ZigType *actual_type = instruction->operand->value->type; |
| ... | @@ -3394,7 +3404,7 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutableGen | ... | @@ -3394,7 +3404,7 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutableGen |
| 3394 | return result_loc; | 3404 | return result_loc; |
| 3395 | } | 3405 | } |
| 3396 | 3406 | ||
| 3397 | static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutableGen *executable, | 3407 | static LLVMValueRef ir_render_ptr_cast(CodeGen *g, Stage1Air *executable, |
| 3398 | IrInstGenPtrCast *instruction) | 3408 | IrInstGenPtrCast *instruction) |
| 3399 | { | 3409 | { |
| 3400 | ZigType *wanted_type = instruction->base.value->type; | 3410 | ZigType *wanted_type = instruction->base.value->type; |
| ... | @@ -3420,7 +3430,7 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutableGen *executable, | ... | @@ -3420,7 +3430,7 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutableGen *executable, |
| 3420 | return result_ptr; | 3430 | return result_ptr; |
| 3421 | } | 3431 | } |
| 3422 | 3432 | ||
| 3423 | static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutableGen *executable, | 3433 | static LLVMValueRef ir_render_bit_cast(CodeGen *g, Stage1Air *executable, |
| 3424 | IrInstGenBitCast *instruction) | 3434 | IrInstGenBitCast *instruction) |
| 3425 | { | 3435 | { |
| 3426 | ZigType *wanted_type = instruction->base.value->type; | 3436 | ZigType *wanted_type = instruction->base.value->type; |
| ... | @@ -3448,7 +3458,7 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutableGen *executable, | ... | @@ -3448,7 +3458,7 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutableGen *executable, |
| 3448 | } | 3458 | } |
| 3449 | } | 3459 | } |
| 3450 | 3460 | ||
| 3451 | static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutableGen *executable, | 3461 | static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, Stage1Air *executable, |
| 3452 | IrInstGenWidenOrShorten *instruction) | 3462 | IrInstGenWidenOrShorten *instruction) |
| 3453 | { | 3463 | { |
| 3454 | ZigType *actual_type = instruction->target->value->type; | 3464 | ZigType *actual_type = instruction->target->value->type; |
| ... | @@ -3465,7 +3475,7 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutableGen *exec | ... | @@ -3465,7 +3475,7 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutableGen *exec |
| 3465 | instruction->base.value->type, target_val); | 3475 | instruction->base.value->type, target_val); |
| 3466 | } | 3476 | } |
| 3467 | 3477 | ||
| 3468 | static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutableGen *executable, IrInstGenIntToPtr *instruction) { | 3478 | static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, Stage1Air *executable, IrInstGenIntToPtr *instruction) { |
| 3469 | ZigType *wanted_type = instruction->base.value->type; | 3479 | ZigType *wanted_type = instruction->base.value->type; |
| 3470 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); | 3480 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); |
| 3471 | const uint32_t align_bytes = get_ptr_align(g, wanted_type); | 3481 | const uint32_t align_bytes = get_ptr_align(g, wanted_type); |
| ... | @@ -3503,13 +3513,13 @@ static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutableGen *executable | ... | @@ -3503,13 +3513,13 @@ static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutableGen *executable |
| 3503 | return LLVMBuildIntToPtr(g->builder, target_val, get_llvm_type(g, wanted_type), ""); | 3513 | return LLVMBuildIntToPtr(g->builder, target_val, get_llvm_type(g, wanted_type), ""); |
| 3504 | } | 3514 | } |
| 3505 | 3515 | ||
| 3506 | static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutableGen *executable, IrInstGenPtrToInt *instruction) { | 3516 | static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, Stage1Air *executable, IrInstGenPtrToInt *instruction) { |
| 3507 | ZigType *wanted_type = instruction->base.value->type; | 3517 | ZigType *wanted_type = instruction->base.value->type; |
| 3508 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); | 3518 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); |
| 3509 | return LLVMBuildPtrToInt(g->builder, target_val, get_llvm_type(g, wanted_type), ""); | 3519 | return LLVMBuildPtrToInt(g->builder, target_val, get_llvm_type(g, wanted_type), ""); |
| 3510 | } | 3520 | } |
| 3511 | 3521 | ||
| 3512 | static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutableGen *executable, IrInstGenIntToEnum *instruction) { | 3522 | static LLVMValueRef ir_render_int_to_enum(CodeGen *g, Stage1Air *executable, IrInstGenIntToEnum *instruction) { |
| 3513 | ZigType *wanted_type = instruction->base.value->type; | 3523 | ZigType *wanted_type = instruction->base.value->type; |
| 3514 | assert(wanted_type->id == ZigTypeIdEnum); | 3524 | assert(wanted_type->id == ZigTypeIdEnum); |
| 3515 | ZigType *tag_int_type = wanted_type->data.enumeration.tag_int_type; | 3525 | ZigType *tag_int_type = wanted_type->data.enumeration.tag_int_type; |
| ... | @@ -3549,7 +3559,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutableGen *executabl | ... | @@ -3549,7 +3559,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutableGen *executabl |
| 3549 | return tag_int_value; | 3559 | return tag_int_value; |
| 3550 | } | 3560 | } |
| 3551 | 3561 | ||
| 3552 | static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutableGen *executable, IrInstGenIntToErr *instruction) { | 3562 | static LLVMValueRef ir_render_int_to_err(CodeGen *g, Stage1Air *executable, IrInstGenIntToErr *instruction) { |
| 3553 | ZigType *wanted_type = instruction->base.value->type; | 3563 | ZigType *wanted_type = instruction->base.value->type; |
| 3554 | assert(wanted_type->id == ZigTypeIdErrorSet); | 3564 | assert(wanted_type->id == ZigTypeIdErrorSet); |
| 3555 | 3565 | ||
| ... | @@ -3566,7 +3576,7 @@ static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutableGen *executable | ... | @@ -3566,7 +3576,7 @@ static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutableGen *executable |
| 3566 | return gen_widen_or_shorten(g, false, actual_type, g->err_tag_type, target_val); | 3576 | return gen_widen_or_shorten(g, false, actual_type, g->err_tag_type, target_val); |
| 3567 | } | 3577 | } |
| 3568 | 3578 | ||
| 3569 | static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutableGen *executable, IrInstGenErrToInt *instruction) { | 3579 | static LLVMValueRef ir_render_err_to_int(CodeGen *g, Stage1Air *executable, IrInstGenErrToInt *instruction) { |
| 3570 | ZigType *wanted_type = instruction->base.value->type; | 3580 | ZigType *wanted_type = instruction->base.value->type; |
| 3571 | assert(wanted_type->id == ZigTypeIdInt); | 3581 | assert(wanted_type->id == ZigTypeIdInt); |
| 3572 | assert(!wanted_type->data.integral.is_signed); | 3582 | assert(!wanted_type->data.integral.is_signed); |
| ... | @@ -3592,7 +3602,7 @@ static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutableGen *executable | ... | @@ -3592,7 +3602,7 @@ static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutableGen *executable |
| 3592 | } | 3602 | } |
| 3593 | } | 3603 | } |
| 3594 | 3604 | ||
| 3595 | static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutableGen *executable, | 3605 | static LLVMValueRef ir_render_unreachable(CodeGen *g, Stage1Air *executable, |
| 3596 | IrInstGenUnreachable *unreachable_instruction) | 3606 | IrInstGenUnreachable *unreachable_instruction) |
| 3597 | { | 3607 | { |
| 3598 | if (ir_want_runtime_safety(g, &unreachable_instruction->base)) { | 3608 | if (ir_want_runtime_safety(g, &unreachable_instruction->base)) { |
| ... | @@ -3603,7 +3613,7 @@ static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutableGen *executabl | ... | @@ -3603,7 +3613,7 @@ static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutableGen *executabl |
| 3603 | return nullptr; | 3613 | return nullptr; |
| 3604 | } | 3614 | } |
| 3605 | 3615 | ||
| 3606 | static LLVMValueRef ir_render_cond_br(CodeGen *g, IrExecutableGen *executable, | 3616 | static LLVMValueRef ir_render_cond_br(CodeGen *g, Stage1Air *executable, |
| 3607 | IrInstGenCondBr *cond_br_instruction) | 3617 | IrInstGenCondBr *cond_br_instruction) |
| 3608 | { | 3618 | { |
| 3609 | LLVMBuildCondBr(g->builder, | 3619 | LLVMBuildCondBr(g->builder, |
| ... | @@ -3613,12 +3623,12 @@ static LLVMValueRef ir_render_cond_br(CodeGen *g, IrExecutableGen *executable, | ... | @@ -3613,12 +3623,12 @@ static LLVMValueRef ir_render_cond_br(CodeGen *g, IrExecutableGen *executable, |
| 3613 | return nullptr; | 3623 | return nullptr; |
| 3614 | } | 3624 | } |
| 3615 | 3625 | ||
| 3616 | static LLVMValueRef ir_render_br(CodeGen *g, IrExecutableGen *executable, IrInstGenBr *br_instruction) { | 3626 | static LLVMValueRef ir_render_br(CodeGen *g, Stage1Air *executable, IrInstGenBr *br_instruction) { |
| 3617 | LLVMBuildBr(g->builder, br_instruction->dest_block->llvm_block); | 3627 | LLVMBuildBr(g->builder, br_instruction->dest_block->llvm_block); |
| 3618 | return nullptr; | 3628 | return nullptr; |
| 3619 | } | 3629 | } |
| 3620 | 3630 | ||
| 3621 | static LLVMValueRef ir_render_binary_not(CodeGen *g, IrExecutableGen *executable, | 3631 | static LLVMValueRef ir_render_binary_not(CodeGen *g, Stage1Air *executable, |
| 3622 | IrInstGenBinaryNot *inst) | 3632 | IrInstGenBinaryNot *inst) |
| 3623 | { | 3633 | { |
| 3624 | LLVMValueRef operand = ir_llvm_value(g, inst->operand); | 3634 | LLVMValueRef operand = ir_llvm_value(g, inst->operand); |
| ... | @@ -3650,13 +3660,13 @@ static LLVMValueRef ir_gen_negation(CodeGen *g, IrInstGen *inst, IrInstGen *oper | ... | @@ -3650,13 +3660,13 @@ static LLVMValueRef ir_gen_negation(CodeGen *g, IrInstGen *inst, IrInstGen *oper |
| 3650 | } | 3660 | } |
| 3651 | } | 3661 | } |
| 3652 | 3662 | ||
| 3653 | static LLVMValueRef ir_render_negation(CodeGen *g, IrExecutableGen *executable, | 3663 | static LLVMValueRef ir_render_negation(CodeGen *g, Stage1Air *executable, |
| 3654 | IrInstGenNegation *inst) | 3664 | IrInstGenNegation *inst) |
| 3655 | { | 3665 | { |
| 3656 | return ir_gen_negation(g, &inst->base, inst->operand, inst->wrapping); | 3666 | return ir_gen_negation(g, &inst->base, inst->operand, inst->wrapping); |
| 3657 | } | 3667 | } |
| 3658 | 3668 | ||
| 3659 | static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutableGen *executable, IrInstGenBoolNot *instruction) { | 3669 | static LLVMValueRef ir_render_bool_not(CodeGen *g, Stage1Air *executable, IrInstGenBoolNot *instruction) { |
| 3660 | LLVMValueRef value = ir_llvm_value(g, instruction->value); | 3670 | LLVMValueRef value = ir_llvm_value(g, instruction->value); |
| 3661 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(value)); | 3671 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(value)); |
| 3662 | return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, ""); | 3672 | return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, ""); |
| ... | @@ -3670,14 +3680,14 @@ static void render_decl_var(CodeGen *g, ZigVar *var) { | ... | @@ -3670,14 +3680,14 @@ static void render_decl_var(CodeGen *g, ZigVar *var) { |
| 3670 | gen_var_debug_decl(g, var); | 3680 | gen_var_debug_decl(g, var); |
| 3671 | } | 3681 | } |
| 3672 | 3682 | ||
| 3673 | static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutableGen *executable, IrInstGenDeclVar *instruction) { | 3683 | static LLVMValueRef ir_render_decl_var(CodeGen *g, Stage1Air *executable, IrInstGenDeclVar *instruction) { |
| 3674 | instruction->var->ptr_instruction = instruction->var_ptr; | 3684 | instruction->var->ptr_instruction = instruction->var_ptr; |
| 3675 | instruction->var->did_the_decl_codegen = true; | 3685 | instruction->var->did_the_decl_codegen = true; |
| 3676 | render_decl_var(g, instruction->var); | 3686 | render_decl_var(g, instruction->var); |
| 3677 | return nullptr; | 3687 | return nullptr; |
| 3678 | } | 3688 | } |
| 3679 | 3689 | ||
| 3680 | static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutableGen *executable, | 3690 | static LLVMValueRef ir_render_load_ptr(CodeGen *g, Stage1Air *executable, |
| 3681 | IrInstGenLoadPtr *instruction) | 3691 | IrInstGenLoadPtr *instruction) |
| 3682 | { | 3692 | { |
| 3683 | ZigType *child_type = instruction->base.value->type; | 3693 | ZigType *child_type = instruction->base.value->type; |
| ... | @@ -3879,7 +3889,7 @@ static void gen_undef_init(CodeGen *g, ZigType *ptr_type, ZigType *value_type, L | ... | @@ -3879,7 +3889,7 @@ static void gen_undef_init(CodeGen *g, ZigType *ptr_type, ZigType *value_type, L |
| 3879 | gen_assign_raw(g, ptr, ptr_type, zero); | 3889 | gen_assign_raw(g, ptr, ptr_type, zero); |
| 3880 | } | 3890 | } |
| 3881 | 3891 | ||
| 3882 | static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutableGen *executable, IrInstGenStorePtr *instruction) { | 3892 | static LLVMValueRef ir_render_store_ptr(CodeGen *g, Stage1Air *executable, IrInstGenStorePtr *instruction) { |
| 3883 | Error err; | 3893 | Error err; |
| 3884 | 3894 | ||
| 3885 | ZigType *ptr_type = instruction->ptr->value->type; | 3895 | ZigType *ptr_type = instruction->ptr->value->type; |
| ... | @@ -3911,7 +3921,7 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutableGen *executable, | ... | @@ -3911,7 +3921,7 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutableGen *executable, |
| 3911 | return nullptr; | 3921 | return nullptr; |
| 3912 | } | 3922 | } |
| 3913 | 3923 | ||
| 3914 | static LLVMValueRef ir_render_vector_store_elem(CodeGen *g, IrExecutableGen *executable, | 3924 | static LLVMValueRef ir_render_vector_store_elem(CodeGen *g, Stage1Air *executable, |
| 3915 | IrInstGenVectorStoreElem *instruction) | 3925 | IrInstGenVectorStoreElem *instruction) |
| 3916 | { | 3926 | { |
| 3917 | LLVMValueRef vector_ptr = ir_llvm_value(g, instruction->vector_ptr); | 3927 | LLVMValueRef vector_ptr = ir_llvm_value(g, instruction->vector_ptr); |
| ... | @@ -3924,7 +3934,7 @@ static LLVMValueRef ir_render_vector_store_elem(CodeGen *g, IrExecutableGen *exe | ... | @@ -3924,7 +3934,7 @@ static LLVMValueRef ir_render_vector_store_elem(CodeGen *g, IrExecutableGen *exe |
| 3924 | return nullptr; | 3934 | return nullptr; |
| 3925 | } | 3935 | } |
| 3926 | 3936 | ||
| 3927 | static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutableGen *executable, IrInstGenVarPtr *instruction) { | 3937 | static LLVMValueRef ir_render_var_ptr(CodeGen *g, Stage1Air *executable, IrInstGenVarPtr *instruction) { |
| 3928 | Error err; | 3938 | Error err; |
| 3929 | 3939 | ||
| 3930 | ZigType *ptr_type = instruction->base.value->type; | 3940 | ZigType *ptr_type = instruction->base.value->type; |
| ... | @@ -3951,7 +3961,7 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutableGen *executable, I | ... | @@ -3951,7 +3961,7 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutableGen *executable, I |
| 3951 | get_llvm_type(g, ptr_type), ""); | 3961 | get_llvm_type(g, ptr_type), ""); |
| 3952 | } | 3962 | } |
| 3953 | 3963 | ||
| 3954 | static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutableGen *executable, | 3964 | static LLVMValueRef ir_render_return_ptr(CodeGen *g, Stage1Air *executable, |
| 3955 | IrInstGenReturnPtr *instruction) | 3965 | IrInstGenReturnPtr *instruction) |
| 3956 | { | 3966 | { |
| 3957 | if (!type_has_bits(g, instruction->base.value->type)) | 3967 | if (!type_has_bits(g, instruction->base.value->type)) |
| ... | @@ -3960,7 +3970,7 @@ static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutableGen *executable | ... | @@ -3960,7 +3970,7 @@ static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutableGen *executable |
| 3960 | return g->cur_ret_ptr; | 3970 | return g->cur_ret_ptr; |
| 3961 | } | 3971 | } |
| 3962 | 3972 | ||
| 3963 | static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutableGen *executable, IrInstGenElemPtr *instruction) { | 3973 | static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, IrInstGenElemPtr *instruction) { |
| 3964 | LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr); | 3974 | LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr); |
| 3965 | ZigType *array_ptr_type = instruction->array_ptr->value->type; | 3975 | ZigType *array_ptr_type = instruction->array_ptr->value->type; |
| 3966 | assert(array_ptr_type->id == ZigTypeIdPointer); | 3976 | assert(array_ptr_type->id == ZigTypeIdPointer); |
| ... | @@ -4126,7 +4136,7 @@ static void render_async_spills(CodeGen *g) { | ... | @@ -4126,7 +4136,7 @@ static void render_async_spills(CodeGen *g) { |
| 4126 | if (var->decl_node) { | 4136 | if (var->decl_node) { |
| 4127 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), | 4137 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| 4128 | var->name, import->data.structure.root_struct->di_file, | 4138 | var->name, import->data.structure.root_struct->di_file, |
| 4129 | (unsigned)(var->decl_node->line + 1), | 4139 | node_line_onebased(var->decl_node), |
| 4130 | get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); | 4140 | get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); |
| 4131 | gen_var_debug_decl(g, var); | 4141 | gen_var_debug_decl(g, var); |
| 4132 | } | 4142 | } |
| ... | @@ -4212,7 +4222,7 @@ static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMV | ... | @@ -4212,7 +4222,7 @@ static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMV |
| 4212 | LLVMBuildStore(g->builder, LLVMConstInt(usize_type_ref, stack_trace_ptr_count, false), addrs_len_ptr); | 4222 | LLVMBuildStore(g->builder, LLVMConstInt(usize_type_ref, stack_trace_ptr_count, false), addrs_len_ptr); |
| 4213 | } | 4223 | } |
| 4214 | 4224 | ||
| 4215 | static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrInstGenCall *instruction) { | 4225 | static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, IrInstGenCall *instruction) { |
| 4216 | Error err; | 4226 | Error err; |
| 4217 | 4227 | ||
| 4218 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; | 4228 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; |
| ... | @@ -4632,7 +4642,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn | ... | @@ -4632,7 +4642,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn |
| 4632 | } | 4642 | } |
| 4633 | } | 4643 | } |
| 4634 | 4644 | ||
| 4635 | static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutableGen *executable, | 4645 | static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, Stage1Air *executable, |
| 4636 | IrInstGenStructFieldPtr *instruction) | 4646 | IrInstGenStructFieldPtr *instruction) |
| 4637 | { | 4647 | { |
| 4638 | Error err; | 4648 | Error err; |
| ... | @@ -4683,7 +4693,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutableGen *exec | ... | @@ -4683,7 +4693,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutableGen *exec |
| 4683 | return field_ptr_val; | 4693 | return field_ptr_val; |
| 4684 | } | 4694 | } |
| 4685 | 4695 | ||
| 4686 | static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutableGen *executable, | 4696 | static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, Stage1Air *executable, |
| 4687 | IrInstGenUnionFieldPtr *instruction) | 4697 | IrInstGenUnionFieldPtr *instruction) |
| 4688 | { | 4698 | { |
| 4689 | if (instruction->base.value->special != ConstValSpecialRuntime) | 4699 | if (instruction->base.value->special != ConstValSpecialRuntime) |
| ... | @@ -4783,7 +4793,7 @@ static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_ | ... | @@ -4783,7 +4793,7 @@ static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_ |
| 4783 | return SIZE_MAX; | 4793 | return SIZE_MAX; |
| 4784 | } | 4794 | } |
| 4785 | 4795 | ||
| 4786 | static LLVMValueRef ir_render_asm_gen(CodeGen *g, IrExecutableGen *executable, IrInstGenAsm *instruction) { | 4796 | static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, IrInstGenAsm *instruction) { |
| 4787 | AstNode *asm_node = instruction->base.base.source_node; | 4797 | AstNode *asm_node = instruction->base.base.source_node; |
| 4788 | assert(asm_node->type == NodeTypeAsmExpr); | 4798 | assert(asm_node->type == NodeTypeAsmExpr); |
| 4789 | AstNodeAsmExpr *asm_expr = &asm_node->data.asm_expr; | 4799 | AstNodeAsmExpr *asm_expr = &asm_node->data.asm_expr; |
| ... | @@ -4960,13 +4970,13 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR | ... | @@ -4960,13 +4970,13 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR |
| 4960 | return gen_load_untyped(g, maybe_field_ptr, 0, false, ""); | 4970 | return gen_load_untyped(g, maybe_field_ptr, 0, false, ""); |
| 4961 | } | 4971 | } |
| 4962 | 4972 | ||
| 4963 | static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutableGen *executable, | 4973 | static LLVMValueRef ir_render_test_non_null(CodeGen *g, Stage1Air *executable, |
| 4964 | IrInstGenTestNonNull *instruction) | 4974 | IrInstGenTestNonNull *instruction) |
| 4965 | { | 4975 | { |
| 4966 | return gen_non_null_bit(g, instruction->value->value->type, ir_llvm_value(g, instruction->value)); | 4976 | return gen_non_null_bit(g, instruction->value->value->type, ir_llvm_value(g, instruction->value)); |
| 4967 | } | 4977 | } |
| 4968 | 4978 | ||
| 4969 | static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutableGen *executable, | 4979 | static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, Stage1Air *executable, |
| 4970 | IrInstGenOptionalUnwrapPtr *instruction) | 4980 | IrInstGenOptionalUnwrapPtr *instruction) |
| 4971 | { | 4981 | { |
| 4972 | if (instruction->base.value->special != ConstValSpecialRuntime) | 4982 | if (instruction->base.value->special != ConstValSpecialRuntime) |
| ... | @@ -5073,7 +5083,7 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *expr_type, BuiltinFn | ... | @@ -5073,7 +5083,7 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *expr_type, BuiltinFn |
| 5073 | return fn_val; | 5083 | return fn_val; |
| 5074 | } | 5084 | } |
| 5075 | 5085 | ||
| 5076 | static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutableGen *executable, IrInstGenClz *instruction) { | 5086 | static LLVMValueRef ir_render_clz(CodeGen *g, Stage1Air *executable, IrInstGenClz *instruction) { |
| 5077 | ZigType *int_type = instruction->op->value->type; | 5087 | ZigType *int_type = instruction->op->value->type; |
| 5078 | LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdClz); | 5088 | LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdClz); |
| 5079 | LLVMValueRef operand = ir_llvm_value(g, instruction->op); | 5089 | LLVMValueRef operand = ir_llvm_value(g, instruction->op); |
| ... | @@ -5085,7 +5095,7 @@ static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutableGen *executable, IrIns | ... | @@ -5085,7 +5095,7 @@ static LLVMValueRef ir_render_clz(CodeGen *g, IrExecutableGen *executable, IrIns |
| 5085 | return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); | 5095 | return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); |
| 5086 | } | 5096 | } |
| 5087 | 5097 | ||
| 5088 | static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutableGen *executable, IrInstGenCtz *instruction) { | 5098 | static LLVMValueRef ir_render_ctz(CodeGen *g, Stage1Air *executable, IrInstGenCtz *instruction) { |
| 5089 | ZigType *int_type = instruction->op->value->type; | 5099 | ZigType *int_type = instruction->op->value->type; |
| 5090 | LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdCtz); | 5100 | LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdCtz); |
| 5091 | LLVMValueRef operand = ir_llvm_value(g, instruction->op); | 5101 | LLVMValueRef operand = ir_llvm_value(g, instruction->op); |
| ... | @@ -5097,7 +5107,7 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutableGen *executable, IrIns | ... | @@ -5097,7 +5107,7 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, IrExecutableGen *executable, IrIns |
| 5097 | return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); | 5107 | return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); |
| 5098 | } | 5108 | } |
| 5099 | 5109 | ||
| 5100 | static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutableGen *executable, IrInstGenShuffleVector *instruction) { | 5110 | static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, Stage1Air *executable, IrInstGenShuffleVector *instruction) { |
| 5101 | uint64_t len_a = instruction->a->value->type->data.vector.len; | 5111 | uint64_t len_a = instruction->a->value->type->data.vector.len; |
| 5102 | uint64_t len_mask = instruction->mask->value->type->data.vector.len; | 5112 | uint64_t len_mask = instruction->mask->value->type->data.vector.len; |
| 5103 | 5113 | ||
| ... | @@ -5127,7 +5137,7 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutableGen *execut | ... | @@ -5127,7 +5137,7 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutableGen *execut |
| 5127 | llvm_mask_value, ""); | 5137 | llvm_mask_value, ""); |
| 5128 | } | 5138 | } |
| 5129 | 5139 | ||
| 5130 | static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutableGen *executable, IrInstGenSplat *instruction) { | 5140 | static LLVMValueRef ir_render_splat(CodeGen *g, Stage1Air *executable, IrInstGenSplat *instruction) { |
| 5131 | ZigType *result_type = instruction->base.value->type; | 5141 | ZigType *result_type = instruction->base.value->type; |
| 5132 | ir_assert(result_type->id == ZigTypeIdVector, &instruction->base); | 5142 | ir_assert(result_type->id == ZigTypeIdVector, &instruction->base); |
| 5133 | uint32_t len = result_type->data.vector.len; | 5143 | uint32_t len = result_type->data.vector.len; |
| ... | @@ -5139,7 +5149,7 @@ static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutableGen *executable, IrI | ... | @@ -5139,7 +5149,7 @@ static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutableGen *executable, IrI |
| 5139 | return LLVMBuildShuffleVector(g->builder, op_vector, undef_vector, LLVMConstNull(mask_llvm_type), ""); | 5149 | return LLVMBuildShuffleVector(g->builder, op_vector, undef_vector, LLVMConstNull(mask_llvm_type), ""); |
| 5140 | } | 5150 | } |
| 5141 | 5151 | ||
| 5142 | static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutableGen *executable, IrInstGenPopCount *instruction) { | 5152 | static LLVMValueRef ir_render_pop_count(CodeGen *g, Stage1Air *executable, IrInstGenPopCount *instruction) { |
| 5143 | ZigType *int_type = instruction->op->value->type; | 5153 | ZigType *int_type = instruction->op->value->type; |
| 5144 | LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount); | 5154 | LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount); |
| 5145 | LLVMValueRef operand = ir_llvm_value(g, instruction->op); | 5155 | LLVMValueRef operand = ir_llvm_value(g, instruction->op); |
| ... | @@ -5147,7 +5157,7 @@ static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutableGen *executable, | ... | @@ -5147,7 +5157,7 @@ static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutableGen *executable, |
| 5147 | return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); | 5157 | return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); |
| 5148 | } | 5158 | } |
| 5149 | 5159 | ||
| 5150 | static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutableGen *executable, IrInstGenSwitchBr *instruction) { | 5160 | static LLVMValueRef ir_render_switch_br(CodeGen *g, Stage1Air *executable, IrInstGenSwitchBr *instruction) { |
| 5151 | ZigType *target_type = instruction->target_value->value->type; | 5161 | ZigType *target_type = instruction->target_value->value->type; |
| 5152 | LLVMBasicBlockRef else_block = instruction->else_block->llvm_block; | 5162 | LLVMBasicBlockRef else_block = instruction->else_block->llvm_block; |
| 5153 | 5163 | ||
| ... | @@ -5175,7 +5185,7 @@ static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutableGen *executable, | ... | @@ -5175,7 +5185,7 @@ static LLVMValueRef ir_render_switch_br(CodeGen *g, IrExecutableGen *executable, |
| 5175 | return nullptr; | 5185 | return nullptr; |
| 5176 | } | 5186 | } |
| 5177 | 5187 | ||
| 5178 | static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutableGen *executable, IrInstGenPhi *instruction) { | 5188 | static LLVMValueRef ir_render_phi(CodeGen *g, Stage1Air *executable, IrInstGenPhi *instruction) { |
| 5179 | if (!type_has_bits(g, instruction->base.value->type)) | 5189 | if (!type_has_bits(g, instruction->base.value->type)) |
| 5180 | return nullptr; | 5190 | return nullptr; |
| 5181 | 5191 | ||
| ... | @@ -5199,7 +5209,7 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutableGen *executable, IrIns | ... | @@ -5199,7 +5209,7 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutableGen *executable, IrIns |
| 5199 | return phi; | 5209 | return phi; |
| 5200 | } | 5210 | } |
| 5201 | 5211 | ||
| 5202 | static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutableGen *executable, IrInstGenRef *instruction) { | 5212 | static LLVMValueRef ir_render_ref(CodeGen *g, Stage1Air *executable, IrInstGenRef *instruction) { |
| 5203 | if (!type_has_bits(g, instruction->base.value->type)) { | 5213 | if (!type_has_bits(g, instruction->base.value->type)) { |
| 5204 | return nullptr; | 5214 | return nullptr; |
| 5205 | } | 5215 | } |
| ... | @@ -5219,7 +5229,7 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutableGen *executable, IrIns | ... | @@ -5219,7 +5229,7 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutableGen *executable, IrIns |
| 5219 | } | 5229 | } |
| 5220 | } | 5230 | } |
| 5221 | 5231 | ||
| 5222 | static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutableGen *executable, IrInstGenErrName *instruction) { | 5232 | static LLVMValueRef ir_render_err_name(CodeGen *g, Stage1Air *executable, IrInstGenErrName *instruction) { |
| 5223 | assert(g->generate_error_name_table); | 5233 | assert(g->generate_error_name_table); |
| 5224 | assert(g->errors_by_index.length > 0); | 5234 | assert(g->errors_by_index.length > 0); |
| 5225 | 5235 | ||
| ... | @@ -5346,7 +5356,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { | ... | @@ -5346,7 +5356,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { |
| 5346 | return fn_val; | 5356 | return fn_val; |
| 5347 | } | 5357 | } |
| 5348 | 5358 | ||
| 5349 | static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutableGen *executable, | 5359 | static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, Stage1Air *executable, |
| 5350 | IrInstGenTagName *instruction) | 5360 | IrInstGenTagName *instruction) |
| 5351 | { | 5361 | { |
| 5352 | ZigType *enum_type = instruction->target->value->type; | 5362 | ZigType *enum_type = instruction->target->value->type; |
| ... | @@ -5359,7 +5369,7 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutableGen *executa | ... | @@ -5359,7 +5369,7 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutableGen *executa |
| 5359 | get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); | 5369 | get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); |
| 5360 | } | 5370 | } |
| 5361 | 5371 | ||
| 5362 | static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutableGen *executable, | 5372 | static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, Stage1Air *executable, |
| 5363 | IrInstGenFieldParentPtr *instruction) | 5373 | IrInstGenFieldParentPtr *instruction) |
| 5364 | { | 5374 | { |
| 5365 | ZigType *container_ptr_type = instruction->base.value->type; | 5375 | ZigType *container_ptr_type = instruction->base.value->type; |
| ... | @@ -5386,7 +5396,7 @@ static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutableGen *exec | ... | @@ -5386,7 +5396,7 @@ static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutableGen *exec |
| 5386 | } | 5396 | } |
| 5387 | } | 5397 | } |
| 5388 | 5398 | ||
| 5389 | static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutableGen *executable, IrInstGenAlignCast *instruction) { | 5399 | static LLVMValueRef ir_render_align_cast(CodeGen *g, Stage1Air *executable, IrInstGenAlignCast *instruction) { |
| 5390 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); | 5400 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); |
| 5391 | assert(target_val); | 5401 | assert(target_val); |
| 5392 | 5402 | ||
| ... | @@ -5449,7 +5459,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutableGen *executable | ... | @@ -5449,7 +5459,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutableGen *executable |
| 5449 | return target_val; | 5459 | return target_val; |
| 5450 | } | 5460 | } |
| 5451 | 5461 | ||
| 5452 | static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutableGen *executable, | 5462 | static LLVMValueRef ir_render_error_return_trace(CodeGen *g, Stage1Air *executable, |
| 5453 | IrInstGenErrorReturnTrace *instruction) | 5463 | IrInstGenErrorReturnTrace *instruction) |
| 5454 | { | 5464 | { |
| 5455 | bool is_llvm_alloca; | 5465 | bool is_llvm_alloca; |
| ... | @@ -5522,7 +5532,7 @@ static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction, bool | ... | @@ -5522,7 +5532,7 @@ static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction, bool |
| 5522 | } | 5532 | } |
| 5523 | } | 5533 | } |
| 5524 | 5534 | ||
| 5525 | static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, IrInstGenCmpxchg *instruction) { | 5535 | static LLVMValueRef ir_render_cmpxchg(CodeGen *g, Stage1Air *executable, IrInstGenCmpxchg *instruction) { |
| 5526 | LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr); | 5536 | LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr); |
| 5527 | LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value); | 5537 | LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value); |
| 5528 | LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value); | 5538 | LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value); |
| ... | @@ -5584,7 +5594,7 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I | ... | @@ -5584,7 +5594,7 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutableGen *executable, I |
| 5584 | return result_loc; | 5594 | return result_loc; |
| 5585 | } | 5595 | } |
| 5586 | 5596 | ||
| 5587 | static LLVMValueRef ir_render_reduce(CodeGen *g, IrExecutableGen *executable, IrInstGenReduce *instruction) { | 5597 | static LLVMValueRef ir_render_reduce(CodeGen *g, Stage1Air *executable, IrInstGenReduce *instruction) { |
| 5588 | LLVMValueRef value = ir_llvm_value(g, instruction->value); | 5598 | LLVMValueRef value = ir_llvm_value(g, instruction->value); |
| 5589 | 5599 | ||
| 5590 | ZigType *value_type = instruction->value->value->type; | 5600 | ZigType *value_type = instruction->value->value->type; |
| ... | @@ -5648,13 +5658,13 @@ static LLVMValueRef ir_render_reduce(CodeGen *g, IrExecutableGen *executable, Ir | ... | @@ -5648,13 +5658,13 @@ static LLVMValueRef ir_render_reduce(CodeGen *g, IrExecutableGen *executable, Ir |
| 5648 | return result_val; | 5658 | return result_val; |
| 5649 | } | 5659 | } |
| 5650 | 5660 | ||
| 5651 | static LLVMValueRef ir_render_fence(CodeGen *g, IrExecutableGen *executable, IrInstGenFence *instruction) { | 5661 | static LLVMValueRef ir_render_fence(CodeGen *g, Stage1Air *executable, IrInstGenFence *instruction) { |
| 5652 | LLVMAtomicOrdering atomic_order = to_LLVMAtomicOrdering(instruction->order); | 5662 | LLVMAtomicOrdering atomic_order = to_LLVMAtomicOrdering(instruction->order); |
| 5653 | LLVMBuildFence(g->builder, atomic_order, false, ""); | 5663 | LLVMBuildFence(g->builder, atomic_order, false, ""); |
| 5654 | return nullptr; | 5664 | return nullptr; |
| 5655 | } | 5665 | } |
| 5656 | 5666 | ||
| 5657 | static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutableGen *executable, IrInstGenTruncate *instruction) { | 5667 | static LLVMValueRef ir_render_truncate(CodeGen *g, Stage1Air *executable, IrInstGenTruncate *instruction) { |
| 5658 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); | 5668 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); |
| 5659 | ZigType *dest_type = instruction->base.value->type; | 5669 | ZigType *dest_type = instruction->base.value->type; |
| 5660 | ZigType *src_type = instruction->target->value->type; | 5670 | ZigType *src_type = instruction->target->value->type; |
| ... | @@ -5669,7 +5679,7 @@ static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutableGen *executable, | ... | @@ -5669,7 +5679,7 @@ static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutableGen *executable, |
| 5669 | } | 5679 | } |
| 5670 | } | 5680 | } |
| 5671 | 5681 | ||
| 5672 | static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutableGen *executable, IrInstGenMemset *instruction) { | 5682 | static LLVMValueRef ir_render_memset(CodeGen *g, Stage1Air *executable, IrInstGenMemset *instruction) { |
| 5673 | LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr); | 5683 | LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr); |
| 5674 | LLVMValueRef len_val = ir_llvm_value(g, instruction->count); | 5684 | LLVMValueRef len_val = ir_llvm_value(g, instruction->count); |
| 5675 | 5685 | ||
| ... | @@ -5699,7 +5709,7 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutableGen *executable, Ir | ... | @@ -5699,7 +5709,7 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutableGen *executable, Ir |
| 5699 | return nullptr; | 5709 | return nullptr; |
| 5700 | } | 5710 | } |
| 5701 | 5711 | ||
| 5702 | static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutableGen *executable, IrInstGenMemcpy *instruction) { | 5712 | static LLVMValueRef ir_render_memcpy(CodeGen *g, Stage1Air *executable, IrInstGenMemcpy *instruction) { |
| 5703 | LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr); | 5713 | LLVMValueRef dest_ptr = ir_llvm_value(g, instruction->dest_ptr); |
| 5704 | LLVMValueRef src_ptr = ir_llvm_value(g, instruction->src_ptr); | 5714 | LLVMValueRef src_ptr = ir_llvm_value(g, instruction->src_ptr); |
| 5705 | LLVMValueRef len_val = ir_llvm_value(g, instruction->count); | 5715 | LLVMValueRef len_val = ir_llvm_value(g, instruction->count); |
| ... | @@ -5721,14 +5731,14 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutableGen *executable, Ir | ... | @@ -5721,14 +5731,14 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutableGen *executable, Ir |
| 5721 | return nullptr; | 5731 | return nullptr; |
| 5722 | } | 5732 | } |
| 5723 | 5733 | ||
| 5724 | static LLVMValueRef ir_render_wasm_memory_size(CodeGen *g, IrExecutableGen *executable, IrInstGenWasmMemorySize *instruction) { | 5734 | static LLVMValueRef ir_render_wasm_memory_size(CodeGen *g, Stage1Air *executable, IrInstGenWasmMemorySize *instruction) { |
| 5725 | // TODO adjust for wasm64 | 5735 | // TODO adjust for wasm64 |
| 5726 | LLVMValueRef param = ir_llvm_value(g, instruction->index); | 5736 | LLVMValueRef param = ir_llvm_value(g, instruction->index); |
| 5727 | LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_size(g), &param, 1, ""); | 5737 | LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_size(g), &param, 1, ""); |
| 5728 | return val; | 5738 | return val; |
| 5729 | } | 5739 | } |
| 5730 | 5740 | ||
| 5731 | static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, IrExecutableGen *executable, IrInstGenWasmMemoryGrow *instruction) { | 5741 | static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, Stage1Air *executable, IrInstGenWasmMemoryGrow *instruction) { |
| 5732 | // TODO adjust for wasm64 | 5742 | // TODO adjust for wasm64 |
| 5733 | LLVMValueRef params[] = { | 5743 | LLVMValueRef params[] = { |
| 5734 | ir_llvm_value(g, instruction->index), | 5744 | ir_llvm_value(g, instruction->index), |
| ... | @@ -5738,7 +5748,7 @@ static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, IrExecutableGen *exec | ... | @@ -5738,7 +5748,7 @@ static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, IrExecutableGen *exec |
| 5738 | return val; | 5748 | return val; |
| 5739 | } | 5749 | } |
| 5740 | 5750 | ||
| 5741 | static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrInstGenSlice *instruction) { | 5751 | static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, IrInstGenSlice *instruction) { |
| 5742 | Error err; | 5752 | Error err; |
| 5743 | 5753 | ||
| 5744 | LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr); | 5754 | LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr); |
| ... | @@ -5975,12 +5985,12 @@ static LLVMValueRef get_trap_fn_val(CodeGen *g) { | ... | @@ -5975,12 +5985,12 @@ static LLVMValueRef get_trap_fn_val(CodeGen *g) { |
| 5975 | } | 5985 | } |
| 5976 | 5986 | ||
| 5977 | 5987 | ||
| 5978 | static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutableGen *executable, IrInstGenBreakpoint *instruction) { | 5988 | static LLVMValueRef ir_render_breakpoint(CodeGen *g, Stage1Air *executable, IrInstGenBreakpoint *instruction) { |
| 5979 | LLVMBuildCall(g->builder, get_trap_fn_val(g), nullptr, 0, ""); | 5989 | LLVMBuildCall(g->builder, get_trap_fn_val(g), nullptr, 0, ""); |
| 5980 | return nullptr; | 5990 | return nullptr; |
| 5981 | } | 5991 | } |
| 5982 | 5992 | ||
| 5983 | static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutableGen *executable, | 5993 | static LLVMValueRef ir_render_return_address(CodeGen *g, Stage1Air *executable, |
| 5984 | IrInstGenReturnAddress *instruction) | 5994 | IrInstGenReturnAddress *instruction) |
| 5985 | { | 5995 | { |
| 5986 | if (target_is_wasm(g->zig_target) && g->zig_target->os != OsEmscripten) { | 5996 | if (target_is_wasm(g->zig_target) && g->zig_target->os != OsEmscripten) { |
| ... | @@ -6008,7 +6018,7 @@ static LLVMValueRef get_frame_address_fn_val(CodeGen *g) { | ... | @@ -6008,7 +6018,7 @@ static LLVMValueRef get_frame_address_fn_val(CodeGen *g) { |
| 6008 | return g->frame_address_fn_val; | 6018 | return g->frame_address_fn_val; |
| 6009 | } | 6019 | } |
| 6010 | 6020 | ||
| 6011 | static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutableGen *executable, | 6021 | static LLVMValueRef ir_render_frame_address(CodeGen *g, Stage1Air *executable, |
| 6012 | IrInstGenFrameAddress *instruction) | 6022 | IrInstGenFrameAddress *instruction) |
| 6013 | { | 6023 | { |
| 6014 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); | 6024 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); |
| ... | @@ -6016,7 +6026,7 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutableGen *executa | ... | @@ -6016,7 +6026,7 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutableGen *executa |
| 6016 | return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); | 6026 | return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); |
| 6017 | } | 6027 | } |
| 6018 | 6028 | ||
| 6019 | static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutableGen *executable, IrInstGenFrameHandle *instruction) { | 6029 | static LLVMValueRef ir_render_handle(CodeGen *g, Stage1Air *executable, IrInstGenFrameHandle *instruction) { |
| 6020 | return g->cur_frame_ptr; | 6030 | return g->cur_frame_ptr; |
| 6021 | } | 6031 | } |
| 6022 | 6032 | ||
| ... | @@ -6045,7 +6055,7 @@ static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstGenOverflowOp *in | ... | @@ -6045,7 +6055,7 @@ static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstGenOverflowOp *in |
| 6045 | return overflow_bit; | 6055 | return overflow_bit; |
| 6046 | } | 6056 | } |
| 6047 | 6057 | ||
| 6048 | static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutableGen *executable, IrInstGenOverflowOp *instruction) { | 6058 | static LLVMValueRef ir_render_overflow_op(CodeGen *g, Stage1Air *executable, IrInstGenOverflowOp *instruction) { |
| 6049 | AddSubMul add_sub_mul; | 6059 | AddSubMul add_sub_mul; |
| 6050 | switch (instruction->op) { | 6060 | switch (instruction->op) { |
| 6051 | case IrOverflowOpAdd: | 6061 | case IrOverflowOpAdd: |
| ... | @@ -6083,7 +6093,7 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutableGen *executabl | ... | @@ -6083,7 +6093,7 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutableGen *executabl |
| 6083 | return overflow_bit; | 6093 | return overflow_bit; |
| 6084 | } | 6094 | } |
| 6085 | 6095 | ||
| 6086 | static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutableGen *executable, IrInstGenTestErr *instruction) { | 6096 | static LLVMValueRef ir_render_test_err(CodeGen *g, Stage1Air *executable, IrInstGenTestErr *instruction) { |
| 6087 | ZigType *err_union_type = instruction->err_union->value->type; | 6097 | ZigType *err_union_type = instruction->err_union->value->type; |
| 6088 | ZigType *payload_type = err_union_type->data.error_union.payload_type; | 6098 | ZigType *payload_type = err_union_type->data.error_union.payload_type; |
| 6089 | LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->err_union); | 6099 | LLVMValueRef err_union_handle = ir_llvm_value(g, instruction->err_union); |
| ... | @@ -6100,7 +6110,7 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutableGen *executable, | ... | @@ -6100,7 +6110,7 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutableGen *executable, |
| 6100 | return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, ""); | 6110 | return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, ""); |
| 6101 | } | 6111 | } |
| 6102 | 6112 | ||
| 6103 | static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutableGen *executable, | 6113 | static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, Stage1Air *executable, |
| 6104 | IrInstGenUnwrapErrCode *instruction) | 6114 | IrInstGenUnwrapErrCode *instruction) |
| 6105 | { | 6115 | { |
| 6106 | if (instruction->base.value->special != ConstValSpecialRuntime) | 6116 | if (instruction->base.value->special != ConstValSpecialRuntime) |
| ... | @@ -6120,7 +6130,7 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutableGen *execu | ... | @@ -6120,7 +6130,7 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutableGen *execu |
| 6120 | } | 6130 | } |
| 6121 | } | 6131 | } |
| 6122 | 6132 | ||
| 6123 | static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutableGen *executable, | 6133 | static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, Stage1Air *executable, |
| 6124 | IrInstGenUnwrapErrPayload *instruction) | 6134 | IrInstGenUnwrapErrPayload *instruction) |
| 6125 | { | 6135 | { |
| 6126 | Error err; | 6136 | Error err; |
| ... | @@ -6189,7 +6199,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutableGen *ex | ... | @@ -6189,7 +6199,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutableGen *ex |
| 6189 | } | 6199 | } |
| 6190 | } | 6200 | } |
| 6191 | 6201 | ||
| 6192 | static LLVMValueRef ir_render_optional_wrap(CodeGen *g, IrExecutableGen *executable, IrInstGenOptionalWrap *instruction) { | 6202 | static LLVMValueRef ir_render_optional_wrap(CodeGen *g, Stage1Air *executable, IrInstGenOptionalWrap *instruction) { |
| 6193 | ZigType *wanted_type = instruction->base.value->type; | 6203 | ZigType *wanted_type = instruction->base.value->type; |
| 6194 | 6204 | ||
| 6195 | assert(wanted_type->id == ZigTypeIdOptional); | 6205 | assert(wanted_type->id == ZigTypeIdOptional); |
| ... | @@ -6225,7 +6235,7 @@ static LLVMValueRef ir_render_optional_wrap(CodeGen *g, IrExecutableGen *executa | ... | @@ -6225,7 +6235,7 @@ static LLVMValueRef ir_render_optional_wrap(CodeGen *g, IrExecutableGen *executa |
| 6225 | return result_loc; | 6235 | return result_loc; |
| 6226 | } | 6236 | } |
| 6227 | 6237 | ||
| 6228 | static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutableGen *executable, IrInstGenErrWrapCode *instruction) { | 6238 | static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, Stage1Air *executable, IrInstGenErrWrapCode *instruction) { |
| 6229 | ZigType *wanted_type = instruction->base.value->type; | 6239 | ZigType *wanted_type = instruction->base.value->type; |
| 6230 | 6240 | ||
| 6231 | assert(wanted_type->id == ZigTypeIdErrorUnion); | 6241 | assert(wanted_type->id == ZigTypeIdErrorUnion); |
| ... | @@ -6245,7 +6255,7 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutableGen *executa | ... | @@ -6245,7 +6255,7 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, IrExecutableGen *executa |
| 6245 | return result_loc; | 6255 | return result_loc; |
| 6246 | } | 6256 | } |
| 6247 | 6257 | ||
| 6248 | static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutableGen *executable, IrInstGenErrWrapPayload *instruction) { | 6258 | static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, Stage1Air *executable, IrInstGenErrWrapPayload *instruction) { |
| 6249 | ZigType *wanted_type = instruction->base.value->type; | 6259 | ZigType *wanted_type = instruction->base.value->type; |
| 6250 | 6260 | ||
| 6251 | assert(wanted_type->id == ZigTypeIdErrorUnion); | 6261 | assert(wanted_type->id == ZigTypeIdErrorUnion); |
| ... | @@ -6276,7 +6286,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutableGen *exec | ... | @@ -6276,7 +6286,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutableGen *exec |
| 6276 | return result_loc; | 6286 | return result_loc; |
| 6277 | } | 6287 | } |
| 6278 | 6288 | ||
| 6279 | static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutableGen *executable, IrInstGenUnionTag *instruction) { | 6289 | static LLVMValueRef ir_render_union_tag(CodeGen *g, Stage1Air *executable, IrInstGenUnionTag *instruction) { |
| 6280 | ZigType *union_type = instruction->value->value->type; | 6290 | ZigType *union_type = instruction->value->value->type; |
| 6281 | 6291 | ||
| 6282 | ZigType *tag_type = union_type->data.unionation.tag_type; | 6292 | ZigType *tag_type = union_type->data.unionation.tag_type; |
| ... | @@ -6294,14 +6304,14 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutableGen *executable, | ... | @@ -6294,14 +6304,14 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutableGen *executable, |
| 6294 | return get_handle_value(g, tag_field_ptr, tag_type, ptr_type); | 6304 | return get_handle_value(g, tag_field_ptr, tag_type, ptr_type); |
| 6295 | } | 6305 | } |
| 6296 | 6306 | ||
| 6297 | static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutableGen *executable, IrInstGenPanic *instruction) { | 6307 | static LLVMValueRef ir_render_panic(CodeGen *g, Stage1Air *executable, IrInstGenPanic *instruction) { |
| 6298 | bool is_llvm_alloca; | 6308 | bool is_llvm_alloca; |
| 6299 | LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.base.scope, &is_llvm_alloca); | 6309 | LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.base.scope, &is_llvm_alloca); |
| 6300 | gen_panic(g, ir_llvm_value(g, instruction->msg), err_ret_trace_val, is_llvm_alloca); | 6310 | gen_panic(g, ir_llvm_value(g, instruction->msg), err_ret_trace_val, is_llvm_alloca); |
| 6301 | return nullptr; | 6311 | return nullptr; |
| 6302 | } | 6312 | } |
| 6303 | 6313 | ||
| 6304 | static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable, | 6314 | static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, Stage1Air *executable, |
| 6305 | IrInstGenAtomicRmw *instruction) | 6315 | IrInstGenAtomicRmw *instruction) |
| 6306 | { | 6316 | { |
| 6307 | bool is_signed; | 6317 | bool is_signed; |
| ... | @@ -6353,7 +6363,7 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable | ... | @@ -6353,7 +6363,7 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutableGen *executable |
| 6353 | return LLVMBuildIntToPtr(g->builder, uncasted_result, get_llvm_type(g, operand_type), ""); | 6363 | return LLVMBuildIntToPtr(g->builder, uncasted_result, get_llvm_type(g, operand_type), ""); |
| 6354 | } | 6364 | } |
| 6355 | 6365 | ||
| 6356 | static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutableGen *executable, | 6366 | static LLVMValueRef ir_render_atomic_load(CodeGen *g, Stage1Air *executable, |
| 6357 | IrInstGenAtomicLoad *instruction) | 6367 | IrInstGenAtomicLoad *instruction) |
| 6358 | { | 6368 | { |
| 6359 | LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering); | 6369 | LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering); |
| ... | @@ -6374,7 +6384,7 @@ static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutableGen *executabl | ... | @@ -6374,7 +6384,7 @@ static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutableGen *executabl |
| 6374 | return load_inst; | 6384 | return load_inst; |
| 6375 | } | 6385 | } |
| 6376 | 6386 | ||
| 6377 | static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executable, | 6387 | static LLVMValueRef ir_render_atomic_store(CodeGen *g, Stage1Air *executable, |
| 6378 | IrInstGenAtomicStore *instruction) | 6388 | IrInstGenAtomicStore *instruction) |
| 6379 | { | 6389 | { |
| 6380 | LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering); | 6390 | LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->ordering); |
| ... | @@ -6397,13 +6407,13 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executab | ... | @@ -6397,13 +6407,13 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutableGen *executab |
| 6397 | return nullptr; | 6407 | return nullptr; |
| 6398 | } | 6408 | } |
| 6399 | 6409 | ||
| 6400 | static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutableGen *executable, IrInstGenFloatOp *instruction) { | 6410 | static LLVMValueRef ir_render_float_op(CodeGen *g, Stage1Air *executable, IrInstGenFloatOp *instruction) { |
| 6401 | LLVMValueRef operand = ir_llvm_value(g, instruction->operand); | 6411 | LLVMValueRef operand = ir_llvm_value(g, instruction->operand); |
| 6402 | LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFloatOp, instruction->fn_id); | 6412 | LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFloatOp, instruction->fn_id); |
| 6403 | return LLVMBuildCall(g->builder, fn_val, &operand, 1, ""); | 6413 | return LLVMBuildCall(g->builder, fn_val, &operand, 1, ""); |
| 6404 | } | 6414 | } |
| 6405 | 6415 | ||
| 6406 | static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutableGen *executable, IrInstGenMulAdd *instruction) { | 6416 | static LLVMValueRef ir_render_mul_add(CodeGen *g, Stage1Air *executable, IrInstGenMulAdd *instruction) { |
| 6407 | LLVMValueRef op1 = ir_llvm_value(g, instruction->op1); | 6417 | LLVMValueRef op1 = ir_llvm_value(g, instruction->op1); |
| 6408 | LLVMValueRef op2 = ir_llvm_value(g, instruction->op2); | 6418 | LLVMValueRef op2 = ir_llvm_value(g, instruction->op2); |
| 6409 | LLVMValueRef op3 = ir_llvm_value(g, instruction->op3); | 6419 | LLVMValueRef op3 = ir_llvm_value(g, instruction->op3); |
| ... | @@ -6418,7 +6428,7 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutableGen *executable, I | ... | @@ -6418,7 +6428,7 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, IrExecutableGen *executable, I |
| 6418 | return LLVMBuildCall(g->builder, fn_val, args, 3, ""); | 6428 | return LLVMBuildCall(g->builder, fn_val, args, 3, ""); |
| 6419 | } | 6429 | } |
| 6420 | 6430 | ||
| 6421 | static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutableGen *executable, IrInstGenBswap *instruction) { | 6431 | static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, IrInstGenBswap *instruction) { |
| 6422 | LLVMValueRef op = ir_llvm_value(g, instruction->op); | 6432 | LLVMValueRef op = ir_llvm_value(g, instruction->op); |
| 6423 | ZigType *expr_type = instruction->base.value->type; | 6433 | ZigType *expr_type = instruction->base.value->type; |
| 6424 | bool is_vector = expr_type->id == ZigTypeIdVector; | 6434 | bool is_vector = expr_type->id == ZigTypeIdVector; |
| ... | @@ -6452,7 +6462,7 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutableGen *executable, IrI | ... | @@ -6452,7 +6462,7 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutableGen *executable, IrI |
| 6452 | return LLVMBuildTrunc(g->builder, shifted, get_llvm_type(g, expr_type), ""); | 6462 | return LLVMBuildTrunc(g->builder, shifted, get_llvm_type(g, expr_type), ""); |
| 6453 | } | 6463 | } |
| 6454 | 6464 | ||
| 6455 | static LLVMValueRef ir_render_extern(CodeGen *g, IrExecutableGen *executable, | 6465 | static LLVMValueRef ir_render_extern(CodeGen *g, Stage1Air *executable, |
| 6456 | IrInstGenExtern *instruction) | 6466 | IrInstGenExtern *instruction) |
| 6457 | { | 6467 | { |
| 6458 | ZigType *expr_type = instruction->base.value->type; | 6468 | ZigType *expr_type = instruction->base.value->type; |
| ... | @@ -6476,7 +6486,7 @@ static LLVMValueRef ir_render_extern(CodeGen *g, IrExecutableGen *executable, | ... | @@ -6476,7 +6486,7 @@ static LLVMValueRef ir_render_extern(CodeGen *g, IrExecutableGen *executable, |
| 6476 | return LLVMBuildBitCast(g->builder, global_value, get_llvm_type(g, expr_type), ""); | 6486 | return LLVMBuildBitCast(g->builder, global_value, get_llvm_type(g, expr_type), ""); |
| 6477 | } | 6487 | } |
| 6478 | 6488 | ||
| 6479 | static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutableGen *executable, IrInstGenBitReverse *instruction) { | 6489 | static LLVMValueRef ir_render_bit_reverse(CodeGen *g, Stage1Air *executable, IrInstGenBitReverse *instruction) { |
| 6480 | LLVMValueRef op = ir_llvm_value(g, instruction->op); | 6490 | LLVMValueRef op = ir_llvm_value(g, instruction->op); |
| 6481 | ZigType *int_type = instruction->base.value->type; | 6491 | ZigType *int_type = instruction->base.value->type; |
| 6482 | assert(int_type->id == ZigTypeIdInt); | 6492 | assert(int_type->id == ZigTypeIdInt); |
| ... | @@ -6484,7 +6494,7 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutableGen *executabl | ... | @@ -6484,7 +6494,7 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutableGen *executabl |
| 6484 | return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); | 6494 | return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); |
| 6485 | } | 6495 | } |
| 6486 | 6496 | ||
| 6487 | static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutableGen *executable, | 6497 | static LLVMValueRef ir_render_vector_to_array(CodeGen *g, Stage1Air *executable, |
| 6488 | IrInstGenVectorToArray *instruction) | 6498 | IrInstGenVectorToArray *instruction) |
| 6489 | { | 6499 | { |
| 6490 | ZigType *array_type = instruction->base.value->type; | 6500 | ZigType *array_type = instruction->base.value->type; |
| ... | @@ -6518,7 +6528,7 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutableGen *execu | ... | @@ -6518,7 +6528,7 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutableGen *execu |
| 6518 | return result_loc; | 6528 | return result_loc; |
| 6519 | } | 6529 | } |
| 6520 | 6530 | ||
| 6521 | static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutableGen *executable, | 6531 | static LLVMValueRef ir_render_array_to_vector(CodeGen *g, Stage1Air *executable, |
| 6522 | IrInstGenArrayToVector *instruction) | 6532 | IrInstGenArrayToVector *instruction) |
| 6523 | { | 6533 | { |
| 6524 | ZigType *vector_type = instruction->base.value->type; | 6534 | ZigType *vector_type = instruction->base.value->type; |
| ... | @@ -6555,7 +6565,7 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutableGen *execu | ... | @@ -6555,7 +6565,7 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutableGen *execu |
| 6555 | } | 6565 | } |
| 6556 | } | 6566 | } |
| 6557 | 6567 | ||
| 6558 | static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutableGen *executable, | 6568 | static LLVMValueRef ir_render_assert_zero(CodeGen *g, Stage1Air *executable, |
| 6559 | IrInstGenAssertZero *instruction) | 6569 | IrInstGenAssertZero *instruction) |
| 6560 | { | 6570 | { |
| 6561 | LLVMValueRef target = ir_llvm_value(g, instruction->target); | 6571 | LLVMValueRef target = ir_llvm_value(g, instruction->target); |
| ... | @@ -6566,7 +6576,7 @@ static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutableGen *executabl | ... | @@ -6566,7 +6576,7 @@ static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutableGen *executabl |
| 6566 | return nullptr; | 6576 | return nullptr; |
| 6567 | } | 6577 | } |
| 6568 | 6578 | ||
| 6569 | static LLVMValueRef ir_render_assert_non_null(CodeGen *g, IrExecutableGen *executable, | 6579 | static LLVMValueRef ir_render_assert_non_null(CodeGen *g, Stage1Air *executable, |
| 6570 | IrInstGenAssertNonNull *instruction) | 6580 | IrInstGenAssertNonNull *instruction) |
| 6571 | { | 6581 | { |
| 6572 | LLVMValueRef target = ir_llvm_value(g, instruction->target); | 6582 | LLVMValueRef target = ir_llvm_value(g, instruction->target); |
| ... | @@ -6591,7 +6601,7 @@ static LLVMValueRef ir_render_assert_non_null(CodeGen *g, IrExecutableGen *execu | ... | @@ -6591,7 +6601,7 @@ static LLVMValueRef ir_render_assert_non_null(CodeGen *g, IrExecutableGen *execu |
| 6591 | return nullptr; | 6601 | return nullptr; |
| 6592 | } | 6602 | } |
| 6593 | 6603 | ||
| 6594 | static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutableGen *executable, | 6604 | static LLVMValueRef ir_render_suspend_begin(CodeGen *g, Stage1Air *executable, |
| 6595 | IrInstGenSuspendBegin *instruction) | 6605 | IrInstGenSuspendBegin *instruction) |
| 6596 | { | 6606 | { |
| 6597 | if (fn_is_async(g->cur_fn)) { | 6607 | if (fn_is_async(g->cur_fn)) { |
| ... | @@ -6600,7 +6610,7 @@ static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutableGen *executa | ... | @@ -6600,7 +6610,7 @@ static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutableGen *executa |
| 6600 | return nullptr; | 6610 | return nullptr; |
| 6601 | } | 6611 | } |
| 6602 | 6612 | ||
| 6603 | static LLVMValueRef ir_render_suspend_finish(CodeGen *g, IrExecutableGen *executable, | 6613 | static LLVMValueRef ir_render_suspend_finish(CodeGen *g, Stage1Air *executable, |
| 6604 | IrInstGenSuspendFinish *instruction) | 6614 | IrInstGenSuspendFinish *instruction) |
| 6605 | { | 6615 | { |
| 6606 | LLVMBuildRetVoid(g->builder); | 6616 | LLVMBuildRetVoid(g->builder); |
| ... | @@ -6652,7 +6662,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstGen *source_instr, | ... | @@ -6652,7 +6662,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstGen *source_instr, |
| 6652 | } | 6662 | } |
| 6653 | } | 6663 | } |
| 6654 | 6664 | ||
| 6655 | static LLVMValueRef ir_render_await(CodeGen *g, IrExecutableGen *executable, IrInstGenAwait *instruction) { | 6665 | static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, IrInstGenAwait *instruction) { |
| 6656 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; | 6666 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; |
| 6657 | LLVMValueRef zero = LLVMConstNull(usize_type_ref); | 6667 | LLVMValueRef zero = LLVMConstNull(usize_type_ref); |
| 6658 | LLVMValueRef target_frame_ptr = ir_llvm_value(g, instruction->frame); | 6668 | LLVMValueRef target_frame_ptr = ir_llvm_value(g, instruction->frame); |
| ... | @@ -6739,7 +6749,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutableGen *executable, IrI | ... | @@ -6739,7 +6749,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutableGen *executable, IrI |
| 6739 | return nullptr; | 6749 | return nullptr; |
| 6740 | } | 6750 | } |
| 6741 | 6751 | ||
| 6742 | static LLVMValueRef ir_render_resume(CodeGen *g, IrExecutableGen *executable, IrInstGenResume *instruction) { | 6752 | static LLVMValueRef ir_render_resume(CodeGen *g, Stage1Air *executable, IrInstGenResume *instruction) { |
| 6743 | LLVMValueRef frame = ir_llvm_value(g, instruction->frame); | 6753 | LLVMValueRef frame = ir_llvm_value(g, instruction->frame); |
| 6744 | ZigType *frame_type = instruction->frame->value->type; | 6754 | ZigType *frame_type = instruction->frame->value->type; |
| 6745 | assert(frame_type->id == ZigTypeIdAnyFrame); | 6755 | assert(frame_type->id == ZigTypeIdAnyFrame); |
| ... | @@ -6748,14 +6758,14 @@ static LLVMValueRef ir_render_resume(CodeGen *g, IrExecutableGen *executable, Ir | ... | @@ -6748,14 +6758,14 @@ static LLVMValueRef ir_render_resume(CodeGen *g, IrExecutableGen *executable, Ir |
| 6748 | return nullptr; | 6758 | return nullptr; |
| 6749 | } | 6759 | } |
| 6750 | 6760 | ||
| 6751 | static LLVMValueRef ir_render_frame_size(CodeGen *g, IrExecutableGen *executable, | 6761 | static LLVMValueRef ir_render_frame_size(CodeGen *g, Stage1Air *executable, |
| 6752 | IrInstGenFrameSize *instruction) | 6762 | IrInstGenFrameSize *instruction) |
| 6753 | { | 6763 | { |
| 6754 | LLVMValueRef fn_val = ir_llvm_value(g, instruction->fn); | 6764 | LLVMValueRef fn_val = ir_llvm_value(g, instruction->fn); |
| 6755 | return gen_frame_size(g, fn_val); | 6765 | return gen_frame_size(g, fn_val); |
| 6756 | } | 6766 | } |
| 6757 | 6767 | ||
| 6758 | static LLVMValueRef ir_render_spill_begin(CodeGen *g, IrExecutableGen *executable, | 6768 | static LLVMValueRef ir_render_spill_begin(CodeGen *g, Stage1Air *executable, |
| 6759 | IrInstGenSpillBegin *instruction) | 6769 | IrInstGenSpillBegin *instruction) |
| 6760 | { | 6770 | { |
| 6761 | if (!fn_is_async(g->cur_fn)) | 6771 | if (!fn_is_async(g->cur_fn)) |
| ... | @@ -6775,7 +6785,7 @@ static LLVMValueRef ir_render_spill_begin(CodeGen *g, IrExecutableGen *executabl | ... | @@ -6775,7 +6785,7 @@ static LLVMValueRef ir_render_spill_begin(CodeGen *g, IrExecutableGen *executabl |
| 6775 | zig_unreachable(); | 6785 | zig_unreachable(); |
| 6776 | } | 6786 | } |
| 6777 | 6787 | ||
| 6778 | static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutableGen *executable, IrInstGenSpillEnd *instruction) { | 6788 | static LLVMValueRef ir_render_spill_end(CodeGen *g, Stage1Air *executable, IrInstGenSpillEnd *instruction) { |
| 6779 | if (!fn_is_async(g->cur_fn)) | 6789 | if (!fn_is_async(g->cur_fn)) |
| 6780 | return ir_llvm_value(g, instruction->begin->operand); | 6790 | return ir_llvm_value(g, instruction->begin->operand); |
| 6781 | 6791 | ||
| ... | @@ -6791,7 +6801,7 @@ static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutableGen *executable, | ... | @@ -6791,7 +6801,7 @@ static LLVMValueRef ir_render_spill_end(CodeGen *g, IrExecutableGen *executable, |
| 6791 | zig_unreachable(); | 6801 | zig_unreachable(); |
| 6792 | } | 6802 | } |
| 6793 | 6803 | ||
| 6794 | static LLVMValueRef ir_render_vector_extract_elem(CodeGen *g, IrExecutableGen *executable, | 6804 | static LLVMValueRef ir_render_vector_extract_elem(CodeGen *g, Stage1Air *executable, |
| 6795 | IrInstGenVectorExtractElem *instruction) | 6805 | IrInstGenVectorExtractElem *instruction) |
| 6796 | { | 6806 | { |
| 6797 | LLVMValueRef vector = ir_llvm_value(g, instruction->vector); | 6807 | LLVMValueRef vector = ir_llvm_value(g, instruction->vector); |
| ... | @@ -6806,11 +6816,11 @@ static void set_debug_location(CodeGen *g, IrInstGen *instruction) { | ... | @@ -6806,11 +6816,11 @@ static void set_debug_location(CodeGen *g, IrInstGen *instruction) { |
| 6806 | assert(source_node); | 6816 | assert(source_node); |
| 6807 | assert(scope); | 6817 | assert(scope); |
| 6808 | 6818 | ||
| 6809 | ZigLLVMSetCurrentDebugLocation(g->builder, (int)source_node->line + 1, | 6819 | ZigLLVMSetCurrentDebugLocation(g->builder, node_line_onebased(source_node), |
| 6810 | (int)source_node->column + 1, get_di_scope(g, scope)); | 6820 | node_column_onebased(source_node), get_di_scope(g, scope)); |
| 6811 | } | 6821 | } |
| 6812 | 6822 | ||
| 6813 | static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executable, IrInstGen *instruction) { | 6823 | static LLVMValueRef ir_render_instruction(CodeGen *g, Stage1Air *executable, IrInstGen *instruction) { |
| 6814 | switch (instruction->id) { | 6824 | switch (instruction->id) { |
| 6815 | case IrInstGenIdInvalid: | 6825 | case IrInstGenIdInvalid: |
| 6816 | case IrInstGenIdConst: | 6826 | case IrInstGenIdConst: |
| ... | @@ -6998,7 +7008,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executabl | ... | @@ -6998,7 +7008,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executabl |
| 6998 | static void ir_render(CodeGen *g, ZigFn *fn_entry) { | 7008 | static void ir_render(CodeGen *g, ZigFn *fn_entry) { |
| 6999 | assert(fn_entry); | 7009 | assert(fn_entry); |
| 7000 | 7010 | ||
| 7001 | IrExecutableGen *executable = &fn_entry->analyzed_executable; | 7011 | Stage1Air *executable = &fn_entry->analyzed_executable; |
| 7002 | assert(executable->basic_block_list.length > 0); | 7012 | assert(executable->basic_block_list.length > 0); |
| 7003 | 7013 | ||
| 7004 | for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) { | 7014 | for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) { |
| ... | @@ -7996,7 +8006,7 @@ static void generate_error_name_table(CodeGen *g) { | ... | @@ -7996,7 +8006,7 @@ static void generate_error_name_table(CodeGen *g) { |
| 7996 | } | 8006 | } |
| 7997 | 8007 | ||
| 7998 | static void build_all_basic_blocks(CodeGen *g, ZigFn *fn) { | 8008 | static void build_all_basic_blocks(CodeGen *g, ZigFn *fn) { |
| 7999 | IrExecutableGen *executable = &fn->analyzed_executable; | 8009 | Stage1Air *executable = &fn->analyzed_executable; |
| 8000 | assert(executable->basic_block_list.length > 0); | 8010 | assert(executable->basic_block_list.length > 0); |
| 8001 | LLVMValueRef fn_val = fn_llvm_value(g, fn); | 8011 | LLVMValueRef fn_val = fn_llvm_value(g, fn); |
| 8002 | LLVMBasicBlockRef first_bb = nullptr; | 8012 | LLVMBasicBlockRef first_bb = nullptr; |
| ... | @@ -8030,7 +8040,7 @@ static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val, | ... | @@ -8030,7 +8040,7 @@ static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val, |
| 8030 | bool is_local_to_unit = true; | 8040 | bool is_local_to_unit = true; |
| 8031 | ZigLLVMCreateGlobalVariable(g->dbuilder, get_di_scope(g, var->parent_scope), var->name, | 8041 | ZigLLVMCreateGlobalVariable(g->dbuilder, get_di_scope(g, var->parent_scope), var->name, |
| 8032 | var->name, import->data.structure.root_struct->di_file, | 8042 | var->name, import->data.structure.root_struct->di_file, |
| 8033 | (unsigned)(var->decl_node->line + 1), | 8043 | node_line_onebased(var->decl_node), |
| 8034 | get_llvm_di_type(g, type_entry), is_local_to_unit); | 8044 | get_llvm_di_type(g, type_entry), is_local_to_unit); |
| 8035 | 8045 | ||
| 8036 | // TODO ^^ make an actual global variable | 8046 | // TODO ^^ make an actual global variable |
| ... | @@ -8305,7 +8315,8 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -8305,7 +8315,8 @@ static void do_code_gen(CodeGen *g) { |
| 8305 | 8315 | ||
| 8306 | if (var->src_arg_index == SIZE_MAX) { | 8316 | if (var->src_arg_index == SIZE_MAX) { |
| 8307 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), | 8317 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| 8308 | var->name, import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), | 8318 | var->name, import->data.structure.root_struct->di_file, |
| 8319 | node_line_onebased(var->decl_node), | ||
| 8309 | get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); | 8320 | get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); |
| 8310 | 8321 | ||
| 8311 | } else if (is_c_abi) { | 8322 | } else if (is_c_abi) { |
| ... | @@ -8330,7 +8341,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -8330,7 +8341,7 @@ static void do_code_gen(CodeGen *g) { |
| 8330 | if (var->decl_node) { | 8341 | if (var->decl_node) { |
| 8331 | var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), | 8342 | var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| 8332 | var->name, import->data.structure.root_struct->di_file, | 8343 | var->name, import->data.structure.root_struct->di_file, |
| 8333 | (unsigned)(var->decl_node->line + 1), | 8344 | node_line_onebased(var->decl_node), |
| 8334 | get_llvm_di_type(g, gen_type), !g->strip_debug_symbols, 0, (unsigned)(gen_info->gen_index+1)); | 8345 | get_llvm_di_type(g, gen_type), !g->strip_debug_symbols, 0, (unsigned)(gen_info->gen_index+1)); |
| 8335 | } | 8346 | } |
| 8336 | 8347 | ||
| ... | @@ -8374,10 +8385,11 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -8374,10 +8385,11 @@ static void do_code_gen(CodeGen *g) { |
| 8374 | 8385 | ||
| 8375 | if (!g->strip_debug_symbols) { | 8386 | if (!g->strip_debug_symbols) { |
| 8376 | AstNode *source_node = fn_table_entry->proto_node; | 8387 | AstNode *source_node = fn_table_entry->proto_node; |
| 8377 | ZigLLVMSetCurrentDebugLocation(g->builder, (int)source_node->line + 1, | 8388 | ZigLLVMSetCurrentDebugLocation(g->builder, |
| 8378 | (int)source_node->column + 1, get_di_scope(g, fn_table_entry->child_scope)); | 8389 | node_line_onebased(source_node), node_column_onebased(source_node), |
| 8390 | get_di_scope(g, fn_table_entry->child_scope)); | ||
| 8379 | } | 8391 | } |
| 8380 | IrExecutableGen *executable = &fn_table_entry->analyzed_executable; | 8392 | Stage1Air *executable = &fn_table_entry->analyzed_executable; |
| 8381 | LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume"); | 8393 | LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume"); |
| 8382 | LLVMPositionBuilderAtEnd(g->builder, bad_resume_block); | 8394 | LLVMPositionBuilderAtEnd(g->builder, bad_resume_block); |
| 8383 | gen_assertion_scope(g, PanicMsgIdBadResume, fn_table_entry->child_scope); | 8395 | gen_assertion_scope(g, PanicMsgIdBadResume, fn_table_entry->child_scope); |
src/stage1/dump_analysis.cpp+33-9| ... | @@ -1084,19 +1084,43 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { | ... | @@ -1084,19 +1084,43 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { |
| 1084 | jw_end_object(jw); | 1084 | jw_end_object(jw); |
| 1085 | } | 1085 | } |
| 1086 | 1086 | ||
| 1087 | static Buf *collect_doc_comments(RootStruct *root_struct, TokenIndex first_token) { | ||
| 1088 | if (first_token == 0) | ||
| 1089 | return nullptr; | ||
| 1090 | |||
| 1091 | TokenId *token_ids = root_struct->token_ids; | ||
| 1092 | TokenLoc *token_locs = root_struct->token_locs; | ||
| 1093 | Buf *str = buf_alloc(); | ||
| 1094 | const char *source = buf_ptr(root_struct->source_code); | ||
| 1095 | TokenIndex doc_token = first_token; | ||
| 1096 | for (;token_ids[doc_token] == TokenIdDocComment; doc_token += 1) { | ||
| 1097 | // chops off '///' but leaves '\n' | ||
| 1098 | uint32_t start_pos = token_locs[doc_token].offset; | ||
| 1099 | uint32_t token_len = 0; | ||
| 1100 | while (source[start_pos + token_len] != '\n' && | ||
| 1101 | source[start_pos + token_len] != 0) | ||
| 1102 | { | ||
| 1103 | token_len += 1; | ||
| 1104 | } | ||
| 1105 | buf_append_mem(str, source + start_pos + 3, token_len - 3); | ||
| 1106 | } | ||
| 1107 | return str; | ||
| 1108 | } | ||
| 1109 | |||
| 1087 | static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) { | 1110 | static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) { |
| 1088 | JsonWriter *jw = &ctx->jw; | 1111 | JsonWriter *jw = &ctx->jw; |
| 1089 | 1112 | ||
| 1090 | jw_begin_object(jw); | 1113 | jw_begin_object(jw); |
| 1091 | 1114 | ||
| 1092 | jw_object_field(jw, "file"); | 1115 | jw_object_field(jw, "file"); |
| 1093 | anal_dump_file_ref(ctx, node->owner->data.structure.root_struct->path); | 1116 | RootStruct *root_struct = node->owner->data.structure.root_struct; |
| 1117 | anal_dump_file_ref(ctx, root_struct->path); | ||
| 1094 | 1118 | ||
| 1095 | jw_object_field(jw, "line"); | 1119 | jw_object_field(jw, "line"); |
| 1096 | jw_int(jw, node->line); | 1120 | jw_int(jw, root_struct->token_locs[node->main_token].line); |
| 1097 | 1121 | ||
| 1098 | jw_object_field(jw, "col"); | 1122 | jw_object_field(jw, "col"); |
| 1099 | jw_int(jw, node->column); | 1123 | jw_int(jw, root_struct->token_locs[node->main_token].column); |
| 1100 | 1124 | ||
| 1101 | const Buf *doc_comments_buf = nullptr; | 1125 | const Buf *doc_comments_buf = nullptr; |
| 1102 | const Buf *name_buf = nullptr; | 1126 | const Buf *name_buf = nullptr; |
| ... | @@ -1107,30 +1131,30 @@ static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) { | ... | @@ -1107,30 +1131,30 @@ static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) { |
| 1107 | 1131 | ||
| 1108 | switch (node->type) { | 1132 | switch (node->type) { |
| 1109 | case NodeTypeParamDecl: | 1133 | case NodeTypeParamDecl: |
| 1110 | doc_comments_buf = &node->data.param_decl.doc_comments; | 1134 | doc_comments_buf = collect_doc_comments(root_struct, node->data.param_decl.doc_comments); |
| 1111 | name_buf = node->data.param_decl.name; | 1135 | name_buf = node->data.param_decl.name; |
| 1112 | is_var_args = node->data.param_decl.is_var_args; | 1136 | is_var_args = node->data.param_decl.is_var_args; |
| 1113 | is_noalias = node->data.param_decl.is_noalias; | 1137 | is_noalias = node->data.param_decl.is_noalias; |
| 1114 | is_comptime = node->data.param_decl.is_comptime; | 1138 | is_comptime = node->data.param_decl.is_comptime; |
| 1115 | break; | 1139 | break; |
| 1116 | case NodeTypeFnProto: | 1140 | case NodeTypeFnProto: |
| 1117 | doc_comments_buf = &node->data.fn_proto.doc_comments; | 1141 | doc_comments_buf = collect_doc_comments(root_struct, node->data.fn_proto.doc_comments); |
| 1118 | field_nodes = &node->data.fn_proto.params; | 1142 | field_nodes = &node->data.fn_proto.params; |
| 1119 | is_var_args = node->data.fn_proto.is_var_args; | 1143 | is_var_args = node->data.fn_proto.is_var_args; |
| 1120 | break; | 1144 | break; |
| 1121 | case NodeTypeVariableDeclaration: | 1145 | case NodeTypeVariableDeclaration: |
| 1122 | doc_comments_buf = &node->data.variable_declaration.doc_comments; | 1146 | doc_comments_buf = collect_doc_comments(root_struct, node->data.variable_declaration.doc_comments); |
| 1123 | break; | 1147 | break; |
| 1124 | case NodeTypeErrorSetField: | 1148 | case NodeTypeErrorSetField: |
| 1125 | doc_comments_buf = &node->data.err_set_field.doc_comments; | 1149 | doc_comments_buf = collect_doc_comments(root_struct, node->data.err_set_field.doc_comments); |
| 1126 | break; | 1150 | break; |
| 1127 | case NodeTypeStructField: | 1151 | case NodeTypeStructField: |
| 1128 | doc_comments_buf = &node->data.struct_field.doc_comments; | 1152 | doc_comments_buf = collect_doc_comments(root_struct, node->data.struct_field.doc_comments); |
| 1129 | name_buf = node->data.struct_field.name; | 1153 | name_buf = node->data.struct_field.name; |
| 1130 | break; | 1154 | break; |
| 1131 | case NodeTypeContainerDecl: | 1155 | case NodeTypeContainerDecl: |
| 1132 | field_nodes = &node->data.container_decl.fields; | 1156 | field_nodes = &node->data.container_decl.fields; |
| 1133 | doc_comments_buf = &node->data.container_decl.doc_comments; | 1157 | doc_comments_buf = collect_doc_comments(root_struct, node->data.container_decl.doc_comments); |
| 1134 | break; | 1158 | break; |
| 1135 | default: | 1159 | default: |
| 1136 | break; | 1160 | break; |
src/stage1/errmsg.cpp+19-40| ... | @@ -96,14 +96,14 @@ void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note) { | ... | @@ -96,14 +96,14 @@ void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note) { |
| 96 | parent->notes.append(note); | 96 | parent->notes.append(note); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | ErrorMsg *err_msg_create_with_offset(Buf *path, size_t line, size_t column, size_t offset, | 99 | ErrorMsg *err_msg_create_with_offset(Buf *path, uint32_t byte_offset, const char *source, |
| 100 | const char *source, Buf *msg) | 100 | Buf *msg) |
| 101 | { | 101 | { |
| 102 | ErrorMsg *err_msg = heap::c_allocator.create<ErrorMsg>(); | 102 | ErrorMsg *err_msg = heap::c_allocator.create<ErrorMsg>(); |
| 103 | err_msg->path = path; | 103 | err_msg->path = path; |
| 104 | err_msg->line_start = line; | ||
| 105 | err_msg->column_start = column; | ||
| 106 | err_msg->msg = msg; | 104 | err_msg->msg = msg; |
| 105 | err_msg->line_start = 0; | ||
| 106 | err_msg->column_start = 0; | ||
| 107 | 107 | ||
| 108 | if (source == nullptr) { | 108 | if (source == nullptr) { |
| 109 | // Must initialize the buffer anyway | 109 | // Must initialize the buffer anyway |
| ... | @@ -111,46 +111,25 @@ ErrorMsg *err_msg_create_with_offset(Buf *path, size_t line, size_t column, size | ... | @@ -111,46 +111,25 @@ ErrorMsg *err_msg_create_with_offset(Buf *path, size_t line, size_t column, size |
| 111 | return err_msg; | 111 | return err_msg; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | size_t line_start_offset = offset; | 114 | size_t line_start = 0; |
| 115 | for (;;) { | 115 | size_t i = 0; |
| 116 | if (line_start_offset == 0) { | 116 | for (;i < byte_offset; i += 1) { |
| 117 | break; | 117 | switch (source[i]) { |
| 118 | } | 118 | case '\n': |
| 119 | 119 | err_msg->line_start += 1; | |
| 120 | line_start_offset -= 1; | 120 | err_msg->column_start = 0; |
| 121 | 121 | line_start = i + 1; | |
| 122 | if (source[line_start_offset] == '\n') { | 122 | continue; |
| 123 | line_start_offset += 1; | 123 | default: |
| 124 | break; | 124 | err_msg->column_start += 1; |
| 125 | continue; | ||
| 125 | } | 126 | } |
| 126 | } | 127 | } |
| 127 | 128 | while (source[i] != '\n' && source[i] != 0) { | |
| 128 | size_t line_end_offset = offset; | 129 | i += 1; |
| 129 | while (source[line_end_offset] && source[line_end_offset] != '\n') { | ||
| 130 | line_end_offset += 1; | ||
| 131 | } | 130 | } |
| 132 | 131 | ||
| 133 | buf_init_from_mem(&err_msg->line_buf, source + line_start_offset, line_end_offset - line_start_offset); | 132 | buf_init_from_mem(&err_msg->line_buf, source + line_start, i - line_start); |
| 134 | |||
| 135 | return err_msg; | ||
| 136 | } | ||
| 137 | |||
| 138 | ErrorMsg *err_msg_create_with_line(Buf *path, size_t line, size_t column, | ||
| 139 | Buf *source, ZigList<size_t> *line_offsets, Buf *msg) | ||
| 140 | { | ||
| 141 | ErrorMsg *err_msg = heap::c_allocator.create<ErrorMsg>(); | ||
| 142 | err_msg->path = path; | ||
| 143 | err_msg->line_start = line; | ||
| 144 | err_msg->column_start = column; | ||
| 145 | err_msg->msg = msg; | ||
| 146 | |||
| 147 | size_t line_start_offset = line_offsets->at(line); | ||
| 148 | size_t end_line = line + 1; | ||
| 149 | size_t line_end_offset = (end_line >= line_offsets->length) ? buf_len(source) : line_offsets->at(line + 1); | ||
| 150 | size_t len = (line_end_offset + 1 > line_start_offset) ? (line_end_offset - line_start_offset - 1) : 0; | ||
| 151 | if (len == SIZE_MAX) len = 0; | ||
| 152 | |||
| 153 | buf_init_from_mem(&err_msg->line_buf, buf_ptr(source) + line_start_offset, len); | ||
| 154 | 133 | ||
| 155 | return err_msg; | 134 | return err_msg; |
| 156 | } | 135 | } |
src/stage1/errmsg.hpp+1-5| ... | @@ -25,10 +25,6 @@ struct ErrorMsg { | ... | @@ -25,10 +25,6 @@ struct ErrorMsg { |
| 25 | void print_err_msg(ErrorMsg *msg, ErrColor color); | 25 | void print_err_msg(ErrorMsg *msg, ErrColor color); |
| 26 | 26 | ||
| 27 | void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note); | 27 | void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note); |
| 28 | ErrorMsg *err_msg_create_with_offset(Buf *path, size_t line, size_t column, size_t offset, | 28 | ErrorMsg *err_msg_create_with_offset(Buf *path, uint32_t byte_offset, const char *source, Buf *msg); |
| 29 | const char *source, Buf *msg); | ||
| 30 | |||
| 31 | ErrorMsg *err_msg_create_with_line(Buf *path, size_t line, size_t column, | ||
| 32 | Buf *source, ZigList<size_t> *line_offsets, Buf *msg); | ||
| 33 | 29 | ||
| 34 | #endif | 30 | #endif |
src/stage1/error.cpp+2| ... | @@ -88,6 +88,8 @@ const char *err_str(Error err) { | ... | @@ -88,6 +88,8 @@ const char *err_str(Error err) { |
| 88 | case ErrorZigIsTheCCompiler: return "Zig was not provided with libc installation information, and so it does not know where the libc paths are on the system. Zig attempted to use the system C compiler to find out where the libc paths are, but discovered that Zig is being used as the system C compiler."; | 88 | case ErrorZigIsTheCCompiler: return "Zig was not provided with libc installation information, and so it does not know where the libc paths are on the system. Zig attempted to use the system C compiler to find out where the libc paths are, but discovered that Zig is being used as the system C compiler."; |
| 89 | case ErrorFileBusy: return "file is busy"; | 89 | case ErrorFileBusy: return "file is busy"; |
| 90 | case ErrorLocked: return "file is locked by another process"; | 90 | case ErrorLocked: return "file is locked by another process"; |
| 91 | case ErrorInvalidCharacter: return "invalid character"; | ||
| 92 | case ErrorUnicodePointTooLarge: return "unicode codepoint too large"; | ||
| 91 | } | 93 | } |
| 92 | return "(invalid error)"; | 94 | return "(invalid error)"; |
| 93 | } | 95 | } |
src/stage1/ir.cpp+1336-9376| ... | @@ -5,8 +5,8 @@ | ... | @@ -5,8 +5,8 @@ |
| 5 | * See http://opensource.org/licenses/MIT | 5 | * See http://opensource.org/licenses/MIT |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include "astgen.hpp" | ||
| 8 | #include "analyze.hpp" | 9 | #include "analyze.hpp" |
| 9 | #include "ast_render.hpp" | ||
| 10 | #include "error.hpp" | 10 | #include "error.hpp" |
| 11 | #include "ir.hpp" | 11 | #include "ir.hpp" |
| 12 | #include "ir_print.hpp" | 12 | #include "ir_print.hpp" |
| ... | @@ -22,16 +22,9 @@ | ... | @@ -22,16 +22,9 @@ |
| 22 | #include <errno.h> | 22 | #include <errno.h> |
| 23 | #include <math.h> | 23 | #include <math.h> |
| 24 | 24 | ||
| 25 | struct IrBuilderSrc { | ||
| 26 | CodeGen *codegen; | ||
| 27 | IrExecutableSrc *exec; | ||
| 28 | IrBasicBlockSrc *current_basic_block; | ||
| 29 | AstNode *main_block_node; | ||
| 30 | }; | ||
| 31 | |||
| 32 | struct IrBuilderGen { | 25 | struct IrBuilderGen { |
| 33 | CodeGen *codegen; | 26 | CodeGen *codegen; |
| 34 | IrExecutableGen *exec; | 27 | Stage1Air *exec; |
| 35 | IrBasicBlockGen *current_basic_block; | 28 | IrBasicBlockGen *current_basic_block; |
| 36 | 29 | ||
| 37 | // track for immediate post-analysis destruction | 30 | // track for immediate post-analysis destruction |
| ... | @@ -40,7 +33,8 @@ struct IrBuilderGen { | ... | @@ -40,7 +33,8 @@ struct IrBuilderGen { |
| 40 | 33 | ||
| 41 | struct IrAnalyze { | 34 | struct IrAnalyze { |
| 42 | CodeGen *codegen; | 35 | CodeGen *codegen; |
| 43 | IrBuilderSrc old_irb; | 36 | Stage1Zir *zir; |
| 37 | Stage1ZirBasicBlock *zir_current_basic_block; | ||
| 44 | IrBuilderGen new_irb; | 38 | IrBuilderGen new_irb; |
| 45 | size_t old_bb_index; | 39 | size_t old_bb_index; |
| 46 | size_t instruction_index; | 40 | size_t instruction_index; |
| ... | @@ -48,10 +42,14 @@ struct IrAnalyze { | ... | @@ -48,10 +42,14 @@ struct IrAnalyze { |
| 48 | AstNode *explicit_return_type_source_node; | 42 | AstNode *explicit_return_type_source_node; |
| 49 | ZigList<IrInstGen *> src_implicit_return_type_list; | 43 | ZigList<IrInstGen *> src_implicit_return_type_list; |
| 50 | ZigList<IrSuspendPosition> resume_stack; | 44 | ZigList<IrSuspendPosition> resume_stack; |
| 51 | IrBasicBlockSrc *const_predecessor_bb; | 45 | Stage1ZirBasicBlock *const_predecessor_bb; |
| 52 | size_t ref_count; | 46 | size_t ref_count; |
| 53 | size_t break_debug_id; // for debugging purposes | 47 | size_t break_debug_id; // for debugging purposes |
| 54 | IrInstGen *return_ptr; | 48 | IrInstGen *return_ptr; |
| 49 | Stage1Air *parent_exec; | ||
| 50 | size_t *backward_branch_count; | ||
| 51 | size_t *backward_branch_quota; | ||
| 52 | ZigFn *fn; | ||
| 55 | 53 | ||
| 56 | // For the purpose of using in a debugger | 54 | // For the purpose of using in a debugger |
| 57 | void dump(); | 55 | void dump(); |
| ... | @@ -216,27 +214,18 @@ struct DbgIrBreakPoint { | ... | @@ -216,27 +214,18 @@ struct DbgIrBreakPoint { |
| 216 | const char *src_file; | 214 | const char *src_file; |
| 217 | uint32_t line; | 215 | uint32_t line; |
| 218 | }; | 216 | }; |
| 219 | DbgIrBreakPoint dbg_ir_breakpoints_buf[20]; | ||
| 220 | size_t dbg_ir_breakpoints_count = 0; | ||
| 221 | 217 | ||
| 222 | static IrInstSrc *ir_gen_node(IrBuilderSrc *irb, AstNode *node, Scope *scope); | ||
| 223 | static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *scope, LVal lval, | ||
| 224 | ResultLoc *result_loc); | ||
| 225 | static IrInstGen *ir_implicit_cast(IrAnalyze *ira, IrInstGen *value, ZigType *expected_type); | 218 | static IrInstGen *ir_implicit_cast(IrAnalyze *ira, IrInstGen *value, ZigType *expected_type); |
| 226 | static IrInstGen *ir_implicit_cast2(IrAnalyze *ira, IrInst *value_source_instr, | 219 | static IrInstGen *ir_implicit_cast2(IrAnalyze *ira, IrInst *value_source_instr, |
| 227 | IrInstGen *value, ZigType *expected_type); | 220 | IrInstGen *value, ZigType *expected_type); |
| 228 | static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst *source_instr, IrInstGen *ptr, | 221 | static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst *source_instr, IrInstGen *ptr, |
| 229 | ResultLoc *result_loc); | 222 | ResultLoc *result_loc); |
| 230 | static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutableSrc *exec, AstNode *source_node, Buf *msg); | ||
| 231 | static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, | 223 | static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, |
| 232 | IrInst* source_instr, IrInstGen *container_ptr, IrInst *container_ptr_src, | 224 | IrInst* source_instr, IrInstGen *container_ptr, IrInst *container_ptr_src, |
| 233 | ZigType *container_type, bool initializing); | 225 | ZigType *container_type, bool initializing); |
| 234 | static void ir_assert_impl(bool ok, IrInst* source_instruction, const char *file, unsigned int line); | ||
| 235 | static void ir_assert_gen_impl(bool ok, IrInstGen *source_instruction, const char *file, unsigned int line); | 226 | static void ir_assert_gen_impl(bool ok, IrInstGen *source_instruction, const char *file, unsigned int line); |
| 236 | static IrInstGen *ir_get_var_ptr(IrAnalyze *ira, IrInst *source_instr, ZigVar *var); | 227 | static IrInstGen *ir_get_var_ptr(IrAnalyze *ira, IrInst *source_instr, ZigVar *var); |
| 237 | static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op); | 228 | static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op); |
| 238 | static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc); | ||
| 239 | static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc); | ||
| 240 | static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align); | 229 | static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align); |
| 241 | static ZigType *adjust_ptr_const(CodeGen *g, ZigType *ptr_type, bool is_const); | 230 | static ZigType *adjust_ptr_const(CodeGen *g, ZigType *ptr_type, bool is_const); |
| 242 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); | 231 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); |
| ... | @@ -265,26 +254,14 @@ static IrInstGen *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInst* source_inst | ... | @@ -265,26 +254,14 @@ static IrInstGen *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInst* source_inst |
| 265 | IrInstGen *base_ptr, bool initializing); | 254 | IrInstGen *base_ptr, bool initializing); |
| 266 | static IrInstGen *ir_analyze_store_ptr(IrAnalyze *ira, IrInst* source_instr, | 255 | static IrInstGen *ir_analyze_store_ptr(IrAnalyze *ira, IrInst* source_instr, |
| 267 | IrInstGen *ptr, IrInstGen *uncasted_value, bool allow_write_through_const); | 256 | IrInstGen *ptr, IrInstGen *uncasted_value, bool allow_write_through_const); |
| 268 | static IrInstSrc *ir_gen_union_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 269 | IrInstSrc *union_type, IrInstSrc *field_name, AstNode *expr_node, | ||
| 270 | LVal lval, ResultLoc *parent_result_loc); | ||
| 271 | static void ir_reset_result(ResultLoc *result_loc); | 257 | static void ir_reset_result(ResultLoc *result_loc); |
| 272 | static Buf *get_anon_type_name(CodeGen *codegen, IrExecutableSrc *exec, const char *kind_name, | ||
| 273 | Scope *scope, AstNode *source_node, Buf *out_bare_name); | ||
| 274 | static ResultLocCast *ir_build_cast_result_loc(IrBuilderSrc *irb, IrInstSrc *dest_type, | ||
| 275 | ResultLoc *parent_result_loc); | ||
| 276 | static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_instr, | 258 | static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_instr, |
| 277 | TypeStructField *field, IrInstGen *struct_ptr, ZigType *struct_type, bool initializing); | 259 | TypeStructField *field, IrInstGen *struct_ptr, ZigType *struct_type, bool initializing); |
| 278 | static IrInstGen *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, | 260 | static IrInstGen *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, |
| 279 | IrInst* source_instr, IrInstGen *container_ptr, ZigType *container_type); | 261 | IrInst* source_instr, IrInstGen *container_ptr, ZigType *container_type); |
| 280 | static ResultLoc *no_result_loc(void); | ||
| 281 | static IrInstGen *ir_analyze_test_non_null(IrAnalyze *ira, IrInst *source_inst, IrInstGen *value); | 262 | static IrInstGen *ir_analyze_test_non_null(IrAnalyze *ira, IrInst *source_inst, IrInstGen *value); |
| 282 | static IrInstGen *ir_error_dependency_loop(IrAnalyze *ira, IrInst *source_instr); | 263 | static IrInstGen *ir_error_dependency_loop(IrAnalyze *ira, IrInst *source_instr); |
| 283 | static IrInstGen *ir_const_undef(IrAnalyze *ira, IrInst *source_instruction, ZigType *ty); | 264 | static IrInstGen *ir_const_undef(IrAnalyze *ira, IrInst *source_instruction, ZigType *ty); |
| 284 | static ZigVar *ir_create_var(IrBuilderSrc *irb, AstNode *node, Scope *scope, Buf *name, | ||
| 285 | bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime); | ||
| 286 | static void build_decl_var_and_init(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var, | ||
| 287 | IrInstSrc *init, const char *name_hint, IrInstSrc *is_comptime); | ||
| 288 | static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instruction, | 265 | static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instruction, |
| 289 | AstNode *field_source_node, ZigType *union_type, Buf *field_name, IrInstGen *field_result_loc, | 266 | AstNode *field_source_node, ZigType *union_type, Buf *field_name, IrInstGen *field_result_loc, |
| 290 | IrInstGen *result_loc); | 267 | IrInstGen *result_loc); |
| ... | @@ -295,292 +272,15 @@ static bool value_cmp_numeric_val_all(ZigValue *left, Cmp predicate, ZigValue *r | ... | @@ -295,292 +272,15 @@ static bool value_cmp_numeric_val_all(ZigValue *left, Cmp predicate, ZigValue *r |
| 295 | static void memoize_field_init_val(CodeGen *codegen, ZigType *container_type, TypeStructField *field); | 272 | static void memoize_field_init_val(CodeGen *codegen, ZigType *container_type, TypeStructField *field); |
| 296 | static void value_to_bigfloat(BigFloat *out, ZigValue *val); | 273 | static void value_to_bigfloat(BigFloat *out, ZigValue *val); |
| 297 | 274 | ||
| 275 | static void ir_assert_impl(bool ok, IrInst *source_instruction, char const *file, unsigned int line) { | ||
| 276 | if (ok) return; | ||
| 277 | src_assert_impl(ok, source_instruction->source_node, file, line); | ||
| 278 | } | ||
| 279 | |||
| 280 | |||
| 298 | #define ir_assert(OK, SOURCE_INSTRUCTION) ir_assert_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__) | 281 | #define ir_assert(OK, SOURCE_INSTRUCTION) ir_assert_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__) |
| 299 | #define ir_assert_gen(OK, SOURCE_INSTRUCTION) ir_assert_gen_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__) | 282 | #define ir_assert_gen(OK, SOURCE_INSTRUCTION) ir_assert_gen_impl((OK), (SOURCE_INSTRUCTION), __FILE__, __LINE__) |
| 300 | 283 | ||
| 301 | static void destroy_instruction_src(IrInstSrc *inst) { | ||
| 302 | switch (inst->id) { | ||
| 303 | case IrInstSrcIdInvalid: | ||
| 304 | zig_unreachable(); | ||
| 305 | case IrInstSrcIdReturn: | ||
| 306 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcReturn *>(inst)); | ||
| 307 | case IrInstSrcIdConst: | ||
| 308 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcConst *>(inst)); | ||
| 309 | case IrInstSrcIdBinOp: | ||
| 310 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBinOp *>(inst)); | ||
| 311 | case IrInstSrcIdMergeErrSets: | ||
| 312 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcMergeErrSets *>(inst)); | ||
| 313 | case IrInstSrcIdDeclVar: | ||
| 314 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcDeclVar *>(inst)); | ||
| 315 | case IrInstSrcIdCall: | ||
| 316 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCall *>(inst)); | ||
| 317 | case IrInstSrcIdCallExtra: | ||
| 318 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCallExtra *>(inst)); | ||
| 319 | case IrInstSrcIdAsyncCallExtra: | ||
| 320 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAsyncCallExtra *>(inst)); | ||
| 321 | case IrInstSrcIdUnOp: | ||
| 322 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcUnOp *>(inst)); | ||
| 323 | case IrInstSrcIdCondBr: | ||
| 324 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCondBr *>(inst)); | ||
| 325 | case IrInstSrcIdBr: | ||
| 326 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBr *>(inst)); | ||
| 327 | case IrInstSrcIdPhi: | ||
| 328 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPhi *>(inst)); | ||
| 329 | case IrInstSrcIdContainerInitList: | ||
| 330 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcContainerInitList *>(inst)); | ||
| 331 | case IrInstSrcIdContainerInitFields: | ||
| 332 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcContainerInitFields *>(inst)); | ||
| 333 | case IrInstSrcIdUnreachable: | ||
| 334 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcUnreachable *>(inst)); | ||
| 335 | case IrInstSrcIdElemPtr: | ||
| 336 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcElemPtr *>(inst)); | ||
| 337 | case IrInstSrcIdVarPtr: | ||
| 338 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcVarPtr *>(inst)); | ||
| 339 | case IrInstSrcIdLoadPtr: | ||
| 340 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcLoadPtr *>(inst)); | ||
| 341 | case IrInstSrcIdStorePtr: | ||
| 342 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcStorePtr *>(inst)); | ||
| 343 | case IrInstSrcIdTypeOf: | ||
| 344 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTypeOf *>(inst)); | ||
| 345 | case IrInstSrcIdFieldPtr: | ||
| 346 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFieldPtr *>(inst)); | ||
| 347 | case IrInstSrcIdSetCold: | ||
| 348 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSetCold *>(inst)); | ||
| 349 | case IrInstSrcIdSetRuntimeSafety: | ||
| 350 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSetRuntimeSafety *>(inst)); | ||
| 351 | case IrInstSrcIdSetFloatMode: | ||
| 352 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSetFloatMode *>(inst)); | ||
| 353 | case IrInstSrcIdArrayType: | ||
| 354 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcArrayType *>(inst)); | ||
| 355 | case IrInstSrcIdSliceType: | ||
| 356 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSliceType *>(inst)); | ||
| 357 | case IrInstSrcIdAnyFrameType: | ||
| 358 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAnyFrameType *>(inst)); | ||
| 359 | case IrInstSrcIdAsm: | ||
| 360 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAsm *>(inst)); | ||
| 361 | case IrInstSrcIdSizeOf: | ||
| 362 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSizeOf *>(inst)); | ||
| 363 | case IrInstSrcIdTestNonNull: | ||
| 364 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTestNonNull *>(inst)); | ||
| 365 | case IrInstSrcIdOptionalUnwrapPtr: | ||
| 366 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcOptionalUnwrapPtr *>(inst)); | ||
| 367 | case IrInstSrcIdPopCount: | ||
| 368 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPopCount *>(inst)); | ||
| 369 | case IrInstSrcIdClz: | ||
| 370 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcClz *>(inst)); | ||
| 371 | case IrInstSrcIdCtz: | ||
| 372 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCtz *>(inst)); | ||
| 373 | case IrInstSrcIdBswap: | ||
| 374 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBswap *>(inst)); | ||
| 375 | case IrInstSrcIdBitReverse: | ||
| 376 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBitReverse *>(inst)); | ||
| 377 | case IrInstSrcIdSwitchBr: | ||
| 378 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSwitchBr *>(inst)); | ||
| 379 | case IrInstSrcIdSwitchVar: | ||
| 380 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSwitchVar *>(inst)); | ||
| 381 | case IrInstSrcIdSwitchElseVar: | ||
| 382 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSwitchElseVar *>(inst)); | ||
| 383 | case IrInstSrcIdSwitchTarget: | ||
| 384 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSwitchTarget *>(inst)); | ||
| 385 | case IrInstSrcIdImport: | ||
| 386 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcImport *>(inst)); | ||
| 387 | case IrInstSrcIdRef: | ||
| 388 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcRef *>(inst)); | ||
| 389 | case IrInstSrcIdCompileErr: | ||
| 390 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCompileErr *>(inst)); | ||
| 391 | case IrInstSrcIdCompileLog: | ||
| 392 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCompileLog *>(inst)); | ||
| 393 | case IrInstSrcIdErrName: | ||
| 394 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcErrName *>(inst)); | ||
| 395 | case IrInstSrcIdCImport: | ||
| 396 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCImport *>(inst)); | ||
| 397 | case IrInstSrcIdCInclude: | ||
| 398 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCInclude *>(inst)); | ||
| 399 | case IrInstSrcIdCDefine: | ||
| 400 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCDefine *>(inst)); | ||
| 401 | case IrInstSrcIdCUndef: | ||
| 402 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCUndef *>(inst)); | ||
| 403 | case IrInstSrcIdEmbedFile: | ||
| 404 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcEmbedFile *>(inst)); | ||
| 405 | case IrInstSrcIdCmpxchg: | ||
| 406 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCmpxchg *>(inst)); | ||
| 407 | case IrInstSrcIdFence: | ||
| 408 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFence *>(inst)); | ||
| 409 | case IrInstSrcIdReduce: | ||
| 410 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcReduce *>(inst)); | ||
| 411 | case IrInstSrcIdTruncate: | ||
| 412 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTruncate *>(inst)); | ||
| 413 | case IrInstSrcIdIntCast: | ||
| 414 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcIntCast *>(inst)); | ||
| 415 | case IrInstSrcIdFloatCast: | ||
| 416 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFloatCast *>(inst)); | ||
| 417 | case IrInstSrcIdErrSetCast: | ||
| 418 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcErrSetCast *>(inst)); | ||
| 419 | case IrInstSrcIdIntToFloat: | ||
| 420 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcIntToFloat *>(inst)); | ||
| 421 | case IrInstSrcIdFloatToInt: | ||
| 422 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFloatToInt *>(inst)); | ||
| 423 | case IrInstSrcIdBoolToInt: | ||
| 424 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBoolToInt *>(inst)); | ||
| 425 | case IrInstSrcIdVectorType: | ||
| 426 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcVectorType *>(inst)); | ||
| 427 | case IrInstSrcIdShuffleVector: | ||
| 428 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcShuffleVector *>(inst)); | ||
| 429 | case IrInstSrcIdSplat: | ||
| 430 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSplat *>(inst)); | ||
| 431 | case IrInstSrcIdBoolNot: | ||
| 432 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBoolNot *>(inst)); | ||
| 433 | case IrInstSrcIdMemset: | ||
| 434 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcMemset *>(inst)); | ||
| 435 | case IrInstSrcIdMemcpy: | ||
| 436 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcMemcpy *>(inst)); | ||
| 437 | case IrInstSrcIdSlice: | ||
| 438 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSlice *>(inst)); | ||
| 439 | case IrInstSrcIdBreakpoint: | ||
| 440 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBreakpoint *>(inst)); | ||
| 441 | case IrInstSrcIdReturnAddress: | ||
| 442 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcReturnAddress *>(inst)); | ||
| 443 | case IrInstSrcIdFrameAddress: | ||
| 444 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFrameAddress *>(inst)); | ||
| 445 | case IrInstSrcIdFrameHandle: | ||
| 446 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFrameHandle *>(inst)); | ||
| 447 | case IrInstSrcIdFrameType: | ||
| 448 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFrameType *>(inst)); | ||
| 449 | case IrInstSrcIdFrameSize: | ||
| 450 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFrameSize *>(inst)); | ||
| 451 | case IrInstSrcIdAlignOf: | ||
| 452 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAlignOf *>(inst)); | ||
| 453 | case IrInstSrcIdOverflowOp: | ||
| 454 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcOverflowOp *>(inst)); | ||
| 455 | case IrInstSrcIdTestErr: | ||
| 456 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTestErr *>(inst)); | ||
| 457 | case IrInstSrcIdUnwrapErrCode: | ||
| 458 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcUnwrapErrCode *>(inst)); | ||
| 459 | case IrInstSrcIdUnwrapErrPayload: | ||
| 460 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcUnwrapErrPayload *>(inst)); | ||
| 461 | case IrInstSrcIdFnProto: | ||
| 462 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFnProto *>(inst)); | ||
| 463 | case IrInstSrcIdTestComptime: | ||
| 464 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTestComptime *>(inst)); | ||
| 465 | case IrInstSrcIdPtrCast: | ||
| 466 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPtrCast *>(inst)); | ||
| 467 | case IrInstSrcIdBitCast: | ||
| 468 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBitCast *>(inst)); | ||
| 469 | case IrInstSrcIdPtrToInt: | ||
| 470 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPtrToInt *>(inst)); | ||
| 471 | case IrInstSrcIdIntToPtr: | ||
| 472 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcIntToPtr *>(inst)); | ||
| 473 | case IrInstSrcIdIntToEnum: | ||
| 474 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcIntToEnum *>(inst)); | ||
| 475 | case IrInstSrcIdIntToErr: | ||
| 476 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcIntToErr *>(inst)); | ||
| 477 | case IrInstSrcIdErrToInt: | ||
| 478 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcErrToInt *>(inst)); | ||
| 479 | case IrInstSrcIdCheckSwitchProngsUnderNo: | ||
| 480 | case IrInstSrcIdCheckSwitchProngsUnderYes: | ||
| 481 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCheckSwitchProngs *>(inst)); | ||
| 482 | case IrInstSrcIdCheckStatementIsVoid: | ||
| 483 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCheckStatementIsVoid *>(inst)); | ||
| 484 | case IrInstSrcIdTypeName: | ||
| 485 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTypeName *>(inst)); | ||
| 486 | case IrInstSrcIdTagName: | ||
| 487 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTagName *>(inst)); | ||
| 488 | case IrInstSrcIdPtrType: | ||
| 489 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPtrType *>(inst)); | ||
| 490 | case IrInstSrcIdPtrTypeSimple: | ||
| 491 | case IrInstSrcIdPtrTypeSimpleConst: | ||
| 492 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPtrTypeSimple *>(inst)); | ||
| 493 | case IrInstSrcIdDeclRef: | ||
| 494 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcDeclRef *>(inst)); | ||
| 495 | case IrInstSrcIdPanic: | ||
| 496 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPanic *>(inst)); | ||
| 497 | case IrInstSrcIdFieldParentPtr: | ||
| 498 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFieldParentPtr *>(inst)); | ||
| 499 | case IrInstSrcIdByteOffsetOf: | ||
| 500 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcByteOffsetOf *>(inst)); | ||
| 501 | case IrInstSrcIdBitOffsetOf: | ||
| 502 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBitOffsetOf *>(inst)); | ||
| 503 | case IrInstSrcIdTypeInfo: | ||
| 504 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTypeInfo *>(inst)); | ||
| 505 | case IrInstSrcIdType: | ||
| 506 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcType *>(inst)); | ||
| 507 | case IrInstSrcIdHasField: | ||
| 508 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcHasField *>(inst)); | ||
| 509 | case IrInstSrcIdSetEvalBranchQuota: | ||
| 510 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSetEvalBranchQuota *>(inst)); | ||
| 511 | case IrInstSrcIdAlignCast: | ||
| 512 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAlignCast *>(inst)); | ||
| 513 | case IrInstSrcIdImplicitCast: | ||
| 514 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcImplicitCast *>(inst)); | ||
| 515 | case IrInstSrcIdResolveResult: | ||
| 516 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcResolveResult *>(inst)); | ||
| 517 | case IrInstSrcIdResetResult: | ||
| 518 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcResetResult *>(inst)); | ||
| 519 | case IrInstSrcIdSetAlignStack: | ||
| 520 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSetAlignStack *>(inst)); | ||
| 521 | case IrInstSrcIdArgTypeAllowVarFalse: | ||
| 522 | case IrInstSrcIdArgTypeAllowVarTrue: | ||
| 523 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcArgType *>(inst)); | ||
| 524 | case IrInstSrcIdExport: | ||
| 525 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcExport *>(inst)); | ||
| 526 | case IrInstSrcIdExtern: | ||
| 527 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcExtern *>(inst)); | ||
| 528 | case IrInstSrcIdErrorReturnTrace: | ||
| 529 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcErrorReturnTrace *>(inst)); | ||
| 530 | case IrInstSrcIdErrorUnion: | ||
| 531 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcErrorUnion *>(inst)); | ||
| 532 | case IrInstSrcIdAtomicRmw: | ||
| 533 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAtomicRmw *>(inst)); | ||
| 534 | case IrInstSrcIdSaveErrRetAddr: | ||
| 535 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSaveErrRetAddr *>(inst)); | ||
| 536 | case IrInstSrcIdAddImplicitReturnType: | ||
| 537 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAddImplicitReturnType *>(inst)); | ||
| 538 | case IrInstSrcIdFloatOp: | ||
| 539 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFloatOp *>(inst)); | ||
| 540 | case IrInstSrcIdMulAdd: | ||
| 541 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcMulAdd *>(inst)); | ||
| 542 | case IrInstSrcIdAtomicLoad: | ||
| 543 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAtomicLoad *>(inst)); | ||
| 544 | case IrInstSrcIdAtomicStore: | ||
| 545 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAtomicStore *>(inst)); | ||
| 546 | case IrInstSrcIdEnumToInt: | ||
| 547 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcEnumToInt *>(inst)); | ||
| 548 | case IrInstSrcIdCheckRuntimeScope: | ||
| 549 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCheckRuntimeScope *>(inst)); | ||
| 550 | case IrInstSrcIdHasDecl: | ||
| 551 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcHasDecl *>(inst)); | ||
| 552 | case IrInstSrcIdUndeclaredIdent: | ||
| 553 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcUndeclaredIdent *>(inst)); | ||
| 554 | case IrInstSrcIdAlloca: | ||
| 555 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAlloca *>(inst)); | ||
| 556 | case IrInstSrcIdEndExpr: | ||
| 557 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcEndExpr *>(inst)); | ||
| 558 | case IrInstSrcIdUnionInitNamedField: | ||
| 559 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcUnionInitNamedField *>(inst)); | ||
| 560 | case IrInstSrcIdSuspendBegin: | ||
| 561 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSuspendBegin *>(inst)); | ||
| 562 | case IrInstSrcIdSuspendFinish: | ||
| 563 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSuspendFinish *>(inst)); | ||
| 564 | case IrInstSrcIdResume: | ||
| 565 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcResume *>(inst)); | ||
| 566 | case IrInstSrcIdAwait: | ||
| 567 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcAwait *>(inst)); | ||
| 568 | case IrInstSrcIdSpillBegin: | ||
| 569 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSpillBegin *>(inst)); | ||
| 570 | case IrInstSrcIdSpillEnd: | ||
| 571 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSpillEnd *>(inst)); | ||
| 572 | case IrInstSrcIdCallArgs: | ||
| 573 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcCallArgs *>(inst)); | ||
| 574 | case IrInstSrcIdWasmMemorySize: | ||
| 575 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemorySize *>(inst)); | ||
| 576 | case IrInstSrcIdWasmMemoryGrow: | ||
| 577 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemoryGrow *>(inst)); | ||
| 578 | case IrInstSrcIdSrc: | ||
| 579 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSrc *>(inst)); | ||
| 580 | } | ||
| 581 | zig_unreachable(); | ||
| 582 | } | ||
| 583 | |||
| 584 | void destroy_instruction_gen(IrInstGen *inst) { | 284 | void destroy_instruction_gen(IrInstGen *inst) { |
| 585 | switch (inst->id) { | 285 | switch (inst->id) { |
| 586 | case IrInstGenIdInvalid: | 286 | case IrInstGenIdInvalid: |
| ... | @@ -781,17 +481,17 @@ static void ira_deref(IrAnalyze *ira) { | ... | @@ -781,17 +481,17 @@ static void ira_deref(IrAnalyze *ira) { |
| 781 | } | 481 | } |
| 782 | assert(ira->ref_count != 0); | 482 | assert(ira->ref_count != 0); |
| 783 | 483 | ||
| 784 | for (size_t bb_i = 0; bb_i < ira->old_irb.exec->basic_block_list.length; bb_i += 1) { | 484 | for (size_t bb_i = 0; bb_i < ira->zir->basic_block_list.length; bb_i += 1) { |
| 785 | IrBasicBlockSrc *pass1_bb = ira->old_irb.exec->basic_block_list.items[bb_i]; | 485 | Stage1ZirBasicBlock *pass1_bb = ira->zir->basic_block_list.items[bb_i]; |
| 786 | for (size_t inst_i = 0; inst_i < pass1_bb->instruction_list.length; inst_i += 1) { | 486 | for (size_t inst_i = 0; inst_i < pass1_bb->instruction_list.length; inst_i += 1) { |
| 787 | IrInstSrc *pass1_inst = pass1_bb->instruction_list.items[inst_i]; | 487 | IrInstSrc *pass1_inst = pass1_bb->instruction_list.items[inst_i]; |
| 788 | destroy_instruction_src(pass1_inst); | 488 | destroy_instruction_src(pass1_inst); |
| 789 | } | 489 | } |
| 790 | heap::c_allocator.destroy(pass1_bb); | 490 | heap::c_allocator.destroy(pass1_bb); |
| 791 | } | 491 | } |
| 792 | ira->old_irb.exec->basic_block_list.deinit(); | 492 | ira->zir->basic_block_list.deinit(); |
| 793 | ira->old_irb.exec->tld_list.deinit(); | 493 | ira->zir->tld_list.deinit(); |
| 794 | heap::c_allocator.destroy(ira->old_irb.exec); | 494 | heap::c_allocator.destroy(ira->zir); |
| 795 | ira->src_implicit_return_type_list.deinit(); | 495 | ira->src_implicit_return_type_list.deinit(); |
| 796 | ira->resume_stack.deinit(); | 496 | ira->resume_stack.deinit(); |
| 797 | 497 | ||
| ... | @@ -970,54 +670,18 @@ static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expecte | ... | @@ -970,54 +670,18 @@ static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expecte |
| 970 | zig_unreachable(); | 670 | zig_unreachable(); |
| 971 | } | 671 | } |
| 972 | 672 | ||
| 973 | static bool ir_should_inline(IrExecutableSrc *exec, Scope *scope) { | ||
| 974 | if (exec->is_inline) | ||
| 975 | return true; | ||
| 976 | |||
| 977 | while (scope != nullptr) { | ||
| 978 | if (scope->id == ScopeIdCompTime) | ||
| 979 | return true; | ||
| 980 | if (scope->id == ScopeIdTypeOf) | ||
| 981 | return false; | ||
| 982 | if (scope->id == ScopeIdFnDef) | ||
| 983 | break; | ||
| 984 | scope = scope->parent; | ||
| 985 | } | ||
| 986 | return false; | ||
| 987 | } | ||
| 988 | |||
| 989 | static void ir_instruction_append(IrBasicBlockSrc *basic_block, IrInstSrc *instruction) { | ||
| 990 | assert(basic_block); | ||
| 991 | assert(instruction); | ||
| 992 | basic_block->instruction_list.append(instruction); | ||
| 993 | } | ||
| 994 | |||
| 995 | static void ir_inst_gen_append(IrBasicBlockGen *basic_block, IrInstGen *instruction) { | 673 | static void ir_inst_gen_append(IrBasicBlockGen *basic_block, IrInstGen *instruction) { |
| 996 | assert(basic_block); | 674 | assert(basic_block); |
| 997 | assert(instruction); | 675 | assert(instruction); |
| 998 | basic_block->instruction_list.append(instruction); | 676 | basic_block->instruction_list.append(instruction); |
| 999 | } | 677 | } |
| 1000 | 678 | ||
| 1001 | static size_t exec_next_debug_id(IrExecutableSrc *exec) { | 679 | static size_t exec_next_debug_id_gen(Stage1Air *exec) { |
| 1002 | size_t result = exec->next_debug_id; | ||
| 1003 | exec->next_debug_id += 1; | ||
| 1004 | return result; | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | static size_t exec_next_debug_id_gen(IrExecutableGen *exec) { | ||
| 1008 | size_t result = exec->next_debug_id; | 680 | size_t result = exec->next_debug_id; |
| 1009 | exec->next_debug_id += 1; | 681 | exec->next_debug_id += 1; |
| 1010 | return result; | 682 | return result; |
| 1011 | } | 683 | } |
| 1012 | 684 | ||
| 1013 | static ZigFn *exec_fn_entry(IrExecutableSrc *exec) { | ||
| 1014 | return exec->fn_entry; | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | static Buf *exec_c_import_buf(IrExecutableSrc *exec) { | ||
| 1018 | return exec->c_import_buf; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | static bool value_is_comptime(ZigValue *const_val) { | 685 | static bool value_is_comptime(ZigValue *const_val) { |
| 1022 | return const_val->special != ConstValSpecialRuntime; | 686 | return const_val->special != ConstValSpecialRuntime; |
| 1023 | } | 687 | } |
| ... | @@ -1026,33 +690,11 @@ static bool instr_is_comptime(IrInstGen *instruction) { | ... | @@ -1026,33 +690,11 @@ static bool instr_is_comptime(IrInstGen *instruction) { |
| 1026 | return value_is_comptime(instruction->value); | 690 | return value_is_comptime(instruction->value); |
| 1027 | } | 691 | } |
| 1028 | 692 | ||
| 1029 | static bool instr_is_unreachable(IrInstSrc *instruction) { | ||
| 1030 | return instruction->is_noreturn; | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | static void ir_ref_bb(IrBasicBlockSrc *bb) { | ||
| 1034 | bb->ref_count += 1; | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | static void ir_ref_instruction(IrInstSrc *instruction, IrBasicBlockSrc *cur_bb) { | ||
| 1038 | assert(instruction->id != IrInstSrcIdInvalid); | ||
| 1039 | instruction->base.ref_count += 1; | ||
| 1040 | if (instruction->owner_bb != cur_bb && !instr_is_unreachable(instruction) | ||
| 1041 | && instruction->id != IrInstSrcIdConst) | ||
| 1042 | { | ||
| 1043 | ir_ref_bb(instruction->owner_bb); | ||
| 1044 | } | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | static void ir_ref_inst_gen(IrInstGen *instruction) { | 693 | static void ir_ref_inst_gen(IrInstGen *instruction) { |
| 1048 | assert(instruction->id != IrInstGenIdInvalid); | 694 | assert(instruction->id != IrInstGenIdInvalid); |
| 1049 | instruction->base.ref_count += 1; | 695 | instruction->base.ref_count += 1; |
| 1050 | } | 696 | } |
| 1051 | 697 | ||
| 1052 | static void ir_ref_var(ZigVar *var) { | ||
| 1053 | var->ref_count += 1; | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | static void create_result_ptr(CodeGen *codegen, ZigType *expected_type, | 698 | static void create_result_ptr(CodeGen *codegen, ZigType *expected_type, |
| 1057 | ZigValue **out_result, ZigValue **out_result_ptr) | 699 | ZigValue **out_result, ZigValue **out_result_ptr) |
| 1058 | { | 700 | { |
| ... | @@ -1078,7 +720,7 @@ ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) { | ... | @@ -1078,7 +720,7 @@ ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) { |
| 1078 | create_result_ptr(ira->codegen, ira->codegen->builtin_types.entry_type, &result, &result_ptr); | 720 | create_result_ptr(ira->codegen, ira->codegen->builtin_types.entry_type, &result, &result_ptr); |
| 1079 | 721 | ||
| 1080 | if ((err = ir_eval_const_value(ira->codegen, scope, node, result_ptr, | 722 | if ((err = ir_eval_const_value(ira->codegen, scope, node, result_ptr, |
| 1081 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, | 723 | ira->backward_branch_count, ira->backward_branch_quota, |
| 1082 | nullptr, nullptr, node, nullptr, ira->new_irb.exec, nullptr, UndefBad))) | 724 | nullptr, nullptr, node, nullptr, ira->new_irb.exec, nullptr, UndefBad))) |
| 1083 | { | 725 | { |
| 1084 | return ira->codegen->builtin_types.entry_invalid; | 726 | return ira->codegen->builtin_types.entry_invalid; |
| ... | @@ -1092,15 +734,6 @@ ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) { | ... | @@ -1092,15 +734,6 @@ ZigType *ir_analyze_type_expr(IrAnalyze *ira, Scope *scope, AstNode *node) { |
| 1092 | return res_type; | 734 | return res_type; |
| 1093 | } | 735 | } |
| 1094 | 736 | ||
| 1095 | static IrBasicBlockSrc *ir_create_basic_block(IrBuilderSrc *irb, Scope *scope, const char *name_hint) { | ||
| 1096 | IrBasicBlockSrc *result = heap::c_allocator.create<IrBasicBlockSrc>(); | ||
| 1097 | result->scope = scope; | ||
| 1098 | result->name_hint = name_hint; | ||
| 1099 | result->debug_id = exec_next_debug_id(irb->exec); | ||
| 1100 | result->index = UINT32_MAX; // set later | ||
| 1101 | return result; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | static IrBasicBlockGen *ir_create_basic_block_gen(IrAnalyze *ira, Scope *scope, const char *name_hint) { | 737 | static IrBasicBlockGen *ir_create_basic_block_gen(IrAnalyze *ira, Scope *scope, const char *name_hint) { |
| 1105 | IrBasicBlockGen *result = heap::c_allocator.create<IrBasicBlockGen>(); | 738 | IrBasicBlockGen *result = heap::c_allocator.create<IrBasicBlockGen>(); |
| 1106 | result->scope = scope; | 739 | result->scope = scope; |
| ... | @@ -1109,8813 +742,1693 @@ static IrBasicBlockGen *ir_create_basic_block_gen(IrAnalyze *ira, Scope *scope, | ... | @@ -1109,8813 +742,1693 @@ static IrBasicBlockGen *ir_create_basic_block_gen(IrAnalyze *ira, Scope *scope, |
| 1109 | return result; | 742 | return result; |
| 1110 | } | 743 | } |
| 1111 | 744 | ||
| 1112 | static IrBasicBlockGen *ir_build_bb_from(IrAnalyze *ira, IrBasicBlockSrc *other_bb) { | 745 | static IrBasicBlockGen *ir_build_bb_from(IrAnalyze *ira, Stage1ZirBasicBlock *other_bb) { |
| 1113 | IrBasicBlockGen *new_bb = ir_create_basic_block_gen(ira, other_bb->scope, other_bb->name_hint); | 746 | IrBasicBlockGen *new_bb = ir_create_basic_block_gen(ira, other_bb->scope, other_bb->name_hint); |
| 1114 | other_bb->child = new_bb; | 747 | other_bb->child = new_bb; |
| 1115 | return new_bb; | 748 | return new_bb; |
| 1116 | } | 749 | } |
| 1117 | 750 | ||
| 1118 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcDeclVar *) { | 751 | static constexpr IrInstGenId ir_inst_id(IrInstGenDeclVar *) { |
| 1119 | return IrInstSrcIdDeclVar; | 752 | return IrInstGenIdDeclVar; |
| 1120 | } | 753 | } |
| 1121 | 754 | ||
| 1122 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBr *) { | 755 | static constexpr IrInstGenId ir_inst_id(IrInstGenBr *) { |
| 1123 | return IrInstSrcIdBr; | 756 | return IrInstGenIdBr; |
| 1124 | } | 757 | } |
| 1125 | 758 | ||
| 1126 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCondBr *) { | 759 | static constexpr IrInstGenId ir_inst_id(IrInstGenCondBr *) { |
| 1127 | return IrInstSrcIdCondBr; | 760 | return IrInstGenIdCondBr; |
| 1128 | } | 761 | } |
| 1129 | 762 | ||
| 1130 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchBr *) { | 763 | static constexpr IrInstGenId ir_inst_id(IrInstGenSwitchBr *) { |
| 1131 | return IrInstSrcIdSwitchBr; | 764 | return IrInstGenIdSwitchBr; |
| 1132 | } | 765 | } |
| 1133 | 766 | ||
| 1134 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchVar *) { | 767 | static constexpr IrInstGenId ir_inst_id(IrInstGenPhi *) { |
| 1135 | return IrInstSrcIdSwitchVar; | 768 | return IrInstGenIdPhi; |
| 1136 | } | 769 | } |
| 1137 | 770 | ||
| 1138 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchElseVar *) { | 771 | static constexpr IrInstGenId ir_inst_id(IrInstGenBinaryNot *) { |
| 1139 | return IrInstSrcIdSwitchElseVar; | 772 | return IrInstGenIdBinaryNot; |
| 1140 | } | 773 | } |
| 1141 | 774 | ||
| 1142 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSwitchTarget *) { | 775 | static constexpr IrInstGenId ir_inst_id(IrInstGenNegation *) { |
| 1143 | return IrInstSrcIdSwitchTarget; | 776 | return IrInstGenIdNegation; |
| 1144 | } | 777 | } |
| 1145 | 778 | ||
| 1146 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcPhi *) { | 779 | static constexpr IrInstGenId ir_inst_id(IrInstGenBinOp *) { |
| 1147 | return IrInstSrcIdPhi; | 780 | return IrInstGenIdBinOp; |
| 1148 | } | 781 | } |
| 1149 | 782 | ||
| 1150 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnOp *) { | 783 | static constexpr IrInstGenId ir_inst_id(IrInstGenLoadPtr *) { |
| 1151 | return IrInstSrcIdUnOp; | 784 | return IrInstGenIdLoadPtr; |
| 1152 | } | 785 | } |
| 1153 | 786 | ||
| 1154 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBinOp *) { | 787 | static constexpr IrInstGenId ir_inst_id(IrInstGenStorePtr *) { |
| 1155 | return IrInstSrcIdBinOp; | 788 | return IrInstGenIdStorePtr; |
| 1156 | } | 789 | } |
| 1157 | 790 | ||
| 1158 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcMergeErrSets *) { | 791 | static constexpr IrInstGenId ir_inst_id(IrInstGenVectorStoreElem *) { |
| 1159 | return IrInstSrcIdMergeErrSets; | 792 | return IrInstGenIdVectorStoreElem; |
| 1160 | } | 793 | } |
| 1161 | 794 | ||
| 1162 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcLoadPtr *) { | 795 | static constexpr IrInstGenId ir_inst_id(IrInstGenStructFieldPtr *) { |
| 1163 | return IrInstSrcIdLoadPtr; | 796 | return IrInstGenIdStructFieldPtr; |
| 1164 | } | 797 | } |
| 1165 | 798 | ||
| 1166 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcStorePtr *) { | 799 | static constexpr IrInstGenId ir_inst_id(IrInstGenUnionFieldPtr *) { |
| 1167 | return IrInstSrcIdStorePtr; | 800 | return IrInstGenIdUnionFieldPtr; |
| 1168 | } | 801 | } |
| 1169 | 802 | ||
| 1170 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFieldPtr *) { | 803 | static constexpr IrInstGenId ir_inst_id(IrInstGenElemPtr *) { |
| 1171 | return IrInstSrcIdFieldPtr; | 804 | return IrInstGenIdElemPtr; |
| 1172 | } | 805 | } |
| 1173 | 806 | ||
| 1174 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcElemPtr *) { | 807 | static constexpr IrInstGenId ir_inst_id(IrInstGenVarPtr *) { |
| 1175 | return IrInstSrcIdElemPtr; | 808 | return IrInstGenIdVarPtr; |
| 1176 | } | 809 | } |
| 1177 | 810 | ||
| 1178 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcVarPtr *) { | 811 | static constexpr IrInstGenId ir_inst_id(IrInstGenReturnPtr *) { |
| 1179 | return IrInstSrcIdVarPtr; | 812 | return IrInstGenIdReturnPtr; |
| 1180 | } | 813 | } |
| 1181 | 814 | ||
| 1182 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCall *) { | 815 | static constexpr IrInstGenId ir_inst_id(IrInstGenCall *) { |
| 1183 | return IrInstSrcIdCall; | 816 | return IrInstGenIdCall; |
| 1184 | } | 817 | } |
| 1185 | 818 | ||
| 1186 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCallArgs *) { | 819 | static constexpr IrInstGenId ir_inst_id(IrInstGenReturn *) { |
| 1187 | return IrInstSrcIdCallArgs; | 820 | return IrInstGenIdReturn; |
| 1188 | } | 821 | } |
| 1189 | 822 | ||
| 1190 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCallExtra *) { | 823 | static constexpr IrInstGenId ir_inst_id(IrInstGenCast *) { |
| 1191 | return IrInstSrcIdCallExtra; | 824 | return IrInstGenIdCast; |
| 1192 | } | 825 | } |
| 1193 | 826 | ||
| 1194 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAsyncCallExtra *) { | 827 | static constexpr IrInstGenId ir_inst_id(IrInstGenUnreachable *) { |
| 1195 | return IrInstSrcIdAsyncCallExtra; | 828 | return IrInstGenIdUnreachable; |
| 1196 | } | 829 | } |
| 1197 | 830 | ||
| 1198 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcConst *) { | 831 | static constexpr IrInstGenId ir_inst_id(IrInstGenAsm *) { |
| 1199 | return IrInstSrcIdConst; | 832 | return IrInstGenIdAsm; |
| 1200 | } | 833 | } |
| 1201 | 834 | ||
| 1202 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcReturn *) { | 835 | static constexpr IrInstGenId ir_inst_id(IrInstGenTestNonNull *) { |
| 1203 | return IrInstSrcIdReturn; | 836 | return IrInstGenIdTestNonNull; |
| 1204 | } | 837 | } |
| 1205 | 838 | ||
| 1206 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcContainerInitList *) { | 839 | static constexpr IrInstGenId ir_inst_id(IrInstGenOptionalUnwrapPtr *) { |
| 1207 | return IrInstSrcIdContainerInitList; | 840 | return IrInstGenIdOptionalUnwrapPtr; |
| 1208 | } | 841 | } |
| 1209 | 842 | ||
| 1210 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcContainerInitFields *) { | 843 | static constexpr IrInstGenId ir_inst_id(IrInstGenOptionalWrap *) { |
| 1211 | return IrInstSrcIdContainerInitFields; | 844 | return IrInstGenIdOptionalWrap; |
| 1212 | } | 845 | } |
| 1213 | 846 | ||
| 1214 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnreachable *) { | 847 | static constexpr IrInstGenId ir_inst_id(IrInstGenUnionTag *) { |
| 1215 | return IrInstSrcIdUnreachable; | 848 | return IrInstGenIdUnionTag; |
| 1216 | } | 849 | } |
| 1217 | 850 | ||
| 1218 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeOf *) { | 851 | static constexpr IrInstGenId ir_inst_id(IrInstGenClz *) { |
| 1219 | return IrInstSrcIdTypeOf; | 852 | return IrInstGenIdClz; |
| 1220 | } | 853 | } |
| 1221 | 854 | ||
| 1222 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetCold *) { | 855 | static constexpr IrInstGenId ir_inst_id(IrInstGenCtz *) { |
| 1223 | return IrInstSrcIdSetCold; | 856 | return IrInstGenIdCtz; |
| 1224 | } | 857 | } |
| 1225 | 858 | ||
| 1226 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetRuntimeSafety *) { | 859 | static constexpr IrInstGenId ir_inst_id(IrInstGenPopCount *) { |
| 1227 | return IrInstSrcIdSetRuntimeSafety; | 860 | return IrInstGenIdPopCount; |
| 1228 | } | 861 | } |
| 1229 | 862 | ||
| 1230 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetFloatMode *) { | 863 | static constexpr IrInstGenId ir_inst_id(IrInstGenBswap *) { |
| 1231 | return IrInstSrcIdSetFloatMode; | 864 | return IrInstGenIdBswap; |
| 1232 | } | 865 | } |
| 1233 | 866 | ||
| 1234 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcArrayType *) { | 867 | static constexpr IrInstGenId ir_inst_id(IrInstGenBitReverse *) { |
| 1235 | return IrInstSrcIdArrayType; | 868 | return IrInstGenIdBitReverse; |
| 1236 | } | ||
| 1237 | |||
| 1238 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAnyFrameType *) { | ||
| 1239 | return IrInstSrcIdAnyFrameType; | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSliceType *) { | ||
| 1243 | return IrInstSrcIdSliceType; | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAsm *) { | ||
| 1247 | return IrInstSrcIdAsm; | ||
| 1248 | } | 869 | } |
| 1249 | 870 | ||
| 1250 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSizeOf *) { | 871 | static constexpr IrInstGenId ir_inst_id(IrInstGenRef *) { |
| 1251 | return IrInstSrcIdSizeOf; | 872 | return IrInstGenIdRef; |
| 1252 | } | 873 | } |
| 1253 | 874 | ||
| 1254 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestNonNull *) { | 875 | static constexpr IrInstGenId ir_inst_id(IrInstGenErrName *) { |
| 1255 | return IrInstSrcIdTestNonNull; | 876 | return IrInstGenIdErrName; |
| 1256 | } | 877 | } |
| 1257 | 878 | ||
| 1258 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcOptionalUnwrapPtr *) { | 879 | static constexpr IrInstGenId ir_inst_id(IrInstGenCmpxchg *) { |
| 1259 | return IrInstSrcIdOptionalUnwrapPtr; | 880 | return IrInstGenIdCmpxchg; |
| 1260 | } | 881 | } |
| 1261 | 882 | ||
| 1262 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcClz *) { | 883 | static constexpr IrInstGenId ir_inst_id(IrInstGenFence *) { |
| 1263 | return IrInstSrcIdClz; | 884 | return IrInstGenIdFence; |
| 1264 | } | 885 | } |
| 1265 | 886 | ||
| 1266 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCtz *) { | 887 | static constexpr IrInstGenId ir_inst_id(IrInstGenReduce *) { |
| 1267 | return IrInstSrcIdCtz; | 888 | return IrInstGenIdReduce; |
| 1268 | } | 889 | } |
| 1269 | 890 | ||
| 1270 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcPopCount *) { | 891 | static constexpr IrInstGenId ir_inst_id(IrInstGenTruncate *) { |
| 1271 | return IrInstSrcIdPopCount; | 892 | return IrInstGenIdTruncate; |
| 1272 | } | 893 | } |
| 1273 | 894 | ||
| 1274 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBswap *) { | 895 | static constexpr IrInstGenId ir_inst_id(IrInstGenShuffleVector *) { |
| 1275 | return IrInstSrcIdBswap; | 896 | return IrInstGenIdShuffleVector; |
| 1276 | } | 897 | } |
| 1277 | 898 | ||
| 1278 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitReverse *) { | 899 | static constexpr IrInstGenId ir_inst_id(IrInstGenSplat *) { |
| 1279 | return IrInstSrcIdBitReverse; | 900 | return IrInstGenIdSplat; |
| 1280 | } | 901 | } |
| 1281 | 902 | ||
| 1282 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcImport *) { | 903 | static constexpr IrInstGenId ir_inst_id(IrInstGenBoolNot *) { |
| 1283 | return IrInstSrcIdImport; | 904 | return IrInstGenIdBoolNot; |
| 1284 | } | 905 | } |
| 1285 | 906 | ||
| 1286 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCImport *) { | 907 | static constexpr IrInstGenId ir_inst_id(IrInstGenMemset *) { |
| 1287 | return IrInstSrcIdCImport; | 908 | return IrInstGenIdMemset; |
| 1288 | } | 909 | } |
| 1289 | 910 | ||
| 1290 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCInclude *) { | 911 | static constexpr IrInstGenId ir_inst_id(IrInstGenMemcpy *) { |
| 1291 | return IrInstSrcIdCInclude; | 912 | return IrInstGenIdMemcpy; |
| 1292 | } | 913 | } |
| 1293 | 914 | ||
| 1294 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCDefine *) { | 915 | static constexpr IrInstGenId ir_inst_id(IrInstGenSlice *) { |
| 1295 | return IrInstSrcIdCDefine; | 916 | return IrInstGenIdSlice; |
| 1296 | } | 917 | } |
| 1297 | 918 | ||
| 1298 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCUndef *) { | 919 | static constexpr IrInstGenId ir_inst_id(IrInstGenBreakpoint *) { |
| 1299 | return IrInstSrcIdCUndef; | 920 | return IrInstGenIdBreakpoint; |
| 1300 | } | 921 | } |
| 1301 | 922 | ||
| 1302 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcRef *) { | 923 | static constexpr IrInstGenId ir_inst_id(IrInstGenReturnAddress *) { |
| 1303 | return IrInstSrcIdRef; | 924 | return IrInstGenIdReturnAddress; |
| 1304 | } | 925 | } |
| 1305 | 926 | ||
| 1306 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCompileErr *) { | 927 | static constexpr IrInstGenId ir_inst_id(IrInstGenFrameAddress *) { |
| 1307 | return IrInstSrcIdCompileErr; | 928 | return IrInstGenIdFrameAddress; |
| 1308 | } | 929 | } |
| 1309 | 930 | ||
| 1310 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCompileLog *) { | 931 | static constexpr IrInstGenId ir_inst_id(IrInstGenFrameHandle *) { |
| 1311 | return IrInstSrcIdCompileLog; | 932 | return IrInstGenIdFrameHandle; |
| 1312 | } | 933 | } |
| 1313 | 934 | ||
| 1314 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrName *) { | 935 | static constexpr IrInstGenId ir_inst_id(IrInstGenFrameSize *) { |
| 1315 | return IrInstSrcIdErrName; | 936 | return IrInstGenIdFrameSize; |
| 1316 | } | 937 | } |
| 1317 | 938 | ||
| 1318 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcEmbedFile *) { | 939 | static constexpr IrInstGenId ir_inst_id(IrInstGenOverflowOp *) { |
| 1319 | return IrInstSrcIdEmbedFile; | 940 | return IrInstGenIdOverflowOp; |
| 1320 | } | 941 | } |
| 1321 | 942 | ||
| 1322 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCmpxchg *) { | 943 | static constexpr IrInstGenId ir_inst_id(IrInstGenTestErr *) { |
| 1323 | return IrInstSrcIdCmpxchg; | 944 | return IrInstGenIdTestErr; |
| 1324 | } | 945 | } |
| 1325 | 946 | ||
| 1326 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFence *) { | 947 | static constexpr IrInstGenId ir_inst_id(IrInstGenMulAdd *) { |
| 1327 | return IrInstSrcIdFence; | 948 | return IrInstGenIdMulAdd; |
| 1328 | } | 949 | } |
| 1329 | 950 | ||
| 1330 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcReduce *) { | 951 | static constexpr IrInstGenId ir_inst_id(IrInstGenFloatOp *) { |
| 1331 | return IrInstSrcIdReduce; | 952 | return IrInstGenIdFloatOp; |
| 1332 | } | 953 | } |
| 1333 | 954 | ||
| 1334 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTruncate *) { | 955 | static constexpr IrInstGenId ir_inst_id(IrInstGenUnwrapErrCode *) { |
| 1335 | return IrInstSrcIdTruncate; | 956 | return IrInstGenIdUnwrapErrCode; |
| 1336 | } | 957 | } |
| 1337 | 958 | ||
| 1338 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntCast *) { | 959 | static constexpr IrInstGenId ir_inst_id(IrInstGenUnwrapErrPayload *) { |
| 1339 | return IrInstSrcIdIntCast; | 960 | return IrInstGenIdUnwrapErrPayload; |
| 1340 | } | 961 | } |
| 1341 | 962 | ||
| 1342 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatCast *) { | 963 | static constexpr IrInstGenId ir_inst_id(IrInstGenErrWrapCode *) { |
| 1343 | return IrInstSrcIdFloatCast; | 964 | return IrInstGenIdErrWrapCode; |
| 1344 | } | 965 | } |
| 1345 | 966 | ||
| 1346 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToFloat *) { | 967 | static constexpr IrInstGenId ir_inst_id(IrInstGenErrWrapPayload *) { |
| 1347 | return IrInstSrcIdIntToFloat; | 968 | return IrInstGenIdErrWrapPayload; |
| 1348 | } | 969 | } |
| 1349 | 970 | ||
| 1350 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatToInt *) { | 971 | static constexpr IrInstGenId ir_inst_id(IrInstGenPtrCast *) { |
| 1351 | return IrInstSrcIdFloatToInt; | 972 | return IrInstGenIdPtrCast; |
| 1352 | } | 973 | } |
| 1353 | 974 | ||
| 1354 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolToInt *) { | 975 | static constexpr IrInstGenId ir_inst_id(IrInstGenBitCast *) { |
| 1355 | return IrInstSrcIdBoolToInt; | 976 | return IrInstGenIdBitCast; |
| 1356 | } | 977 | } |
| 1357 | 978 | ||
| 1358 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcVectorType *) { | 979 | static constexpr IrInstGenId ir_inst_id(IrInstGenWidenOrShorten *) { |
| 1359 | return IrInstSrcIdVectorType; | 980 | return IrInstGenIdWidenOrShorten; |
| 1360 | } | 981 | } |
| 1361 | 982 | ||
| 1362 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcShuffleVector *) { | 983 | static constexpr IrInstGenId ir_inst_id(IrInstGenIntToPtr *) { |
| 1363 | return IrInstSrcIdShuffleVector; | 984 | return IrInstGenIdIntToPtr; |
| 1364 | } | 985 | } |
| 1365 | 986 | ||
| 1366 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSplat *) { | 987 | static constexpr IrInstGenId ir_inst_id(IrInstGenPtrToInt *) { |
| 1367 | return IrInstSrcIdSplat; | 988 | return IrInstGenIdPtrToInt; |
| 1368 | } | 989 | } |
| 1369 | 990 | ||
| 1370 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolNot *) { | 991 | static constexpr IrInstGenId ir_inst_id(IrInstGenIntToEnum *) { |
| 1371 | return IrInstSrcIdBoolNot; | 992 | return IrInstGenIdIntToEnum; |
| 1372 | } | 993 | } |
| 1373 | 994 | ||
| 1374 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemset *) { | 995 | static constexpr IrInstGenId ir_inst_id(IrInstGenIntToErr *) { |
| 1375 | return IrInstSrcIdMemset; | 996 | return IrInstGenIdIntToErr; |
| 1376 | } | 997 | } |
| 1377 | 998 | ||
| 1378 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemcpy *) { | 999 | static constexpr IrInstGenId ir_inst_id(IrInstGenErrToInt *) { |
| 1379 | return IrInstSrcIdMemcpy; | 1000 | return IrInstGenIdErrToInt; |
| 1380 | } | 1001 | } |
| 1381 | 1002 | ||
| 1382 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSlice *) { | 1003 | static constexpr IrInstGenId ir_inst_id(IrInstGenPanic *) { |
| 1383 | return IrInstSrcIdSlice; | 1004 | return IrInstGenIdPanic; |
| 1384 | } | 1005 | } |
| 1385 | 1006 | ||
| 1386 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBreakpoint *) { | 1007 | static constexpr IrInstGenId ir_inst_id(IrInstGenTagName *) { |
| 1387 | return IrInstSrcIdBreakpoint; | 1008 | return IrInstGenIdTagName; |
| 1388 | } | 1009 | } |
| 1389 | 1010 | ||
| 1390 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcReturnAddress *) { | 1011 | static constexpr IrInstGenId ir_inst_id(IrInstGenFieldParentPtr *) { |
| 1391 | return IrInstSrcIdReturnAddress; | 1012 | return IrInstGenIdFieldParentPtr; |
| 1392 | } | 1013 | } |
| 1393 | 1014 | ||
| 1394 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameAddress *) { | 1015 | static constexpr IrInstGenId ir_inst_id(IrInstGenAlignCast *) { |
| 1395 | return IrInstSrcIdFrameAddress; | 1016 | return IrInstGenIdAlignCast; |
| 1396 | } | 1017 | } |
| 1397 | 1018 | ||
| 1398 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameHandle *) { | 1019 | static constexpr IrInstGenId ir_inst_id(IrInstGenErrorReturnTrace *) { |
| 1399 | return IrInstSrcIdFrameHandle; | 1020 | return IrInstGenIdErrorReturnTrace; |
| 1400 | } | 1021 | } |
| 1401 | 1022 | ||
| 1402 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameType *) { | 1023 | static constexpr IrInstGenId ir_inst_id(IrInstGenAtomicRmw *) { |
| 1403 | return IrInstSrcIdFrameType; | 1024 | return IrInstGenIdAtomicRmw; |
| 1404 | } | 1025 | } |
| 1405 | 1026 | ||
| 1406 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFrameSize *) { | 1027 | static constexpr IrInstGenId ir_inst_id(IrInstGenAtomicLoad *) { |
| 1407 | return IrInstSrcIdFrameSize; | 1028 | return IrInstGenIdAtomicLoad; |
| 1408 | } | 1029 | } |
| 1409 | 1030 | ||
| 1410 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlignOf *) { | 1031 | static constexpr IrInstGenId ir_inst_id(IrInstGenAtomicStore *) { |
| 1411 | return IrInstSrcIdAlignOf; | 1032 | return IrInstGenIdAtomicStore; |
| 1412 | } | 1033 | } |
| 1413 | 1034 | ||
| 1414 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcOverflowOp *) { | 1035 | static constexpr IrInstGenId ir_inst_id(IrInstGenSaveErrRetAddr *) { |
| 1415 | return IrInstSrcIdOverflowOp; | 1036 | return IrInstGenIdSaveErrRetAddr; |
| 1416 | } | 1037 | } |
| 1417 | 1038 | ||
| 1418 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestErr *) { | 1039 | static constexpr IrInstGenId ir_inst_id(IrInstGenVectorToArray *) { |
| 1419 | return IrInstSrcIdTestErr; | 1040 | return IrInstGenIdVectorToArray; |
| 1420 | } | 1041 | } |
| 1421 | 1042 | ||
| 1422 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcMulAdd *) { | 1043 | static constexpr IrInstGenId ir_inst_id(IrInstGenArrayToVector *) { |
| 1423 | return IrInstSrcIdMulAdd; | 1044 | return IrInstGenIdArrayToVector; |
| 1424 | } | 1045 | } |
| 1425 | 1046 | ||
| 1426 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFloatOp *) { | 1047 | static constexpr IrInstGenId ir_inst_id(IrInstGenAssertZero *) { |
| 1427 | return IrInstSrcIdFloatOp; | 1048 | return IrInstGenIdAssertZero; |
| 1428 | } | 1049 | } |
| 1429 | 1050 | ||
| 1430 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnwrapErrCode *) { | 1051 | static constexpr IrInstGenId ir_inst_id(IrInstGenAssertNonNull *) { |
| 1431 | return IrInstSrcIdUnwrapErrCode; | 1052 | return IrInstGenIdAssertNonNull; |
| 1432 | } | 1053 | } |
| 1433 | 1054 | ||
| 1434 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnwrapErrPayload *) { | 1055 | static constexpr IrInstGenId ir_inst_id(IrInstGenPtrOfArrayToSlice *) { |
| 1435 | return IrInstSrcIdUnwrapErrPayload; | 1056 | return IrInstGenIdPtrOfArrayToSlice; |
| 1436 | } | 1057 | } |
| 1437 | 1058 | ||
| 1438 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFnProto *) { | 1059 | static constexpr IrInstGenId ir_inst_id(IrInstGenSuspendBegin *) { |
| 1439 | return IrInstSrcIdFnProto; | 1060 | return IrInstGenIdSuspendBegin; |
| 1440 | } | 1061 | } |
| 1441 | 1062 | ||
| 1442 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTestComptime *) { | 1063 | static constexpr IrInstGenId ir_inst_id(IrInstGenSuspendFinish *) { |
| 1443 | return IrInstSrcIdTestComptime; | 1064 | return IrInstGenIdSuspendFinish; |
| 1444 | } | 1065 | } |
| 1445 | 1066 | ||
| 1446 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrCast *) { | 1067 | static constexpr IrInstGenId ir_inst_id(IrInstGenAwait *) { |
| 1447 | return IrInstSrcIdPtrCast; | 1068 | return IrInstGenIdAwait; |
| 1448 | } | 1069 | } |
| 1449 | 1070 | ||
| 1450 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitCast *) { | 1071 | static constexpr IrInstGenId ir_inst_id(IrInstGenResume *) { |
| 1451 | return IrInstSrcIdBitCast; | 1072 | return IrInstGenIdResume; |
| 1452 | } | 1073 | } |
| 1453 | 1074 | ||
| 1454 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToPtr *) { | 1075 | static constexpr IrInstGenId ir_inst_id(IrInstGenSpillBegin *) { |
| 1455 | return IrInstSrcIdIntToPtr; | 1076 | return IrInstGenIdSpillBegin; |
| 1456 | } | 1077 | } |
| 1457 | 1078 | ||
| 1458 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrToInt *) { | 1079 | static constexpr IrInstGenId ir_inst_id(IrInstGenSpillEnd *) { |
| 1459 | return IrInstSrcIdPtrToInt; | 1080 | return IrInstGenIdSpillEnd; |
| 1460 | } | 1081 | } |
| 1461 | 1082 | ||
| 1462 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToEnum *) { | 1083 | static constexpr IrInstGenId ir_inst_id(IrInstGenVectorExtractElem *) { |
| 1463 | return IrInstSrcIdIntToEnum; | 1084 | return IrInstGenIdVectorExtractElem; |
| 1464 | } | 1085 | } |
| 1465 | 1086 | ||
| 1466 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcEnumToInt *) { | 1087 | static constexpr IrInstGenId ir_inst_id(IrInstGenAlloca *) { |
| 1467 | return IrInstSrcIdEnumToInt; | 1088 | return IrInstGenIdAlloca; |
| 1468 | } | 1089 | } |
| 1469 | 1090 | ||
| 1470 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntToErr *) { | 1091 | static constexpr IrInstGenId ir_inst_id(IrInstGenConst *) { |
| 1471 | return IrInstSrcIdIntToErr; | 1092 | return IrInstGenIdConst; |
| 1472 | } | 1093 | } |
| 1473 | 1094 | ||
| 1474 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrToInt *) { | 1095 | static constexpr IrInstGenId ir_inst_id(IrInstGenWasmMemorySize *) { |
| 1475 | return IrInstSrcIdErrToInt; | 1096 | return IrInstGenIdWasmMemorySize; |
| 1476 | } | 1097 | } |
| 1477 | 1098 | ||
| 1478 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckStatementIsVoid *) { | 1099 | static constexpr IrInstGenId ir_inst_id(IrInstGenWasmMemoryGrow *) { |
| 1479 | return IrInstSrcIdCheckStatementIsVoid; | 1100 | return IrInstGenIdWasmMemoryGrow; |
| 1480 | } | 1101 | } |
| 1481 | 1102 | ||
| 1482 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeName *) { | 1103 | static constexpr IrInstGenId ir_inst_id(IrInstGenExtern *) { |
| 1483 | return IrInstSrcIdTypeName; | 1104 | return IrInstGenIdExtern; |
| 1484 | } | 1105 | } |
| 1485 | 1106 | ||
| 1486 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcDeclRef *) { | 1107 | template<typename T> |
| 1487 | return IrInstSrcIdDeclRef; | 1108 | static T *ir_create_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { |
| 1109 | T *special_instruction = heap::c_allocator.create<T>(); | ||
| 1110 | special_instruction->base.id = ir_inst_id(special_instruction); | ||
| 1111 | special_instruction->base.base.scope = scope; | ||
| 1112 | special_instruction->base.base.source_node = source_node; | ||
| 1113 | special_instruction->base.base.debug_id = exec_next_debug_id_gen(irb->exec); | ||
| 1114 | special_instruction->base.owner_bb = irb->current_basic_block; | ||
| 1115 | special_instruction->base.value = irb->codegen->pass1_arena->create<ZigValue>(); | ||
| 1116 | return special_instruction; | ||
| 1488 | } | 1117 | } |
| 1489 | 1118 | ||
| 1490 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcPanic *) { | 1119 | template<typename T> |
| 1491 | return IrInstSrcIdPanic; | 1120 | static T *ir_create_inst_noval(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { |
| 1121 | T *special_instruction = heap::c_allocator.create<T>(); | ||
| 1122 | special_instruction->base.id = ir_inst_id(special_instruction); | ||
| 1123 | special_instruction->base.base.scope = scope; | ||
| 1124 | special_instruction->base.base.source_node = source_node; | ||
| 1125 | special_instruction->base.base.debug_id = exec_next_debug_id_gen(irb->exec); | ||
| 1126 | special_instruction->base.owner_bb = irb->current_basic_block; | ||
| 1127 | return special_instruction; | ||
| 1492 | } | 1128 | } |
| 1493 | 1129 | ||
| 1494 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTagName *) { | 1130 | template<typename T> |
| 1495 | return IrInstSrcIdTagName; | 1131 | static T *ir_build_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { |
| 1132 | T *special_instruction = ir_create_inst_gen<T>(irb, scope, source_node); | ||
| 1133 | ir_inst_gen_append(irb->current_basic_block, &special_instruction->base); | ||
| 1134 | return special_instruction; | ||
| 1496 | } | 1135 | } |
| 1497 | 1136 | ||
| 1498 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcFieldParentPtr *) { | 1137 | template<typename T> |
| 1499 | return IrInstSrcIdFieldParentPtr; | 1138 | static T *ir_build_inst_noreturn(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { |
| 1139 | T *special_instruction = ir_create_inst_noval<T>(irb, scope, source_node); | ||
| 1140 | special_instruction->base.value = irb->codegen->intern.for_unreachable(); | ||
| 1141 | ir_inst_gen_append(irb->current_basic_block, &special_instruction->base); | ||
| 1142 | return special_instruction; | ||
| 1500 | } | 1143 | } |
| 1501 | 1144 | ||
| 1502 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcByteOffsetOf *) { | 1145 | template<typename T> |
| 1503 | return IrInstSrcIdByteOffsetOf; | 1146 | static T *ir_build_inst_void(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { |
| 1147 | T *special_instruction = ir_create_inst_noval<T>(irb, scope, source_node); | ||
| 1148 | special_instruction->base.value = irb->codegen->intern.for_void(); | ||
| 1149 | ir_inst_gen_append(irb->current_basic_block, &special_instruction->base); | ||
| 1150 | return special_instruction; | ||
| 1504 | } | 1151 | } |
| 1505 | 1152 | ||
| 1506 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcBitOffsetOf *) { | 1153 | IrInstGen *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, |
| 1507 | return IrInstSrcIdBitOffsetOf; | 1154 | ZigType *var_type, const char *name_hint) |
| 1155 | { | ||
| 1156 | IrInstGenAlloca *alloca_gen = heap::c_allocator.create<IrInstGenAlloca>(); | ||
| 1157 | alloca_gen->base.id = IrInstGenIdAlloca; | ||
| 1158 | alloca_gen->base.base.source_node = source_node; | ||
| 1159 | alloca_gen->base.base.scope = scope; | ||
| 1160 | alloca_gen->base.value = g->pass1_arena->create<ZigValue>(); | ||
| 1161 | alloca_gen->base.value->type = get_pointer_to_type(g, var_type, false); | ||
| 1162 | alloca_gen->base.base.ref_count = 1; | ||
| 1163 | alloca_gen->name_hint = name_hint; | ||
| 1164 | fn->alloca_gen_list.append(alloca_gen); | ||
| 1165 | return &alloca_gen->base; | ||
| 1508 | } | 1166 | } |
| 1509 | 1167 | ||
| 1510 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeInfo *) { | 1168 | static IrInstGen *ir_build_cast(IrAnalyze *ira, IrInst *source_instr,ZigType *dest_type, |
| 1511 | return IrInstSrcIdTypeInfo; | 1169 | IrInstGen *value, CastOp cast_op) |
| 1512 | } | 1170 | { |
| 1171 | IrInstGenCast *inst = ir_build_inst_gen<IrInstGenCast>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 1172 | inst->base.value->type = dest_type; | ||
| 1173 | inst->value = value; | ||
| 1174 | inst->cast_op = cast_op; | ||
| 1513 | 1175 | ||
| 1514 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcType *) { | 1176 | ir_ref_inst_gen(value); |
| 1515 | return IrInstSrcIdType; | ||
| 1516 | } | ||
| 1517 | 1177 | ||
| 1518 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcHasField *) { | 1178 | return &inst->base; |
| 1519 | return IrInstSrcIdHasField; | ||
| 1520 | } | 1179 | } |
| 1521 | 1180 | ||
| 1522 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetEvalBranchQuota *) { | 1181 | static IrInstGen *ir_build_cond_br_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *condition, |
| 1523 | return IrInstSrcIdSetEvalBranchQuota; | 1182 | IrBasicBlockGen *then_block, IrBasicBlockGen *else_block) |
| 1524 | } | 1183 | { |
| 1184 | IrInstGenCondBr *inst = ir_build_inst_noreturn<IrInstGenCondBr>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 1185 | inst->condition = condition; | ||
| 1186 | inst->then_block = then_block; | ||
| 1187 | inst->else_block = else_block; | ||
| 1525 | 1188 | ||
| 1526 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcPtrType *) { | 1189 | ir_ref_inst_gen(condition); |
| 1527 | return IrInstSrcIdPtrType; | ||
| 1528 | } | ||
| 1529 | 1190 | ||
| 1530 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlignCast *) { | 1191 | return &inst->base; |
| 1531 | return IrInstSrcIdAlignCast; | ||
| 1532 | } | 1192 | } |
| 1533 | 1193 | ||
| 1534 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcImplicitCast *) { | 1194 | static IrInstGen *ir_build_return_gen(IrAnalyze *ira, IrInst *source_inst, IrInstGen *operand) { |
| 1535 | return IrInstSrcIdImplicitCast; | 1195 | IrInstGenReturn *inst = ir_build_inst_noreturn<IrInstGenReturn>(&ira->new_irb, |
| 1536 | } | 1196 | source_inst->scope, source_inst->source_node); |
| 1197 | inst->operand = operand; | ||
| 1537 | 1198 | ||
| 1538 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcResolveResult *) { | 1199 | if (operand != nullptr) ir_ref_inst_gen(operand); |
| 1539 | return IrInstSrcIdResolveResult; | ||
| 1540 | } | ||
| 1541 | 1200 | ||
| 1542 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcResetResult *) { | 1201 | return &inst->base; |
| 1543 | return IrInstSrcIdResetResult; | ||
| 1544 | } | 1202 | } |
| 1545 | 1203 | ||
| 1546 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetAlignStack *) { | 1204 | static IrInstGen *ir_build_bin_op_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *res_type, |
| 1547 | return IrInstSrcIdSetAlignStack; | 1205 | IrBinOp op_id, IrInstGen *op1, IrInstGen *op2, bool safety_check_on) |
| 1548 | } | 1206 | { |
| 1207 | IrInstGenBinOp *inst = ir_build_inst_gen<IrInstGenBinOp>(&ira->new_irb, | ||
| 1208 | source_instr->scope, source_instr->source_node); | ||
| 1209 | inst->base.value->type = res_type; | ||
| 1210 | inst->op_id = op_id; | ||
| 1211 | inst->op1 = op1; | ||
| 1212 | inst->op2 = op2; | ||
| 1213 | inst->safety_check_on = safety_check_on; | ||
| 1549 | 1214 | ||
| 1550 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcExport *) { | 1215 | ir_ref_inst_gen(op1); |
| 1551 | return IrInstSrcIdExport; | 1216 | ir_ref_inst_gen(op2); |
| 1552 | } | ||
| 1553 | 1217 | ||
| 1554 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcExtern *) { | 1218 | return &inst->base; |
| 1555 | return IrInstSrcIdExtern; | ||
| 1556 | } | 1219 | } |
| 1557 | 1220 | ||
| 1558 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrorReturnTrace *) { | ||
| 1559 | return IrInstSrcIdErrorReturnTrace; | ||
| 1560 | } | ||
| 1561 | 1221 | ||
| 1562 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrorUnion *) { | 1222 | static IrInstGen *ir_build_var_ptr_gen(IrAnalyze *ira, IrInst *source_instr, ZigVar *var) { |
| 1563 | return IrInstSrcIdErrorUnion; | 1223 | IrInstGenVarPtr *instruction = ir_build_inst_gen<IrInstGenVarPtr>(&ira->new_irb, source_instr->scope, source_instr->source_node); |
| 1564 | } | 1224 | instruction->var = var; |
| 1565 | 1225 | ||
| 1566 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicRmw *) { | 1226 | var->ref_count += 1; |
| 1567 | return IrInstSrcIdAtomicRmw; | ||
| 1568 | } | ||
| 1569 | 1227 | ||
| 1570 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicLoad *) { | 1228 | return &instruction->base; |
| 1571 | return IrInstSrcIdAtomicLoad; | ||
| 1572 | } | 1229 | } |
| 1573 | 1230 | ||
| 1574 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAtomicStore *) { | 1231 | static IrInstGen *ir_build_return_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *ty) { |
| 1575 | return IrInstSrcIdAtomicStore; | 1232 | IrInstGenReturnPtr *instruction = ir_build_inst_gen<IrInstGenReturnPtr>(&ira->new_irb, scope, source_node); |
| 1233 | instruction->base.value->type = ty; | ||
| 1234 | return &instruction->base; | ||
| 1576 | } | 1235 | } |
| 1577 | 1236 | ||
| 1578 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSaveErrRetAddr *) { | 1237 | static IrInstGen *ir_build_elem_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, |
| 1579 | return IrInstSrcIdSaveErrRetAddr; | 1238 | IrInstGen *array_ptr, IrInstGen *elem_index, bool safety_check_on, ZigType *return_type) |
| 1580 | } | 1239 | { |
| 1240 | IrInstGenElemPtr *instruction = ir_build_inst_gen<IrInstGenElemPtr>(&ira->new_irb, scope, source_node); | ||
| 1241 | instruction->base.value->type = return_type; | ||
| 1242 | instruction->array_ptr = array_ptr; | ||
| 1243 | instruction->elem_index = elem_index; | ||
| 1244 | instruction->safety_check_on = safety_check_on; | ||
| 1581 | 1245 | ||
| 1582 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAddImplicitReturnType *) { | 1246 | ir_ref_inst_gen(array_ptr); |
| 1583 | return IrInstSrcIdAddImplicitReturnType; | 1247 | ir_ref_inst_gen(elem_index); |
| 1584 | } | ||
| 1585 | 1248 | ||
| 1586 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrSetCast *) { | 1249 | return &instruction->base; |
| 1587 | return IrInstSrcIdErrSetCast; | ||
| 1588 | } | 1250 | } |
| 1589 | 1251 | ||
| 1590 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckRuntimeScope *) { | 1252 | static IrInstGen *ir_build_struct_field_ptr(IrAnalyze *ira, IrInst *source_instr, |
| 1591 | return IrInstSrcIdCheckRuntimeScope; | 1253 | IrInstGen *struct_ptr, TypeStructField *field, ZigType *ptr_type) |
| 1592 | } | 1254 | { |
| 1255 | IrInstGenStructFieldPtr *inst = ir_build_inst_gen<IrInstGenStructFieldPtr>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 1256 | inst->base.value->type = ptr_type; | ||
| 1257 | inst->struct_ptr = struct_ptr; | ||
| 1258 | inst->field = field; | ||
| 1593 | 1259 | ||
| 1594 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcHasDecl *) { | 1260 | ir_ref_inst_gen(struct_ptr); |
| 1595 | return IrInstSrcIdHasDecl; | ||
| 1596 | } | ||
| 1597 | 1261 | ||
| 1598 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcUndeclaredIdent *) { | 1262 | return &inst->base; |
| 1599 | return IrInstSrcIdUndeclaredIdent; | ||
| 1600 | } | 1263 | } |
| 1601 | 1264 | ||
| 1602 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAlloca *) { | 1265 | static IrInstGen *ir_build_union_field_ptr(IrAnalyze *ira, IrInst *source_instr, |
| 1603 | return IrInstSrcIdAlloca; | 1266 | IrInstGen *union_ptr, TypeUnionField *field, bool safety_check_on, bool initializing, ZigType *ptr_type) |
| 1604 | } | 1267 | { |
| 1268 | IrInstGenUnionFieldPtr *inst = ir_build_inst_gen<IrInstGenUnionFieldPtr>(&ira->new_irb, | ||
| 1269 | source_instr->scope, source_instr->source_node); | ||
| 1270 | inst->base.value->type = ptr_type; | ||
| 1271 | inst->initializing = initializing; | ||
| 1272 | inst->safety_check_on = safety_check_on; | ||
| 1273 | inst->union_ptr = union_ptr; | ||
| 1274 | inst->field = field; | ||
| 1605 | 1275 | ||
| 1606 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcEndExpr *) { | 1276 | ir_ref_inst_gen(union_ptr); |
| 1607 | return IrInstSrcIdEndExpr; | ||
| 1608 | } | ||
| 1609 | 1277 | ||
| 1610 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcUnionInitNamedField *) { | 1278 | return &inst->base; |
| 1611 | return IrInstSrcIdUnionInitNamedField; | ||
| 1612 | } | 1279 | } |
| 1613 | 1280 | ||
| 1614 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSuspendBegin *) { | 1281 | static IrInstGenCall *ir_build_call_gen(IrAnalyze *ira, IrInst *source_instruction, |
| 1615 | return IrInstSrcIdSuspendBegin; | 1282 | ZigFn *fn_entry, IrInstGen *fn_ref, size_t arg_count, IrInstGen **args, |
| 1616 | } | 1283 | CallModifier modifier, IrInstGen *new_stack, bool is_async_call_builtin, |
| 1284 | IrInstGen *result_loc, ZigType *return_type) | ||
| 1285 | { | ||
| 1286 | IrInstGenCall *call_instruction = ir_build_inst_gen<IrInstGenCall>(&ira->new_irb, | ||
| 1287 | source_instruction->scope, source_instruction->source_node); | ||
| 1288 | call_instruction->base.value->type = return_type; | ||
| 1289 | call_instruction->fn_entry = fn_entry; | ||
| 1290 | call_instruction->fn_ref = fn_ref; | ||
| 1291 | call_instruction->args = args; | ||
| 1292 | call_instruction->arg_count = arg_count; | ||
| 1293 | call_instruction->modifier = modifier; | ||
| 1294 | call_instruction->is_async_call_builtin = is_async_call_builtin; | ||
| 1295 | call_instruction->new_stack = new_stack; | ||
| 1296 | call_instruction->result_loc = result_loc; | ||
| 1617 | 1297 | ||
| 1618 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSuspendFinish *) { | 1298 | if (fn_ref != nullptr) ir_ref_inst_gen(fn_ref); |
| 1619 | return IrInstSrcIdSuspendFinish; | 1299 | for (size_t i = 0; i < arg_count; i += 1) |
| 1620 | } | 1300 | ir_ref_inst_gen(args[i]); |
| 1301 | if (new_stack != nullptr) ir_ref_inst_gen(new_stack); | ||
| 1302 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); | ||
| 1621 | 1303 | ||
| 1622 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcAwait *) { | 1304 | return call_instruction; |
| 1623 | return IrInstSrcIdAwait; | ||
| 1624 | } | 1305 | } |
| 1625 | 1306 | ||
| 1626 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcResume *) { | 1307 | static IrInstGen *ir_build_phi_gen(IrAnalyze *ira, IrInst *source_instr, size_t incoming_count, |
| 1627 | return IrInstSrcIdResume; | 1308 | IrBasicBlockGen **incoming_blocks, IrInstGen **incoming_values, ZigType *result_type) |
| 1628 | } | 1309 | { |
| 1310 | assert(incoming_count != 0); | ||
| 1311 | assert(incoming_count != SIZE_MAX); | ||
| 1629 | 1312 | ||
| 1630 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSpillBegin *) { | 1313 | IrInstGenPhi *phi_instruction = ir_build_inst_gen<IrInstGenPhi>(&ira->new_irb, |
| 1631 | return IrInstSrcIdSpillBegin; | 1314 | source_instr->scope, source_instr->source_node); |
| 1632 | } | 1315 | phi_instruction->base.value->type = result_type; |
| 1316 | phi_instruction->incoming_count = incoming_count; | ||
| 1317 | phi_instruction->incoming_blocks = incoming_blocks; | ||
| 1318 | phi_instruction->incoming_values = incoming_values; | ||
| 1633 | 1319 | ||
| 1634 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSpillEnd *) { | 1320 | for (size_t i = 0; i < incoming_count; i += 1) { |
| 1635 | return IrInstSrcIdSpillEnd; | 1321 | ir_ref_inst_gen(incoming_values[i]); |
| 1636 | } | 1322 | } |
| 1637 | 1323 | ||
| 1638 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemorySize *) { | 1324 | return &phi_instruction->base; |
| 1639 | return IrInstSrcIdWasmMemorySize; | ||
| 1640 | } | 1325 | } |
| 1641 | 1326 | ||
| 1642 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemoryGrow *) { | 1327 | static IrInstGen *ir_build_br_gen(IrAnalyze *ira, IrInst *source_instr, IrBasicBlockGen *dest_block) { |
| 1643 | return IrInstSrcIdWasmMemoryGrow; | 1328 | IrInstGenBr *inst = ir_build_inst_noreturn<IrInstGenBr>(&ira->new_irb, source_instr->scope, source_instr->source_node); |
| 1644 | } | 1329 | inst->dest_block = dest_block; |
| 1645 | 1330 | ||
| 1646 | static constexpr IrInstSrcId ir_inst_id(IrInstSrcSrc *) { | 1331 | return &inst->base; |
| 1647 | return IrInstSrcIdSrc; | ||
| 1648 | } | 1332 | } |
| 1649 | 1333 | ||
| 1650 | static constexpr IrInstGenId ir_inst_id(IrInstGenDeclVar *) { | 1334 | static IrInstGen *ir_build_negation(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, ZigType *expr_type, bool wrapping) { |
| 1651 | return IrInstGenIdDeclVar; | 1335 | IrInstGenNegation *instruction = ir_build_inst_gen<IrInstGenNegation>(&ira->new_irb, |
| 1652 | } | 1336 | source_instr->scope, source_instr->source_node); |
| 1337 | instruction->base.value->type = expr_type; | ||
| 1338 | instruction->operand = operand; | ||
| 1339 | instruction->wrapping = wrapping; | ||
| 1653 | 1340 | ||
| 1654 | static constexpr IrInstGenId ir_inst_id(IrInstGenBr *) { | 1341 | ir_ref_inst_gen(operand); |
| 1655 | return IrInstGenIdBr; | ||
| 1656 | } | ||
| 1657 | 1342 | ||
| 1658 | static constexpr IrInstGenId ir_inst_id(IrInstGenCondBr *) { | 1343 | return &instruction->base; |
| 1659 | return IrInstGenIdCondBr; | ||
| 1660 | } | 1344 | } |
| 1661 | 1345 | ||
| 1662 | static constexpr IrInstGenId ir_inst_id(IrInstGenSwitchBr *) { | 1346 | static IrInstGen *ir_build_binary_not(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, |
| 1663 | return IrInstGenIdSwitchBr; | 1347 | ZigType *expr_type) |
| 1664 | } | 1348 | { |
| 1349 | IrInstGenBinaryNot *instruction = ir_build_inst_gen<IrInstGenBinaryNot>(&ira->new_irb, | ||
| 1350 | source_instr->scope, source_instr->source_node); | ||
| 1351 | instruction->base.value->type = expr_type; | ||
| 1352 | instruction->operand = operand; | ||
| 1665 | 1353 | ||
| 1666 | static constexpr IrInstGenId ir_inst_id(IrInstGenPhi *) { | 1354 | ir_ref_inst_gen(operand); |
| 1667 | return IrInstGenIdPhi; | ||
| 1668 | } | ||
| 1669 | 1355 | ||
| 1670 | static constexpr IrInstGenId ir_inst_id(IrInstGenBinaryNot *) { | 1356 | return &instruction->base; |
| 1671 | return IrInstGenIdBinaryNot; | ||
| 1672 | } | 1357 | } |
| 1673 | 1358 | ||
| 1674 | static constexpr IrInstGenId ir_inst_id(IrInstGenNegation *) { | 1359 | static IrInstGen *ir_build_unreachable_gen(IrAnalyze *ira, IrInst *source_instr) { |
| 1675 | return IrInstGenIdNegation; | 1360 | IrInstGenUnreachable *inst = ir_build_inst_noreturn<IrInstGenUnreachable>(&ira->new_irb, source_instr->scope, source_instr->source_node); |
| 1361 | return &inst->base; | ||
| 1676 | } | 1362 | } |
| 1677 | 1363 | ||
| 1678 | static constexpr IrInstGenId ir_inst_id(IrInstGenBinOp *) { | 1364 | static IrInstGen *ir_build_store_ptr_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *ptr, IrInstGen *value) { |
| 1679 | return IrInstGenIdBinOp; | 1365 | IrInstGenStorePtr *instruction = ir_build_inst_void<IrInstGenStorePtr>(&ira->new_irb, |
| 1680 | } | 1366 | source_instr->scope, source_instr->source_node); |
| 1367 | instruction->ptr = ptr; | ||
| 1368 | instruction->value = value; | ||
| 1681 | 1369 | ||
| 1682 | static constexpr IrInstGenId ir_inst_id(IrInstGenLoadPtr *) { | 1370 | ir_ref_inst_gen(ptr); |
| 1683 | return IrInstGenIdLoadPtr; | 1371 | ir_ref_inst_gen(value); |
| 1684 | } | ||
| 1685 | 1372 | ||
| 1686 | static constexpr IrInstGenId ir_inst_id(IrInstGenStorePtr *) { | 1373 | return &instruction->base; |
| 1687 | return IrInstGenIdStorePtr; | ||
| 1688 | } | 1374 | } |
| 1689 | 1375 | ||
| 1690 | static constexpr IrInstGenId ir_inst_id(IrInstGenVectorStoreElem *) { | 1376 | static IrInstGen *ir_build_vector_store_elem(IrAnalyze *ira, IrInst *src_inst, |
| 1691 | return IrInstGenIdVectorStoreElem; | 1377 | IrInstGen *vector_ptr, IrInstGen *index, IrInstGen *value) |
| 1692 | } | 1378 | { |
| 1379 | IrInstGenVectorStoreElem *inst = ir_build_inst_void<IrInstGenVectorStoreElem>( | ||
| 1380 | &ira->new_irb, src_inst->scope, src_inst->source_node); | ||
| 1381 | inst->vector_ptr = vector_ptr; | ||
| 1382 | inst->index = index; | ||
| 1383 | inst->value = value; | ||
| 1693 | 1384 | ||
| 1694 | static constexpr IrInstGenId ir_inst_id(IrInstGenStructFieldPtr *) { | 1385 | ir_ref_inst_gen(vector_ptr); |
| 1695 | return IrInstGenIdStructFieldPtr; | 1386 | ir_ref_inst_gen(index); |
| 1696 | } | 1387 | ir_ref_inst_gen(value); |
| 1697 | 1388 | ||
| 1698 | static constexpr IrInstGenId ir_inst_id(IrInstGenUnionFieldPtr *) { | 1389 | return &inst->base; |
| 1699 | return IrInstGenIdUnionFieldPtr; | ||
| 1700 | } | 1390 | } |
| 1701 | 1391 | ||
| 1702 | static constexpr IrInstGenId ir_inst_id(IrInstGenElemPtr *) { | 1392 | static IrInstGen *ir_build_var_decl_gen(IrAnalyze *ira, IrInst *source_instruction, |
| 1703 | return IrInstGenIdElemPtr; | 1393 | ZigVar *var, IrInstGen *var_ptr) |
| 1704 | } | 1394 | { |
| 1395 | IrInstGenDeclVar *inst = ir_build_inst_gen<IrInstGenDeclVar>(&ira->new_irb, | ||
| 1396 | source_instruction->scope, source_instruction->source_node); | ||
| 1397 | inst->base.value->special = ConstValSpecialStatic; | ||
| 1398 | inst->base.value->type = ira->codegen->builtin_types.entry_void; | ||
| 1399 | inst->var = var; | ||
| 1400 | inst->var_ptr = var_ptr; | ||
| 1705 | 1401 | ||
| 1706 | static constexpr IrInstGenId ir_inst_id(IrInstGenVarPtr *) { | 1402 | ir_ref_inst_gen(var_ptr); |
| 1707 | return IrInstGenIdVarPtr; | ||
| 1708 | } | ||
| 1709 | 1403 | ||
| 1710 | static constexpr IrInstGenId ir_inst_id(IrInstGenReturnPtr *) { | 1404 | return &inst->base; |
| 1711 | return IrInstGenIdReturnPtr; | ||
| 1712 | } | 1405 | } |
| 1713 | 1406 | ||
| 1714 | static constexpr IrInstGenId ir_inst_id(IrInstGenCall *) { | 1407 | static IrInstGen *ir_build_extern_gen(IrAnalyze *ira, IrInst *source_instr, Buf *name, |
| 1715 | return IrInstGenIdCall; | 1408 | GlobalLinkageId linkage, bool is_thread_local, ZigType *expr_type) |
| 1716 | } | 1409 | { |
| 1410 | IrInstGenExtern *instruction = ir_build_inst_gen<IrInstGenExtern>(&ira->new_irb, | ||
| 1411 | source_instr->scope, source_instr->source_node); | ||
| 1412 | instruction->base.value->type = expr_type; | ||
| 1413 | instruction->name = name; | ||
| 1414 | instruction->linkage = linkage; | ||
| 1415 | instruction->is_thread_local = is_thread_local; | ||
| 1717 | 1416 | ||
| 1718 | static constexpr IrInstGenId ir_inst_id(IrInstGenReturn *) { | 1417 | return &instruction->base; |
| 1719 | return IrInstGenIdReturn; | ||
| 1720 | } | 1418 | } |
| 1721 | 1419 | ||
| 1722 | static constexpr IrInstGenId ir_inst_id(IrInstGenCast *) { | 1420 | static IrInstGen *ir_build_load_ptr_gen(IrAnalyze *ira, IrInst *source_instruction, |
| 1723 | return IrInstGenIdCast; | 1421 | IrInstGen *ptr, ZigType *ty, IrInstGen *result_loc) |
| 1724 | } | 1422 | { |
| 1423 | IrInstGenLoadPtr *instruction = ir_build_inst_gen<IrInstGenLoadPtr>( | ||
| 1424 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 1425 | instruction->base.value->type = ty; | ||
| 1426 | instruction->ptr = ptr; | ||
| 1427 | instruction->result_loc = result_loc; | ||
| 1725 | 1428 | ||
| 1726 | static constexpr IrInstGenId ir_inst_id(IrInstGenUnreachable *) { | 1429 | ir_ref_inst_gen(ptr); |
| 1727 | return IrInstGenIdUnreachable; | 1430 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); |
| 1728 | } | ||
| 1729 | 1431 | ||
| 1730 | static constexpr IrInstGenId ir_inst_id(IrInstGenAsm *) { | 1432 | return &instruction->base; |
| 1731 | return IrInstGenIdAsm; | ||
| 1732 | } | 1433 | } |
| 1733 | 1434 | ||
| 1734 | static constexpr IrInstGenId ir_inst_id(IrInstGenTestNonNull *) { | 1435 | static IrInstGen *ir_build_asm_gen(IrAnalyze *ira, IrInst *source_instr, |
| 1735 | return IrInstGenIdTestNonNull; | 1436 | Buf *asm_template, AsmToken *token_list, size_t token_list_len, |
| 1736 | } | 1437 | IrInstGen **input_list, IrInstGen **output_types, ZigVar **output_vars, size_t return_count, |
| 1438 | bool has_side_effects, ZigType *return_type) | ||
| 1439 | { | ||
| 1440 | IrInstGenAsm *instruction = ir_build_inst_gen<IrInstGenAsm>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 1441 | instruction->base.value->type = return_type; | ||
| 1442 | instruction->asm_template = asm_template; | ||
| 1443 | instruction->token_list = token_list; | ||
| 1444 | instruction->token_list_len = token_list_len; | ||
| 1445 | instruction->input_list = input_list; | ||
| 1446 | instruction->output_types = output_types; | ||
| 1447 | instruction->output_vars = output_vars; | ||
| 1448 | instruction->return_count = return_count; | ||
| 1449 | instruction->has_side_effects = has_side_effects; | ||
| 1737 | 1450 | ||
| 1738 | static constexpr IrInstGenId ir_inst_id(IrInstGenOptionalUnwrapPtr *) { | 1451 | assert(source_instr->source_node->type == NodeTypeAsmExpr); |
| 1739 | return IrInstGenIdOptionalUnwrapPtr; | 1452 | for (size_t i = 0; i < source_instr->source_node->data.asm_expr.output_list.length; i += 1) { |
| 1740 | } | 1453 | IrInstGen *output_type = output_types[i]; |
| 1454 | if (output_type) ir_ref_inst_gen(output_type); | ||
| 1455 | } | ||
| 1741 | 1456 | ||
| 1742 | static constexpr IrInstGenId ir_inst_id(IrInstGenOptionalWrap *) { | 1457 | for (size_t i = 0; i < source_instr->source_node->data.asm_expr.input_list.length; i += 1) { |
| 1743 | return IrInstGenIdOptionalWrap; | 1458 | IrInstGen *input_value = input_list[i]; |
| 1744 | } | 1459 | ir_ref_inst_gen(input_value); |
| 1460 | } | ||
| 1745 | 1461 | ||
| 1746 | static constexpr IrInstGenId ir_inst_id(IrInstGenUnionTag *) { | 1462 | return &instruction->base; |
| 1747 | return IrInstGenIdUnionTag; | ||
| 1748 | } | 1463 | } |
| 1749 | 1464 | ||
| 1750 | static constexpr IrInstGenId ir_inst_id(IrInstGenClz *) { | 1465 | static IrInstGen *ir_build_test_non_null_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value) { |
| 1751 | return IrInstGenIdClz; | 1466 | IrInstGenTestNonNull *inst = ir_build_inst_gen<IrInstGenTestNonNull>(&ira->new_irb, |
| 1752 | } | 1467 | source_instr->scope, source_instr->source_node); |
| 1468 | inst->base.value->type = ira->codegen->builtin_types.entry_bool; | ||
| 1469 | inst->value = value; | ||
| 1753 | 1470 | ||
| 1754 | static constexpr IrInstGenId ir_inst_id(IrInstGenCtz *) { | 1471 | ir_ref_inst_gen(value); |
| 1755 | return IrInstGenIdCtz; | ||
| 1756 | } | ||
| 1757 | 1472 | ||
| 1758 | static constexpr IrInstGenId ir_inst_id(IrInstGenPopCount *) { | 1473 | return &inst->base; |
| 1759 | return IrInstGenIdPopCount; | ||
| 1760 | } | 1474 | } |
| 1761 | 1475 | ||
| 1762 | static constexpr IrInstGenId ir_inst_id(IrInstGenBswap *) { | 1476 | static IrInstGen *ir_build_optional_unwrap_ptr_gen(IrAnalyze *ira, IrInst *source_instr, |
| 1763 | return IrInstGenIdBswap; | 1477 | IrInstGen *base_ptr, bool safety_check_on, bool initializing, ZigType *result_type) |
| 1764 | } | 1478 | { |
| 1479 | IrInstGenOptionalUnwrapPtr *inst = ir_build_inst_gen<IrInstGenOptionalUnwrapPtr>(&ira->new_irb, | ||
| 1480 | source_instr->scope, source_instr->source_node); | ||
| 1481 | inst->base.value->type = result_type; | ||
| 1482 | inst->base_ptr = base_ptr; | ||
| 1483 | inst->safety_check_on = safety_check_on; | ||
| 1484 | inst->initializing = initializing; | ||
| 1765 | 1485 | ||
| 1766 | static constexpr IrInstGenId ir_inst_id(IrInstGenBitReverse *) { | 1486 | ir_ref_inst_gen(base_ptr); |
| 1767 | return IrInstGenIdBitReverse; | 1487 | |
| 1488 | return &inst->base; | ||
| 1768 | } | 1489 | } |
| 1769 | 1490 | ||
| 1770 | static constexpr IrInstGenId ir_inst_id(IrInstGenRef *) { | 1491 | static IrInstGen *ir_build_optional_wrap(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_ty, |
| 1771 | return IrInstGenIdRef; | 1492 | IrInstGen *operand, IrInstGen *result_loc) |
| 1772 | } | 1493 | { |
| 1494 | IrInstGenOptionalWrap *instruction = ir_build_inst_gen<IrInstGenOptionalWrap>( | ||
| 1495 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 1496 | instruction->base.value->type = result_ty; | ||
| 1497 | instruction->operand = operand; | ||
| 1498 | instruction->result_loc = result_loc; | ||
| 1773 | 1499 | ||
| 1774 | static constexpr IrInstGenId ir_inst_id(IrInstGenErrName *) { | 1500 | ir_ref_inst_gen(operand); |
| 1775 | return IrInstGenIdErrName; | 1501 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); |
| 1776 | } | ||
| 1777 | 1502 | ||
| 1778 | static constexpr IrInstGenId ir_inst_id(IrInstGenCmpxchg *) { | 1503 | return &instruction->base; |
| 1779 | return IrInstGenIdCmpxchg; | ||
| 1780 | } | 1504 | } |
| 1781 | 1505 | ||
| 1782 | static constexpr IrInstGenId ir_inst_id(IrInstGenFence *) { | 1506 | static IrInstGen *ir_build_err_wrap_payload(IrAnalyze *ira, IrInst *source_instruction, |
| 1783 | return IrInstGenIdFence; | 1507 | ZigType *result_type, IrInstGen *operand, IrInstGen *result_loc) |
| 1784 | } | 1508 | { |
| 1509 | IrInstGenErrWrapPayload *instruction = ir_build_inst_gen<IrInstGenErrWrapPayload>( | ||
| 1510 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 1511 | instruction->base.value->type = result_type; | ||
| 1512 | instruction->operand = operand; | ||
| 1513 | instruction->result_loc = result_loc; | ||
| 1785 | 1514 | ||
| 1786 | static constexpr IrInstGenId ir_inst_id(IrInstGenReduce *) { | 1515 | ir_ref_inst_gen(operand); |
| 1787 | return IrInstGenIdReduce; | 1516 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); |
| 1788 | } | ||
| 1789 | 1517 | ||
| 1790 | static constexpr IrInstGenId ir_inst_id(IrInstGenTruncate *) { | 1518 | return &instruction->base; |
| 1791 | return IrInstGenIdTruncate; | ||
| 1792 | } | 1519 | } |
| 1793 | 1520 | ||
| 1794 | static constexpr IrInstGenId ir_inst_id(IrInstGenShuffleVector *) { | 1521 | static IrInstGen *ir_build_err_wrap_code(IrAnalyze *ira, IrInst *source_instruction, |
| 1795 | return IrInstGenIdShuffleVector; | 1522 | ZigType *result_type, IrInstGen *operand, IrInstGen *result_loc) |
| 1796 | } | 1523 | { |
| 1524 | IrInstGenErrWrapCode *instruction = ir_build_inst_gen<IrInstGenErrWrapCode>( | ||
| 1525 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 1526 | instruction->base.value->type = result_type; | ||
| 1527 | instruction->operand = operand; | ||
| 1528 | instruction->result_loc = result_loc; | ||
| 1797 | 1529 | ||
| 1798 | static constexpr IrInstGenId ir_inst_id(IrInstGenSplat *) { | 1530 | ir_ref_inst_gen(operand); |
| 1799 | return IrInstGenIdSplat; | 1531 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); |
| 1800 | } | ||
| 1801 | 1532 | ||
| 1802 | static constexpr IrInstGenId ir_inst_id(IrInstGenBoolNot *) { | 1533 | return &instruction->base; |
| 1803 | return IrInstGenIdBoolNot; | ||
| 1804 | } | 1534 | } |
| 1805 | 1535 | ||
| 1806 | static constexpr IrInstGenId ir_inst_id(IrInstGenMemset *) { | 1536 | static IrInstGen *ir_build_clz_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *result_type, IrInstGen *op) { |
| 1807 | return IrInstGenIdMemset; | 1537 | IrInstGenClz *instruction = ir_build_inst_gen<IrInstGenClz>(&ira->new_irb, |
| 1808 | } | 1538 | source_instr->scope, source_instr->source_node); |
| 1539 | instruction->base.value->type = result_type; | ||
| 1540 | instruction->op = op; | ||
| 1809 | 1541 | ||
| 1810 | static constexpr IrInstGenId ir_inst_id(IrInstGenMemcpy *) { | 1542 | ir_ref_inst_gen(op); |
| 1811 | return IrInstGenIdMemcpy; | ||
| 1812 | } | ||
| 1813 | 1543 | ||
| 1814 | static constexpr IrInstGenId ir_inst_id(IrInstGenSlice *) { | 1544 | return &instruction->base; |
| 1815 | return IrInstGenIdSlice; | ||
| 1816 | } | 1545 | } |
| 1817 | 1546 | ||
| 1818 | static constexpr IrInstGenId ir_inst_id(IrInstGenBreakpoint *) { | 1547 | static IrInstGen *ir_build_ctz_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *result_type, IrInstGen *op) { |
| 1819 | return IrInstGenIdBreakpoint; | 1548 | IrInstGenCtz *instruction = ir_build_inst_gen<IrInstGenCtz>(&ira->new_irb, |
| 1820 | } | 1549 | source_instr->scope, source_instr->source_node); |
| 1550 | instruction->base.value->type = result_type; | ||
| 1551 | instruction->op = op; | ||
| 1821 | 1552 | ||
| 1822 | static constexpr IrInstGenId ir_inst_id(IrInstGenReturnAddress *) { | 1553 | ir_ref_inst_gen(op); |
| 1823 | return IrInstGenIdReturnAddress; | ||
| 1824 | } | ||
| 1825 | 1554 | ||
| 1826 | static constexpr IrInstGenId ir_inst_id(IrInstGenFrameAddress *) { | 1555 | return &instruction->base; |
| 1827 | return IrInstGenIdFrameAddress; | ||
| 1828 | } | 1556 | } |
| 1829 | 1557 | ||
| 1830 | static constexpr IrInstGenId ir_inst_id(IrInstGenFrameHandle *) { | 1558 | static IrInstGen *ir_build_pop_count_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *result_type, |
| 1831 | return IrInstGenIdFrameHandle; | 1559 | IrInstGen *op) |
| 1832 | } | 1560 | { |
| 1561 | IrInstGenPopCount *instruction = ir_build_inst_gen<IrInstGenPopCount>(&ira->new_irb, | ||
| 1562 | source_instr->scope, source_instr->source_node); | ||
| 1563 | instruction->base.value->type = result_type; | ||
| 1564 | instruction->op = op; | ||
| 1833 | 1565 | ||
| 1834 | static constexpr IrInstGenId ir_inst_id(IrInstGenFrameSize *) { | 1566 | ir_ref_inst_gen(op); |
| 1835 | return IrInstGenIdFrameSize; | ||
| 1836 | } | ||
| 1837 | 1567 | ||
| 1838 | static constexpr IrInstGenId ir_inst_id(IrInstGenOverflowOp *) { | 1568 | return &instruction->base; |
| 1839 | return IrInstGenIdOverflowOp; | ||
| 1840 | } | 1569 | } |
| 1841 | 1570 | ||
| 1842 | static constexpr IrInstGenId ir_inst_id(IrInstGenTestErr *) { | 1571 | static IrInstGen *ir_build_bswap_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *op_type, |
| 1843 | return IrInstGenIdTestErr; | 1572 | IrInstGen *op) |
| 1844 | } | 1573 | { |
| 1574 | IrInstGenBswap *instruction = ir_build_inst_gen<IrInstGenBswap>(&ira->new_irb, | ||
| 1575 | source_instr->scope, source_instr->source_node); | ||
| 1576 | instruction->base.value->type = op_type; | ||
| 1577 | instruction->op = op; | ||
| 1845 | 1578 | ||
| 1846 | static constexpr IrInstGenId ir_inst_id(IrInstGenMulAdd *) { | 1579 | ir_ref_inst_gen(op); |
| 1847 | return IrInstGenIdMulAdd; | ||
| 1848 | } | ||
| 1849 | 1580 | ||
| 1850 | static constexpr IrInstGenId ir_inst_id(IrInstGenFloatOp *) { | 1581 | return &instruction->base; |
| 1851 | return IrInstGenIdFloatOp; | ||
| 1852 | } | 1582 | } |
| 1853 | 1583 | ||
| 1854 | static constexpr IrInstGenId ir_inst_id(IrInstGenUnwrapErrCode *) { | 1584 | static IrInstGen *ir_build_bit_reverse_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *int_type, |
| 1855 | return IrInstGenIdUnwrapErrCode; | 1585 | IrInstGen *op) |
| 1856 | } | 1586 | { |
| 1587 | IrInstGenBitReverse *instruction = ir_build_inst_gen<IrInstGenBitReverse>(&ira->new_irb, | ||
| 1588 | source_instr->scope, source_instr->source_node); | ||
| 1589 | instruction->base.value->type = int_type; | ||
| 1590 | instruction->op = op; | ||
| 1857 | 1591 | ||
| 1858 | static constexpr IrInstGenId ir_inst_id(IrInstGenUnwrapErrPayload *) { | 1592 | ir_ref_inst_gen(op); |
| 1859 | return IrInstGenIdUnwrapErrPayload; | ||
| 1860 | } | ||
| 1861 | 1593 | ||
| 1862 | static constexpr IrInstGenId ir_inst_id(IrInstGenErrWrapCode *) { | 1594 | return &instruction->base; |
| 1863 | return IrInstGenIdErrWrapCode; | ||
| 1864 | } | 1595 | } |
| 1865 | 1596 | ||
| 1866 | static constexpr IrInstGenId ir_inst_id(IrInstGenErrWrapPayload *) { | 1597 | static IrInstGenSwitchBr *ir_build_switch_br_gen(IrAnalyze *ira, IrInst *source_instr, |
| 1867 | return IrInstGenIdErrWrapPayload; | 1598 | IrInstGen *target_value, IrBasicBlockGen *else_block, size_t case_count, IrInstGenSwitchBrCase *cases) |
| 1868 | } | 1599 | { |
| 1600 | IrInstGenSwitchBr *instruction = ir_build_inst_noreturn<IrInstGenSwitchBr>(&ira->new_irb, | ||
| 1601 | source_instr->scope, source_instr->source_node); | ||
| 1602 | instruction->target_value = target_value; | ||
| 1603 | instruction->else_block = else_block; | ||
| 1604 | instruction->case_count = case_count; | ||
| 1605 | instruction->cases = cases; | ||
| 1869 | 1606 | ||
| 1870 | static constexpr IrInstGenId ir_inst_id(IrInstGenPtrCast *) { | 1607 | ir_ref_inst_gen(target_value); |
| 1871 | return IrInstGenIdPtrCast; | ||
| 1872 | } | ||
| 1873 | 1608 | ||
| 1874 | static constexpr IrInstGenId ir_inst_id(IrInstGenBitCast *) { | 1609 | for (size_t i = 0; i < case_count; i += 1) { |
| 1875 | return IrInstGenIdBitCast; | 1610 | ir_ref_inst_gen(cases[i].value); |
| 1876 | } | 1611 | } |
| 1877 | 1612 | ||
| 1878 | static constexpr IrInstGenId ir_inst_id(IrInstGenWidenOrShorten *) { | 1613 | return instruction; |
| 1879 | return IrInstGenIdWidenOrShorten; | ||
| 1880 | } | 1614 | } |
| 1881 | 1615 | ||
| 1882 | static constexpr IrInstGenId ir_inst_id(IrInstGenIntToPtr *) { | 1616 | static IrInstGen *ir_build_union_tag(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value, |
| 1883 | return IrInstGenIdIntToPtr; | 1617 | ZigType *tag_type) |
| 1884 | } | 1618 | { |
| 1619 | IrInstGenUnionTag *instruction = ir_build_inst_gen<IrInstGenUnionTag>(&ira->new_irb, | ||
| 1620 | source_instr->scope, source_instr->source_node); | ||
| 1621 | instruction->value = value; | ||
| 1622 | instruction->base.value->type = tag_type; | ||
| 1885 | 1623 | ||
| 1886 | static constexpr IrInstGenId ir_inst_id(IrInstGenPtrToInt *) { | 1624 | ir_ref_inst_gen(value); |
| 1887 | return IrInstGenIdPtrToInt; | ||
| 1888 | } | ||
| 1889 | 1625 | ||
| 1890 | static constexpr IrInstGenId ir_inst_id(IrInstGenIntToEnum *) { | 1626 | return &instruction->base; |
| 1891 | return IrInstGenIdIntToEnum; | ||
| 1892 | } | 1627 | } |
| 1893 | 1628 | ||
| 1894 | static constexpr IrInstGenId ir_inst_id(IrInstGenIntToErr *) { | 1629 | static IrInstGen *ir_build_ref_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type, |
| 1895 | return IrInstGenIdIntToErr; | 1630 | IrInstGen *operand, IrInstGen *result_loc) |
| 1896 | } | 1631 | { |
| 1632 | IrInstGenRef *instruction = ir_build_inst_gen<IrInstGenRef>(&ira->new_irb, | ||
| 1633 | source_instruction->scope, source_instruction->source_node); | ||
| 1634 | instruction->base.value->type = result_type; | ||
| 1635 | instruction->operand = operand; | ||
| 1636 | instruction->result_loc = result_loc; | ||
| 1897 | 1637 | ||
| 1898 | static constexpr IrInstGenId ir_inst_id(IrInstGenErrToInt *) { | 1638 | ir_ref_inst_gen(operand); |
| 1899 | return IrInstGenIdErrToInt; | 1639 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); |
| 1900 | } | ||
| 1901 | 1640 | ||
| 1902 | static constexpr IrInstGenId ir_inst_id(IrInstGenPanic *) { | 1641 | return &instruction->base; |
| 1903 | return IrInstGenIdPanic; | ||
| 1904 | } | 1642 | } |
| 1905 | 1643 | ||
| 1906 | static constexpr IrInstGenId ir_inst_id(IrInstGenTagName *) { | 1644 | static IrInstGen *ir_build_err_name_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value, |
| 1907 | return IrInstGenIdTagName; | 1645 | ZigType *str_type) |
| 1908 | } | 1646 | { |
| 1647 | IrInstGenErrName *instruction = ir_build_inst_gen<IrInstGenErrName>(&ira->new_irb, | ||
| 1648 | source_instr->scope, source_instr->source_node); | ||
| 1649 | instruction->base.value->type = str_type; | ||
| 1650 | instruction->value = value; | ||
| 1909 | 1651 | ||
| 1910 | static constexpr IrInstGenId ir_inst_id(IrInstGenFieldParentPtr *) { | 1652 | ir_ref_inst_gen(value); |
| 1911 | return IrInstGenIdFieldParentPtr; | ||
| 1912 | } | ||
| 1913 | 1653 | ||
| 1914 | static constexpr IrInstGenId ir_inst_id(IrInstGenAlignCast *) { | 1654 | return &instruction->base; |
| 1915 | return IrInstGenIdAlignCast; | ||
| 1916 | } | 1655 | } |
| 1917 | 1656 | ||
| 1918 | static constexpr IrInstGenId ir_inst_id(IrInstGenErrorReturnTrace *) { | 1657 | static IrInstGen *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type, |
| 1919 | return IrInstGenIdErrorReturnTrace; | 1658 | IrInstGen *ptr, IrInstGen *cmp_value, IrInstGen *new_value, |
| 1920 | } | 1659 | AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, IrInstGen *result_loc) |
| 1660 | { | ||
| 1661 | IrInstGenCmpxchg *instruction = ir_build_inst_gen<IrInstGenCmpxchg>(&ira->new_irb, | ||
| 1662 | source_instruction->scope, source_instruction->source_node); | ||
| 1663 | instruction->base.value->type = result_type; | ||
| 1664 | instruction->ptr = ptr; | ||
| 1665 | instruction->cmp_value = cmp_value; | ||
| 1666 | instruction->new_value = new_value; | ||
| 1667 | instruction->success_order = success_order; | ||
| 1668 | instruction->failure_order = failure_order; | ||
| 1669 | instruction->is_weak = is_weak; | ||
| 1670 | instruction->result_loc = result_loc; | ||
| 1921 | 1671 | ||
| 1922 | static constexpr IrInstGenId ir_inst_id(IrInstGenAtomicRmw *) { | 1672 | ir_ref_inst_gen(ptr); |
| 1923 | return IrInstGenIdAtomicRmw; | 1673 | ir_ref_inst_gen(cmp_value); |
| 1924 | } | 1674 | ir_ref_inst_gen(new_value); |
| 1675 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); | ||
| 1925 | 1676 | ||
| 1926 | static constexpr IrInstGenId ir_inst_id(IrInstGenAtomicLoad *) { | 1677 | return &instruction->base; |
| 1927 | return IrInstGenIdAtomicLoad; | ||
| 1928 | } | 1678 | } |
| 1929 | 1679 | ||
| 1930 | static constexpr IrInstGenId ir_inst_id(IrInstGenAtomicStore *) { | 1680 | static IrInstGen *ir_build_fence_gen(IrAnalyze *ira, IrInst *source_instr, AtomicOrder order) { |
| 1931 | return IrInstGenIdAtomicStore; | 1681 | IrInstGenFence *instruction = ir_build_inst_void<IrInstGenFence>(&ira->new_irb, |
| 1932 | } | 1682 | source_instr->scope, source_instr->source_node); |
| 1683 | instruction->order = order; | ||
| 1933 | 1684 | ||
| 1934 | static constexpr IrInstGenId ir_inst_id(IrInstGenSaveErrRetAddr *) { | 1685 | return &instruction->base; |
| 1935 | return IrInstGenIdSaveErrRetAddr; | ||
| 1936 | } | 1686 | } |
| 1937 | 1687 | ||
| 1938 | static constexpr IrInstGenId ir_inst_id(IrInstGenVectorToArray *) { | 1688 | static IrInstGen *ir_build_reduce_gen(IrAnalyze *ira, IrInst *source_instruction, ReduceOp op, IrInstGen *value, ZigType *result_type) { |
| 1939 | return IrInstGenIdVectorToArray; | 1689 | IrInstGenReduce *instruction = ir_build_inst_gen<IrInstGenReduce>(&ira->new_irb, |
| 1940 | } | 1690 | source_instruction->scope, source_instruction->source_node); |
| 1941 | 1691 | instruction->base.value->type = result_type; | |
| 1942 | static constexpr IrInstGenId ir_inst_id(IrInstGenArrayToVector *) { | 1692 | instruction->op = op; |
| 1943 | return IrInstGenIdArrayToVector; | 1693 | instruction->value = value; |
| 1944 | } | ||
| 1945 | 1694 | ||
| 1946 | static constexpr IrInstGenId ir_inst_id(IrInstGenAssertZero *) { | 1695 | ir_ref_inst_gen(value); |
| 1947 | return IrInstGenIdAssertZero; | ||
| 1948 | } | ||
| 1949 | 1696 | ||
| 1950 | static constexpr IrInstGenId ir_inst_id(IrInstGenAssertNonNull *) { | 1697 | return &instruction->base; |
| 1951 | return IrInstGenIdAssertNonNull; | ||
| 1952 | } | 1698 | } |
| 1953 | 1699 | ||
| 1954 | static constexpr IrInstGenId ir_inst_id(IrInstGenPtrOfArrayToSlice *) { | 1700 | static void ir_set_cursor_at_end_gen(IrBuilderGen *irb, IrBasicBlockGen *basic_block) { |
| 1955 | return IrInstGenIdPtrOfArrayToSlice; | 1701 | assert(basic_block); |
| 1702 | irb->current_basic_block = basic_block; | ||
| 1956 | } | 1703 | } |
| 1957 | 1704 | ||
| 1958 | static constexpr IrInstGenId ir_inst_id(IrInstGenSuspendBegin *) { | 1705 | static void ir_append_basic_block_gen(IrBuilderGen *irb, IrBasicBlockGen *bb) { |
| 1959 | return IrInstGenIdSuspendBegin; | 1706 | assert(!bb->already_appended); |
| 1707 | bb->already_appended = true; | ||
| 1708 | irb->exec->basic_block_list.append(bb); | ||
| 1960 | } | 1709 | } |
| 1961 | 1710 | ||
| 1962 | static constexpr IrInstGenId ir_inst_id(IrInstGenSuspendFinish *) { | 1711 | static void ir_set_cursor_at_end_and_append_block_gen(IrBuilderGen *irb, IrBasicBlockGen *basic_block) { |
| 1963 | return IrInstGenIdSuspendFinish; | 1712 | ir_append_basic_block_gen(irb, basic_block); |
| 1713 | ir_set_cursor_at_end_gen(irb, basic_block); | ||
| 1964 | } | 1714 | } |
| 1965 | 1715 | ||
| 1966 | static constexpr IrInstGenId ir_inst_id(IrInstGenAwait *) { | 1716 | static IrInstGen *ir_build_suspend_begin_gen(IrAnalyze *ira, IrInst *source_instr) { |
| 1967 | return IrInstGenIdAwait; | 1717 | IrInstGenSuspendBegin *inst = ir_build_inst_void<IrInstGenSuspendBegin>(&ira->new_irb, |
| 1718 | source_instr->scope, source_instr->source_node); | ||
| 1719 | return &inst->base; | ||
| 1968 | } | 1720 | } |
| 1969 | 1721 | ||
| 1970 | static constexpr IrInstGenId ir_inst_id(IrInstGenResume *) { | 1722 | static IrInstGen *ir_build_save_err_ret_addr_gen(IrAnalyze *ira, IrInst *source_instr) { |
| 1971 | return IrInstGenIdResume; | 1723 | IrInstGenSaveErrRetAddr *inst = ir_build_inst_void<IrInstGenSaveErrRetAddr>(&ira->new_irb, |
| 1724 | source_instr->scope, source_instr->source_node); | ||
| 1725 | return &inst->base; | ||
| 1972 | } | 1726 | } |
| 1973 | 1727 | ||
| 1974 | static constexpr IrInstGenId ir_inst_id(IrInstGenSpillBegin *) { | 1728 | static IrInstGen *ir_build_truncate_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *dest_type, |
| 1975 | return IrInstGenIdSpillBegin; | 1729 | IrInstGen *target) |
| 1976 | } | 1730 | { |
| 1731 | IrInstGenTruncate *instruction = ir_build_inst_gen<IrInstGenTruncate>(&ira->new_irb, | ||
| 1732 | source_instr->scope, source_instr->source_node); | ||
| 1733 | instruction->base.value->type = dest_type; | ||
| 1734 | instruction->target = target; | ||
| 1977 | 1735 | ||
| 1978 | static constexpr IrInstGenId ir_inst_id(IrInstGenSpillEnd *) { | 1736 | ir_ref_inst_gen(target); |
| 1979 | return IrInstGenIdSpillEnd; | ||
| 1980 | } | ||
| 1981 | 1737 | ||
| 1982 | static constexpr IrInstGenId ir_inst_id(IrInstGenVectorExtractElem *) { | 1738 | return &instruction->base; |
| 1983 | return IrInstGenIdVectorExtractElem; | ||
| 1984 | } | 1739 | } |
| 1985 | 1740 | ||
| 1986 | static constexpr IrInstGenId ir_inst_id(IrInstGenAlloca *) { | 1741 | static IrInstGen *ir_build_shuffle_vector_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, |
| 1987 | return IrInstGenIdAlloca; | 1742 | ZigType *result_type, IrInstGen *a, IrInstGen *b, IrInstGen *mask) |
| 1988 | } | 1743 | { |
| 1744 | IrInstGenShuffleVector *inst = ir_build_inst_gen<IrInstGenShuffleVector>(&ira->new_irb, scope, source_node); | ||
| 1745 | inst->base.value->type = result_type; | ||
| 1746 | inst->a = a; | ||
| 1747 | inst->b = b; | ||
| 1748 | inst->mask = mask; | ||
| 1989 | 1749 | ||
| 1990 | static constexpr IrInstGenId ir_inst_id(IrInstGenConst *) { | 1750 | ir_ref_inst_gen(a); |
| 1991 | return IrInstGenIdConst; | 1751 | ir_ref_inst_gen(b); |
| 1992 | } | 1752 | ir_ref_inst_gen(mask); |
| 1993 | 1753 | ||
| 1994 | static constexpr IrInstGenId ir_inst_id(IrInstGenWasmMemorySize *) { | 1754 | return &inst->base; |
| 1995 | return IrInstGenIdWasmMemorySize; | ||
| 1996 | } | 1755 | } |
| 1997 | 1756 | ||
| 1998 | static constexpr IrInstGenId ir_inst_id(IrInstGenWasmMemoryGrow *) { | 1757 | static IrInstGen *ir_build_splat_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type, |
| 1999 | return IrInstGenIdWasmMemoryGrow; | 1758 | IrInstGen *scalar) |
| 2000 | } | 1759 | { |
| 1760 | IrInstGenSplat *instruction = ir_build_inst_gen<IrInstGenSplat>( | ||
| 1761 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 1762 | instruction->base.value->type = result_type; | ||
| 1763 | instruction->scalar = scalar; | ||
| 2001 | 1764 | ||
| 2002 | static constexpr IrInstGenId ir_inst_id(IrInstGenExtern *) { | 1765 | ir_ref_inst_gen(scalar); |
| 2003 | return IrInstGenIdExtern; | ||
| 2004 | } | ||
| 2005 | 1766 | ||
| 2006 | template<typename T> | 1767 | return &instruction->base; |
| 2007 | static T *ir_create_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | ||
| 2008 | T *special_instruction = heap::c_allocator.create<T>(); | ||
| 2009 | special_instruction->base.id = ir_inst_id(special_instruction); | ||
| 2010 | special_instruction->base.base.scope = scope; | ||
| 2011 | special_instruction->base.base.source_node = source_node; | ||
| 2012 | special_instruction->base.base.debug_id = exec_next_debug_id(irb->exec); | ||
| 2013 | special_instruction->base.owner_bb = irb->current_basic_block; | ||
| 2014 | return special_instruction; | ||
| 2015 | } | 1768 | } |
| 2016 | 1769 | ||
| 2017 | template<typename T> | 1770 | static IrInstGen *ir_build_bool_not_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value) { |
| 2018 | static T *ir_create_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { | 1771 | IrInstGenBoolNot *instruction = ir_build_inst_gen<IrInstGenBoolNot>(&ira->new_irb, |
| 2019 | T *special_instruction = heap::c_allocator.create<T>(); | 1772 | source_instr->scope, source_instr->source_node); |
| 2020 | special_instruction->base.id = ir_inst_id(special_instruction); | 1773 | instruction->base.value->type = ira->codegen->builtin_types.entry_bool; |
| 2021 | special_instruction->base.base.scope = scope; | 1774 | instruction->value = value; |
| 2022 | special_instruction->base.base.source_node = source_node; | ||
| 2023 | special_instruction->base.base.debug_id = exec_next_debug_id_gen(irb->exec); | ||
| 2024 | special_instruction->base.owner_bb = irb->current_basic_block; | ||
| 2025 | special_instruction->base.value = irb->codegen->pass1_arena->create<ZigValue>(); | ||
| 2026 | return special_instruction; | ||
| 2027 | } | ||
| 2028 | 1775 | ||
| 2029 | template<typename T> | 1776 | ir_ref_inst_gen(value); |
| 2030 | static T *ir_create_inst_noval(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { | ||
| 2031 | T *special_instruction = heap::c_allocator.create<T>(); | ||
| 2032 | special_instruction->base.id = ir_inst_id(special_instruction); | ||
| 2033 | special_instruction->base.base.scope = scope; | ||
| 2034 | special_instruction->base.base.source_node = source_node; | ||
| 2035 | special_instruction->base.base.debug_id = exec_next_debug_id_gen(irb->exec); | ||
| 2036 | special_instruction->base.owner_bb = irb->current_basic_block; | ||
| 2037 | return special_instruction; | ||
| 2038 | } | ||
| 2039 | 1777 | ||
| 2040 | template<typename T> | 1778 | return &instruction->base; |
| 2041 | static T *ir_build_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | ||
| 2042 | T *special_instruction = ir_create_instruction<T>(irb, scope, source_node); | ||
| 2043 | ir_instruction_append(irb->current_basic_block, &special_instruction->base); | ||
| 2044 | return special_instruction; | ||
| 2045 | } | 1779 | } |
| 2046 | 1780 | ||
| 2047 | template<typename T> | 1781 | static IrInstGen *ir_build_memset_gen(IrAnalyze *ira, IrInst *source_instr, |
| 2048 | static T *ir_build_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { | 1782 | IrInstGen *dest_ptr, IrInstGen *byte, IrInstGen *count) |
| 2049 | T *special_instruction = ir_create_inst_gen<T>(irb, scope, source_node); | 1783 | { |
| 2050 | ir_inst_gen_append(irb->current_basic_block, &special_instruction->base); | 1784 | IrInstGenMemset *instruction = ir_build_inst_void<IrInstGenMemset>(&ira->new_irb, |
| 2051 | return special_instruction; | 1785 | source_instr->scope, source_instr->source_node); |
| 2052 | } | 1786 | instruction->dest_ptr = dest_ptr; |
| 1787 | instruction->byte = byte; | ||
| 1788 | instruction->count = count; | ||
| 2053 | 1789 | ||
| 2054 | template<typename T> | 1790 | ir_ref_inst_gen(dest_ptr); |
| 2055 | static T *ir_build_inst_noreturn(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { | 1791 | ir_ref_inst_gen(byte); |
| 2056 | T *special_instruction = ir_create_inst_noval<T>(irb, scope, source_node); | 1792 | ir_ref_inst_gen(count); |
| 2057 | special_instruction->base.value = irb->codegen->intern.for_unreachable(); | ||
| 2058 | ir_inst_gen_append(irb->current_basic_block, &special_instruction->base); | ||
| 2059 | return special_instruction; | ||
| 2060 | } | ||
| 2061 | 1793 | ||
| 2062 | template<typename T> | 1794 | return &instruction->base; |
| 2063 | static T *ir_build_inst_void(IrBuilderGen *irb, Scope *scope, AstNode *source_node) { | ||
| 2064 | T *special_instruction = ir_create_inst_noval<T>(irb, scope, source_node); | ||
| 2065 | special_instruction->base.value = irb->codegen->intern.for_void(); | ||
| 2066 | ir_inst_gen_append(irb->current_basic_block, &special_instruction->base); | ||
| 2067 | return special_instruction; | ||
| 2068 | } | 1795 | } |
| 2069 | 1796 | ||
| 2070 | IrInstGen *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, | 1797 | static IrInstGen *ir_build_memcpy_gen(IrAnalyze *ira, IrInst *source_instr, |
| 2071 | ZigType *var_type, const char *name_hint) | 1798 | IrInstGen *dest_ptr, IrInstGen *src_ptr, IrInstGen *count) |
| 2072 | { | 1799 | { |
| 2073 | IrInstGenAlloca *alloca_gen = heap::c_allocator.create<IrInstGenAlloca>(); | 1800 | IrInstGenMemcpy *instruction = ir_build_inst_void<IrInstGenMemcpy>(&ira->new_irb, |
| 2074 | alloca_gen->base.id = IrInstGenIdAlloca; | 1801 | source_instr->scope, source_instr->source_node); |
| 2075 | alloca_gen->base.base.source_node = source_node; | 1802 | instruction->dest_ptr = dest_ptr; |
| 2076 | alloca_gen->base.base.scope = scope; | 1803 | instruction->src_ptr = src_ptr; |
| 2077 | alloca_gen->base.value = g->pass1_arena->create<ZigValue>(); | 1804 | instruction->count = count; |
| 2078 | alloca_gen->base.value->type = get_pointer_to_type(g, var_type, false); | 1805 | |
| 2079 | alloca_gen->base.base.ref_count = 1; | 1806 | ir_ref_inst_gen(dest_ptr); |
| 2080 | alloca_gen->name_hint = name_hint; | 1807 | ir_ref_inst_gen(src_ptr); |
| 2081 | fn->alloca_gen_list.append(alloca_gen); | 1808 | ir_ref_inst_gen(count); |
| 2082 | return &alloca_gen->base; | 1809 | |
| 1810 | return &instruction->base; | ||
| 2083 | } | 1811 | } |
| 2084 | 1812 | ||
| 2085 | static IrInstGen *ir_build_cast(IrAnalyze *ira, IrInst *source_instr,ZigType *dest_type, | 1813 | static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *slice_type, |
| 2086 | IrInstGen *value, CastOp cast_op) | 1814 | IrInstGen *ptr, IrInstGen *start, IrInstGen *end, bool safety_check_on, IrInstGen *result_loc, |
| 1815 | ZigValue *sentinel) | ||
| 2087 | { | 1816 | { |
| 2088 | IrInstGenCast *inst = ir_build_inst_gen<IrInstGenCast>(&ira->new_irb, source_instr->scope, source_instr->source_node); | 1817 | IrInstGenSlice *instruction = ir_build_inst_gen<IrInstGenSlice>( |
| 2089 | inst->base.value->type = dest_type; | 1818 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); |
| 2090 | inst->value = value; | 1819 | instruction->base.value->type = slice_type; |
| 2091 | inst->cast_op = cast_op; | 1820 | instruction->ptr = ptr; |
| 1821 | instruction->start = start; | ||
| 1822 | instruction->end = end; | ||
| 1823 | instruction->safety_check_on = safety_check_on; | ||
| 1824 | instruction->result_loc = result_loc; | ||
| 1825 | instruction->sentinel = sentinel; | ||
| 2092 | 1826 | ||
| 2093 | ir_ref_inst_gen(value); | 1827 | ir_ref_inst_gen(ptr); |
| 1828 | ir_ref_inst_gen(start); | ||
| 1829 | if (end != nullptr) ir_ref_inst_gen(end); | ||
| 1830 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); | ||
| 2094 | 1831 | ||
| 2095 | return &inst->base; | 1832 | return &instruction->base; |
| 2096 | } | 1833 | } |
| 2097 | 1834 | ||
| 2098 | static IrInstSrc *ir_build_cond_br(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *condition, | 1835 | static IrInstGen *ir_build_breakpoint_gen(IrAnalyze *ira, IrInst *source_instr) { |
| 2099 | IrBasicBlockSrc *then_block, IrBasicBlockSrc *else_block, IrInstSrc *is_comptime) | 1836 | IrInstGenBreakpoint *instruction = ir_build_inst_void<IrInstGenBreakpoint>(&ira->new_irb, |
| 2100 | { | 1837 | source_instr->scope, source_instr->source_node); |
| 2101 | IrInstSrcCondBr *inst = ir_build_instruction<IrInstSrcCondBr>(irb, scope, source_node); | 1838 | return &instruction->base; |
| 2102 | inst->base.is_noreturn = true; | 1839 | } |
| 2103 | inst->condition = condition; | ||
| 2104 | inst->then_block = then_block; | ||
| 2105 | inst->else_block = else_block; | ||
| 2106 | inst->is_comptime = is_comptime; | ||
| 2107 | |||
| 2108 | ir_ref_instruction(condition, irb->current_basic_block); | ||
| 2109 | ir_ref_bb(then_block); | ||
| 2110 | ir_ref_bb(else_block); | ||
| 2111 | if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block); | ||
| 2112 | 1840 | ||
| 1841 | static IrInstGen *ir_build_return_address_gen(IrAnalyze *ira, IrInst *source_instr) { | ||
| 1842 | IrInstGenReturnAddress *inst = ir_build_inst_gen<IrInstGenReturnAddress>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 1843 | inst->base.value->type = ira->codegen->builtin_types.entry_usize; | ||
| 2113 | return &inst->base; | 1844 | return &inst->base; |
| 2114 | } | 1845 | } |
| 2115 | 1846 | ||
| 2116 | static IrInstGen *ir_build_cond_br_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *condition, | 1847 | static IrInstGen *ir_build_frame_address_gen(IrAnalyze *ira, IrInst *source_instr) { |
| 2117 | IrBasicBlockGen *then_block, IrBasicBlockGen *else_block) | 1848 | IrInstGenFrameAddress *inst = ir_build_inst_gen<IrInstGenFrameAddress>(&ira->new_irb, source_instr->scope, source_instr->source_node); |
| 2118 | { | 1849 | inst->base.value->type = ira->codegen->builtin_types.entry_usize; |
| 2119 | IrInstGenCondBr *inst = ir_build_inst_noreturn<IrInstGenCondBr>(&ira->new_irb, source_instr->scope, source_instr->source_node); | 1850 | return &inst->base; |
| 2120 | inst->condition = condition; | 1851 | } |
| 2121 | inst->then_block = then_block; | ||
| 2122 | inst->else_block = else_block; | ||
| 2123 | |||
| 2124 | ir_ref_inst_gen(condition); | ||
| 2125 | 1852 | ||
| 1853 | static IrInstGen *ir_build_handle_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *ty) { | ||
| 1854 | IrInstGenFrameHandle *inst = ir_build_inst_gen<IrInstGenFrameHandle>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 1855 | inst->base.value->type = ty; | ||
| 2126 | return &inst->base; | 1856 | return &inst->base; |
| 2127 | } | 1857 | } |
| 2128 | 1858 | ||
| 2129 | static IrInstSrc *ir_build_return_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *operand) { | 1859 | static IrInstGen *ir_build_frame_size_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *fn) |
| 2130 | IrInstSrcReturn *inst = ir_build_instruction<IrInstSrcReturn>(irb, scope, source_node); | 1860 | { |
| 2131 | inst->base.is_noreturn = true; | 1861 | IrInstGenFrameSize *inst = ir_build_inst_gen<IrInstGenFrameSize>(&ira->new_irb, source_instr->scope, source_instr->source_node); |
| 2132 | inst->operand = operand; | 1862 | inst->base.value->type = ira->codegen->builtin_types.entry_usize; |
| 1863 | inst->fn = fn; | ||
| 2133 | 1864 | ||
| 2134 | if (operand != nullptr) ir_ref_instruction(operand, irb->current_basic_block); | 1865 | ir_ref_inst_gen(fn); |
| 2135 | 1866 | ||
| 2136 | return &inst->base; | 1867 | return &inst->base; |
| 2137 | } | 1868 | } |
| 2138 | 1869 | ||
| 2139 | static IrInstGen *ir_build_return_gen(IrAnalyze *ira, IrInst *source_inst, IrInstGen *operand) { | 1870 | static IrInstGen *ir_build_overflow_op_gen(IrAnalyze *ira, IrInst *source_instr, |
| 2140 | IrInstGenReturn *inst = ir_build_inst_noreturn<IrInstGenReturn>(&ira->new_irb, | 1871 | IrOverflowOp op, IrInstGen *op1, IrInstGen *op2, IrInstGen *result_ptr, |
| 2141 | source_inst->scope, source_inst->source_node); | 1872 | ZigType *result_ptr_type) |
| 2142 | inst->operand = operand; | 1873 | { |
| 2143 | 1874 | IrInstGenOverflowOp *instruction = ir_build_inst_gen<IrInstGenOverflowOp>(&ira->new_irb, | |
| 2144 | if (operand != nullptr) ir_ref_inst_gen(operand); | 1875 | source_instr->scope, source_instr->source_node); |
| 2145 | 1876 | instruction->base.value->type = ira->codegen->builtin_types.entry_bool; | |
| 2146 | return &inst->base; | 1877 | instruction->op = op; |
| 2147 | } | 1878 | instruction->op1 = op1; |
| 2148 | 1879 | instruction->op2 = op2; | |
| 2149 | static IrInstSrc *ir_build_const_void(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | 1880 | instruction->result_ptr = result_ptr; |
| 2150 | IrInstSrcConst *const_instruction = ir_create_instruction<IrInstSrcConst>(irb, scope, source_node); | 1881 | instruction->result_ptr_type = result_ptr_type; |
| 2151 | ir_instruction_append(irb->current_basic_block, &const_instruction->base); | ||
| 2152 | const_instruction->value = irb->codegen->intern.for_void(); | ||
| 2153 | return &const_instruction->base; | ||
| 2154 | } | ||
| 2155 | |||
| 2156 | static IrInstSrc *ir_build_const_undefined(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | ||
| 2157 | IrInstSrcConst *const_instruction = ir_create_instruction<IrInstSrcConst>(irb, scope, source_node); | ||
| 2158 | ir_instruction_append(irb->current_basic_block, &const_instruction->base); | ||
| 2159 | const_instruction->value = irb->codegen->intern.for_undefined(); | ||
| 2160 | const_instruction->value->special = ConstValSpecialUndef; | ||
| 2161 | return &const_instruction->base; | ||
| 2162 | } | ||
| 2163 | |||
| 2164 | static IrInstSrc *ir_build_const_uint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, uint64_t value) { | ||
| 2165 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(irb, scope, source_node); | ||
| 2166 | const_instruction->value = irb->codegen->pass1_arena->create<ZigValue>(); | ||
| 2167 | const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_int; | ||
| 2168 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 2169 | bigint_init_unsigned(&const_instruction->value->data.x_bigint, value); | ||
| 2170 | return &const_instruction->base; | ||
| 2171 | } | ||
| 2172 | 1882 | ||
| 2173 | static IrInstSrc *ir_build_const_bigint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, BigInt *bigint) { | 1883 | ir_ref_inst_gen(op1); |
| 2174 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(irb, scope, source_node); | 1884 | ir_ref_inst_gen(op2); |
| 2175 | const_instruction->value = irb->codegen->pass1_arena->create<ZigValue>(); | 1885 | ir_ref_inst_gen(result_ptr); |
| 2176 | const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_int; | ||
| 2177 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 2178 | bigint_init_bigint(&const_instruction->value->data.x_bigint, bigint); | ||
| 2179 | return &const_instruction->base; | ||
| 2180 | } | ||
| 2181 | 1886 | ||
| 2182 | static IrInstSrc *ir_build_const_bigfloat(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, BigFloat *bigfloat) { | 1887 | return &instruction->base; |
| 2183 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(irb, scope, source_node); | ||
| 2184 | const_instruction->value = irb->codegen->pass1_arena->create<ZigValue>(); | ||
| 2185 | const_instruction->value->type = irb->codegen->builtin_types.entry_num_lit_float; | ||
| 2186 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 2187 | bigfloat_init_bigfloat(&const_instruction->value->data.x_bigfloat, bigfloat); | ||
| 2188 | return &const_instruction->base; | ||
| 2189 | } | 1888 | } |
| 2190 | 1889 | ||
| 2191 | static IrInstSrc *ir_build_const_null(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | 1890 | static IrInstGen *ir_build_float_op_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, |
| 2192 | IrInstSrcConst *const_instruction = ir_create_instruction<IrInstSrcConst>(irb, scope, source_node); | 1891 | BuiltinFnId fn_id, ZigType *operand_type) |
| 2193 | ir_instruction_append(irb->current_basic_block, &const_instruction->base); | 1892 | { |
| 2194 | const_instruction->value = irb->codegen->intern.for_null(); | 1893 | IrInstGenFloatOp *instruction = ir_build_inst_gen<IrInstGenFloatOp>(&ira->new_irb, |
| 2195 | return &const_instruction->base; | 1894 | source_instr->scope, source_instr->source_node); |
| 2196 | } | 1895 | instruction->base.value->type = operand_type; |
| 1896 | instruction->operand = operand; | ||
| 1897 | instruction->fn_id = fn_id; | ||
| 2197 | 1898 | ||
| 2198 | static IrInstSrc *ir_build_const_usize(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, uint64_t value) { | 1899 | ir_ref_inst_gen(operand); |
| 2199 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(irb, scope, source_node); | ||
| 2200 | const_instruction->value = irb->codegen->pass1_arena->create<ZigValue>(); | ||
| 2201 | const_instruction->value->type = irb->codegen->builtin_types.entry_usize; | ||
| 2202 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 2203 | bigint_init_unsigned(&const_instruction->value->data.x_bigint, value); | ||
| 2204 | return &const_instruction->base; | ||
| 2205 | } | ||
| 2206 | 1900 | ||
| 2207 | static IrInstSrc *ir_create_const_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | 1901 | return &instruction->base; |
| 2208 | ZigType *type_entry) | ||
| 2209 | { | ||
| 2210 | IrInstSrcConst *const_instruction = ir_create_instruction<IrInstSrcConst>(irb, scope, source_node); | ||
| 2211 | const_instruction->value = irb->codegen->pass1_arena->create<ZigValue>(); | ||
| 2212 | const_instruction->value->type = irb->codegen->builtin_types.entry_type; | ||
| 2213 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 2214 | const_instruction->value->data.x_type = type_entry; | ||
| 2215 | return &const_instruction->base; | ||
| 2216 | } | 1902 | } |
| 2217 | 1903 | ||
| 2218 | static IrInstSrc *ir_build_const_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | 1904 | static IrInstGen *ir_build_mul_add_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *op1, IrInstGen *op2, |
| 2219 | ZigType *type_entry) | 1905 | IrInstGen *op3, ZigType *expr_type) |
| 2220 | { | 1906 | { |
| 2221 | IrInstSrc *instruction = ir_create_const_type(irb, scope, source_node, type_entry); | 1907 | IrInstGenMulAdd *instruction = ir_build_inst_gen<IrInstGenMulAdd>(&ira->new_irb, |
| 2222 | ir_instruction_append(irb->current_basic_block, instruction); | 1908 | source_instr->scope, source_instr->source_node); |
| 2223 | return instruction; | 1909 | instruction->base.value->type = expr_type; |
| 2224 | } | 1910 | instruction->op1 = op1; |
| 2225 | 1911 | instruction->op2 = op2; | |
| 2226 | static IrInstSrc *ir_build_const_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigType *import) { | 1912 | instruction->op3 = op3; |
| 2227 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(irb, scope, source_node); | ||
| 2228 | const_instruction->value = irb->codegen->pass1_arena->create<ZigValue>(); | ||
| 2229 | const_instruction->value->type = irb->codegen->builtin_types.entry_type; | ||
| 2230 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 2231 | const_instruction->value->data.x_type = import; | ||
| 2232 | return &const_instruction->base; | ||
| 2233 | } | ||
| 2234 | 1913 | ||
| 2235 | static IrInstSrc *ir_build_const_bool(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, bool value) { | 1914 | ir_ref_inst_gen(op1); |
| 2236 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(irb, scope, source_node); | 1915 | ir_ref_inst_gen(op2); |
| 2237 | const_instruction->value = irb->codegen->pass1_arena->create<ZigValue>(); | 1916 | ir_ref_inst_gen(op3); |
| 2238 | const_instruction->value->type = irb->codegen->builtin_types.entry_bool; | ||
| 2239 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 2240 | const_instruction->value->data.x_bool = value; | ||
| 2241 | return &const_instruction->base; | ||
| 2242 | } | ||
| 2243 | 1917 | ||
| 2244 | static IrInstSrc *ir_build_const_enum_literal(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *name) { | 1918 | return &instruction->base; |
| 2245 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(irb, scope, source_node); | ||
| 2246 | const_instruction->value = irb->codegen->pass1_arena->create<ZigValue>(); | ||
| 2247 | const_instruction->value->type = irb->codegen->builtin_types.entry_enum_literal; | ||
| 2248 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 2249 | const_instruction->value->data.x_enum_literal = name; | ||
| 2250 | return &const_instruction->base; | ||
| 2251 | } | 1919 | } |
| 2252 | 1920 | ||
| 2253 | static IrInstSrc *ir_create_const_str_lit(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *str) { | 1921 | static IrInstGen *ir_build_test_err_gen(IrAnalyze *ira, IrInst *source_instruction, IrInstGen *err_union) { |
| 2254 | IrInstSrcConst *const_instruction = ir_create_instruction<IrInstSrcConst>(irb, scope, source_node); | 1922 | IrInstGenTestErr *instruction = ir_build_inst_gen<IrInstGenTestErr>( |
| 2255 | const_instruction->value = irb->codegen->pass1_arena->create<ZigValue>(); | 1923 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); |
| 2256 | init_const_str_lit(irb->codegen, const_instruction->value, str); | 1924 | instruction->base.value->type = ira->codegen->builtin_types.entry_bool; |
| 1925 | instruction->err_union = err_union; | ||
| 2257 | 1926 | ||
| 2258 | return &const_instruction->base; | 1927 | ir_ref_inst_gen(err_union); |
| 2259 | } | ||
| 2260 | 1928 | ||
| 2261 | static IrInstSrc *ir_build_const_str_lit(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *str) { | 1929 | return &instruction->base; |
| 2262 | IrInstSrc *instruction = ir_create_const_str_lit(irb, scope, source_node, str); | ||
| 2263 | ir_instruction_append(irb->current_basic_block, instruction); | ||
| 2264 | return instruction; | ||
| 2265 | } | 1930 | } |
| 2266 | 1931 | ||
| 2267 | static IrInstSrc *ir_build_bin_op(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrBinOp op_id, | 1932 | static IrInstGen *ir_build_unwrap_err_code_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, |
| 2268 | IrInstSrc *op1, IrInstSrc *op2, bool safety_check_on) | 1933 | IrInstGen *err_union_ptr, ZigType *result_type) |
| 2269 | { | 1934 | { |
| 2270 | IrInstSrcBinOp *inst = ir_build_instruction<IrInstSrcBinOp>(irb, scope, source_node); | 1935 | IrInstGenUnwrapErrCode *inst = ir_build_inst_gen<IrInstGenUnwrapErrCode>(&ira->new_irb, scope, source_node); |
| 2271 | inst->op_id = op_id; | 1936 | inst->base.value->type = result_type; |
| 2272 | inst->op1 = op1; | 1937 | inst->err_union_ptr = err_union_ptr; |
| 2273 | inst->op2 = op2; | ||
| 2274 | inst->safety_check_on = safety_check_on; | ||
| 2275 | 1938 | ||
| 2276 | ir_ref_instruction(op1, irb->current_basic_block); | 1939 | ir_ref_inst_gen(err_union_ptr); |
| 2277 | ir_ref_instruction(op2, irb->current_basic_block); | ||
| 2278 | 1940 | ||
| 2279 | return &inst->base; | 1941 | return &inst->base; |
| 2280 | } | 1942 | } |
| 2281 | 1943 | ||
| 2282 | static IrInstGen *ir_build_bin_op_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *res_type, | 1944 | static IrInstGen *ir_build_unwrap_err_payload_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, |
| 2283 | IrBinOp op_id, IrInstGen *op1, IrInstGen *op2, bool safety_check_on) | 1945 | IrInstGen *value, bool safety_check_on, bool initializing, ZigType *result_type) |
| 2284 | { | 1946 | { |
| 2285 | IrInstGenBinOp *inst = ir_build_inst_gen<IrInstGenBinOp>(&ira->new_irb, | 1947 | IrInstGenUnwrapErrPayload *inst = ir_build_inst_gen<IrInstGenUnwrapErrPayload>(&ira->new_irb, scope, source_node); |
| 2286 | source_instr->scope, source_instr->source_node); | 1948 | inst->base.value->type = result_type; |
| 2287 | inst->base.value->type = res_type; | 1949 | inst->value = value; |
| 2288 | inst->op_id = op_id; | ||
| 2289 | inst->op1 = op1; | ||
| 2290 | inst->op2 = op2; | ||
| 2291 | inst->safety_check_on = safety_check_on; | 1950 | inst->safety_check_on = safety_check_on; |
| 1951 | inst->initializing = initializing; | ||
| 2292 | 1952 | ||
| 2293 | ir_ref_inst_gen(op1); | 1953 | ir_ref_inst_gen(value); |
| 2294 | ir_ref_inst_gen(op2); | ||
| 2295 | 1954 | ||
| 2296 | return &inst->base; | 1955 | return &inst->base; |
| 2297 | } | 1956 | } |
| 2298 | 1957 | ||
| 2299 | 1958 | static IrInstGen *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInst *source_instruction, | |
| 2300 | static IrInstSrc *ir_build_merge_err_sets(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | 1959 | ZigType *ptr_type, IrInstGen *ptr, bool safety_check_on) |
| 2301 | IrInstSrc *op1, IrInstSrc *op2, Buf *type_name) | ||
| 2302 | { | 1960 | { |
| 2303 | IrInstSrcMergeErrSets *inst = ir_build_instruction<IrInstSrcMergeErrSets>(irb, scope, source_node); | 1961 | IrInstGenPtrCast *instruction = ir_build_inst_gen<IrInstGenPtrCast>( |
| 2304 | inst->op1 = op1; | 1962 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); |
| 2305 | inst->op2 = op2; | 1963 | instruction->base.value->type = ptr_type; |
| 2306 | inst->type_name = type_name; | 1964 | instruction->ptr = ptr; |
| 1965 | instruction->safety_check_on = safety_check_on; | ||
| 2307 | 1966 | ||
| 2308 | ir_ref_instruction(op1, irb->current_basic_block); | 1967 | ir_ref_inst_gen(ptr); |
| 2309 | ir_ref_instruction(op2, irb->current_basic_block); | ||
| 2310 | 1968 | ||
| 2311 | return &inst->base; | 1969 | return &instruction->base; |
| 2312 | } | 1970 | } |
| 2313 | 1971 | ||
| 2314 | static IrInstSrc *ir_build_var_ptr_x(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var, | 1972 | static IrInstGen *ir_build_bit_cast_gen(IrAnalyze *ira, IrInst *source_instruction, |
| 2315 | ScopeFnDef *crossed_fndef_scope) | 1973 | IrInstGen *operand, ZigType *ty) |
| 2316 | { | 1974 | { |
| 2317 | IrInstSrcVarPtr *instruction = ir_build_instruction<IrInstSrcVarPtr>(irb, scope, source_node); | 1975 | IrInstGenBitCast *instruction = ir_build_inst_gen<IrInstGenBitCast>( |
| 2318 | instruction->var = var; | 1976 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); |
| 2319 | instruction->crossed_fndef_scope = crossed_fndef_scope; | 1977 | instruction->base.value->type = ty; |
| 1978 | instruction->operand = operand; | ||
| 2320 | 1979 | ||
| 2321 | ir_ref_var(var); | 1980 | ir_ref_inst_gen(operand); |
| 2322 | 1981 | ||
| 2323 | return &instruction->base; | 1982 | return &instruction->base; |
| 2324 | } | 1983 | } |
| 2325 | 1984 | ||
| 2326 | static IrInstSrc *ir_build_var_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var) { | 1985 | static IrInstGen *ir_build_widen_or_shorten(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, |
| 2327 | return ir_build_var_ptr_x(irb, scope, source_node, var, nullptr); | 1986 | ZigType *result_type) |
| 2328 | } | 1987 | { |
| 2329 | 1988 | IrInstGenWidenOrShorten *inst = ir_build_inst_gen<IrInstGenWidenOrShorten>(&ira->new_irb, scope, source_node); | |
| 2330 | static IrInstGen *ir_build_var_ptr_gen(IrAnalyze *ira, IrInst *source_instr, ZigVar *var) { | 1989 | inst->base.value->type = result_type; |
| 2331 | IrInstGenVarPtr *instruction = ir_build_inst_gen<IrInstGenVarPtr>(&ira->new_irb, source_instr->scope, source_instr->source_node); | 1990 | inst->target = target; |
| 2332 | instruction->var = var; | ||
| 2333 | 1991 | ||
| 2334 | ir_ref_var(var); | 1992 | ir_ref_inst_gen(target); |
| 2335 | 1993 | ||
| 2336 | return &instruction->base; | 1994 | return &inst->base; |
| 2337 | } | 1995 | } |
| 2338 | 1996 | ||
| 2339 | static IrInstGen *ir_build_return_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *ty) { | 1997 | static IrInstGen *ir_build_int_to_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, |
| 2340 | IrInstGenReturnPtr *instruction = ir_build_inst_gen<IrInstGenReturnPtr>(&ira->new_irb, scope, source_node); | 1998 | IrInstGen *target, ZigType *ptr_type) |
| 2341 | instruction->base.value->type = ty; | 1999 | { |
| 2000 | IrInstGenIntToPtr *instruction = ir_build_inst_gen<IrInstGenIntToPtr>(&ira->new_irb, scope, source_node); | ||
| 2001 | instruction->base.value->type = ptr_type; | ||
| 2002 | instruction->target = target; | ||
| 2003 | |||
| 2004 | ir_ref_inst_gen(target); | ||
| 2005 | |||
| 2342 | return &instruction->base; | 2006 | return &instruction->base; |
| 2343 | } | 2007 | } |
| 2344 | 2008 | ||
| 2345 | static IrInstSrc *ir_build_elem_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | 2009 | static IrInstGen *ir_build_ptr_to_int_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target) { |
| 2346 | IrInstSrc *array_ptr, IrInstSrc *elem_index, bool safety_check_on, PtrLen ptr_len, | 2010 | IrInstGenPtrToInt *inst = ir_build_inst_gen<IrInstGenPtrToInt>(&ira->new_irb, source_instr->scope, source_instr->source_node); |
| 2347 | AstNode *init_array_type_source_node) | 2011 | inst->base.value->type = ira->codegen->builtin_types.entry_usize; |
| 2348 | { | 2012 | inst->target = target; |
| 2349 | IrInstSrcElemPtr *instruction = ir_build_instruction<IrInstSrcElemPtr>(irb, scope, source_node); | ||
| 2350 | instruction->array_ptr = array_ptr; | ||
| 2351 | instruction->elem_index = elem_index; | ||
| 2352 | instruction->safety_check_on = safety_check_on; | ||
| 2353 | instruction->ptr_len = ptr_len; | ||
| 2354 | instruction->init_array_type_source_node = init_array_type_source_node; | ||
| 2355 | 2013 | ||
| 2356 | ir_ref_instruction(array_ptr, irb->current_basic_block); | 2014 | ir_ref_inst_gen(target); |
| 2357 | ir_ref_instruction(elem_index, irb->current_basic_block); | ||
| 2358 | 2015 | ||
| 2359 | return &instruction->base; | 2016 | return &inst->base; |
| 2360 | } | 2017 | } |
| 2361 | 2018 | ||
| 2362 | static IrInstGen *ir_build_elem_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, | 2019 | static IrInstGen *ir_build_int_to_enum_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, |
| 2363 | IrInstGen *array_ptr, IrInstGen *elem_index, bool safety_check_on, ZigType *return_type) | 2020 | ZigType *dest_type, IrInstGen *target) |
| 2364 | { | 2021 | { |
| 2365 | IrInstGenElemPtr *instruction = ir_build_inst_gen<IrInstGenElemPtr>(&ira->new_irb, scope, source_node); | 2022 | IrInstGenIntToEnum *instruction = ir_build_inst_gen<IrInstGenIntToEnum>(&ira->new_irb, scope, source_node); |
| 2366 | instruction->base.value->type = return_type; | 2023 | instruction->base.value->type = dest_type; |
| 2367 | instruction->array_ptr = array_ptr; | 2024 | instruction->target = target; |
| 2368 | instruction->elem_index = elem_index; | ||
| 2369 | instruction->safety_check_on = safety_check_on; | ||
| 2370 | 2025 | ||
| 2371 | ir_ref_inst_gen(array_ptr); | 2026 | ir_ref_inst_gen(target); |
| 2372 | ir_ref_inst_gen(elem_index); | ||
| 2373 | 2027 | ||
| 2374 | return &instruction->base; | 2028 | return &instruction->base; |
| 2375 | } | 2029 | } |
| 2376 | 2030 | ||
| 2377 | static IrInstSrc *ir_build_field_ptr_instruction(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | 2031 | static IrInstGen *ir_build_int_to_err_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, |
| 2378 | IrInstSrc *container_ptr, IrInstSrc *field_name_expr, bool initializing) | 2032 | ZigType *wanted_type) |
| 2379 | { | 2033 | { |
| 2380 | IrInstSrcFieldPtr *instruction = ir_build_instruction<IrInstSrcFieldPtr>(irb, scope, source_node); | 2034 | IrInstGenIntToErr *instruction = ir_build_inst_gen<IrInstGenIntToErr>(&ira->new_irb, scope, source_node); |
| 2381 | instruction->container_ptr = container_ptr; | 2035 | instruction->base.value->type = wanted_type; |
| 2382 | instruction->field_name_buffer = nullptr; | 2036 | instruction->target = target; |
| 2383 | instruction->field_name_expr = field_name_expr; | ||
| 2384 | instruction->initializing = initializing; | ||
| 2385 | 2037 | ||
| 2386 | ir_ref_instruction(container_ptr, irb->current_basic_block); | 2038 | ir_ref_inst_gen(target); |
| 2387 | ir_ref_instruction(field_name_expr, irb->current_basic_block); | ||
| 2388 | 2039 | ||
| 2389 | return &instruction->base; | 2040 | return &instruction->base; |
| 2390 | } | 2041 | } |
| 2391 | 2042 | ||
| 2392 | static IrInstSrc *ir_build_field_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | 2043 | static IrInstGen *ir_build_err_to_int_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, |
| 2393 | IrInstSrc *container_ptr, Buf *field_name, bool initializing) | 2044 | ZigType *wanted_type) |
| 2394 | { | 2045 | { |
| 2395 | IrInstSrcFieldPtr *instruction = ir_build_instruction<IrInstSrcFieldPtr>(irb, scope, source_node); | 2046 | IrInstGenErrToInt *instruction = ir_build_inst_gen<IrInstGenErrToInt>(&ira->new_irb, scope, source_node); |
| 2396 | instruction->container_ptr = container_ptr; | 2047 | instruction->base.value->type = wanted_type; |
| 2397 | instruction->field_name_buffer = field_name; | 2048 | instruction->target = target; |
| 2398 | instruction->field_name_expr = nullptr; | ||
| 2399 | instruction->initializing = initializing; | ||
| 2400 | 2049 | ||
| 2401 | ir_ref_instruction(container_ptr, irb->current_basic_block); | 2050 | ir_ref_inst_gen(target); |
| 2402 | 2051 | ||
| 2403 | return &instruction->base; | 2052 | return &instruction->base; |
| 2404 | } | 2053 | } |
| 2405 | 2054 | ||
| 2406 | static IrInstSrc *ir_build_has_field(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | 2055 | static IrInstGen *ir_build_panic_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *msg) { |
| 2407 | IrInstSrc *container_type, IrInstSrc *field_name) | 2056 | IrInstGenPanic *instruction = ir_build_inst_noreturn<IrInstGenPanic>(&ira->new_irb, |
| 2408 | { | 2057 | source_instr->scope, source_instr->source_node); |
| 2409 | IrInstSrcHasField *instruction = ir_build_instruction<IrInstSrcHasField>(irb, scope, source_node); | 2058 | instruction->msg = msg; |
| 2410 | instruction->container_type = container_type; | ||
| 2411 | instruction->field_name = field_name; | ||
| 2412 | 2059 | ||
| 2413 | ir_ref_instruction(container_type, irb->current_basic_block); | 2060 | ir_ref_inst_gen(msg); |
| 2414 | ir_ref_instruction(field_name, irb->current_basic_block); | ||
| 2415 | 2061 | ||
| 2416 | return &instruction->base; | 2062 | return &instruction->base; |
| 2417 | } | 2063 | } |
| 2418 | 2064 | ||
| 2419 | static IrInstGen *ir_build_struct_field_ptr(IrAnalyze *ira, IrInst *source_instr, | 2065 | static IrInstGen *ir_build_tag_name_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target, |
| 2420 | IrInstGen *struct_ptr, TypeStructField *field, ZigType *ptr_type) | 2066 | ZigType *result_type) |
| 2421 | { | 2067 | { |
| 2422 | IrInstGenStructFieldPtr *inst = ir_build_inst_gen<IrInstGenStructFieldPtr>(&ira->new_irb, source_instr->scope, source_instr->source_node); | 2068 | IrInstGenTagName *instruction = ir_build_inst_gen<IrInstGenTagName>(&ira->new_irb, |
| 2423 | inst->base.value->type = ptr_type; | 2069 | source_instr->scope, source_instr->source_node); |
| 2424 | inst->struct_ptr = struct_ptr; | 2070 | instruction->base.value->type = result_type; |
| 2425 | inst->field = field; | 2071 | instruction->target = target; |
| 2426 | 2072 | ||
| 2427 | ir_ref_inst_gen(struct_ptr); | 2073 | ir_ref_inst_gen(target); |
| 2428 | 2074 | ||
| 2429 | return &inst->base; | 2075 | return &instruction->base; |
| 2430 | } | 2076 | } |
| 2431 | 2077 | ||
| 2432 | static IrInstGen *ir_build_union_field_ptr(IrAnalyze *ira, IrInst *source_instr, | 2078 | static IrInstGen *ir_build_field_parent_ptr_gen(IrAnalyze *ira, IrInst *source_instr, |
| 2433 | IrInstGen *union_ptr, TypeUnionField *field, bool safety_check_on, bool initializing, ZigType *ptr_type) | 2079 | IrInstGen *field_ptr, TypeStructField *field, ZigType *result_type) |
| 2434 | { | 2080 | { |
| 2435 | IrInstGenUnionFieldPtr *inst = ir_build_inst_gen<IrInstGenUnionFieldPtr>(&ira->new_irb, | 2081 | IrInstGenFieldParentPtr *inst = ir_build_inst_gen<IrInstGenFieldParentPtr>(&ira->new_irb, |
| 2436 | source_instr->scope, source_instr->source_node); | 2082 | source_instr->scope, source_instr->source_node); |
| 2437 | inst->base.value->type = ptr_type; | 2083 | inst->base.value->type = result_type; |
| 2438 | inst->initializing = initializing; | 2084 | inst->field_ptr = field_ptr; |
| 2439 | inst->safety_check_on = safety_check_on; | ||
| 2440 | inst->union_ptr = union_ptr; | ||
| 2441 | inst->field = field; | 2085 | inst->field = field; |
| 2442 | 2086 | ||
| 2443 | ir_ref_inst_gen(union_ptr); | 2087 | ir_ref_inst_gen(field_ptr); |
| 2444 | 2088 | ||
| 2445 | return &inst->base; | 2089 | return &inst->base; |
| 2446 | } | 2090 | } |
| 2447 | 2091 | ||
| 2448 | static IrInstSrc *ir_build_call_extra(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | 2092 | static IrInstGen *ir_build_align_cast_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, |
| 2449 | IrInstSrc *options, IrInstSrc *fn_ref, IrInstSrc *args, ResultLoc *result_loc) | 2093 | ZigType *result_type) |
| 2450 | { | 2094 | { |
| 2451 | IrInstSrcCallExtra *call_instruction = ir_build_instruction<IrInstSrcCallExtra>(irb, scope, source_node); | 2095 | IrInstGenAlignCast *instruction = ir_build_inst_gen<IrInstGenAlignCast>(&ira->new_irb, scope, source_node); |
| 2452 | call_instruction->options = options; | 2096 | instruction->base.value->type = result_type; |
| 2453 | call_instruction->fn_ref = fn_ref; | 2097 | instruction->target = target; |
| 2454 | call_instruction->args = args; | ||
| 2455 | call_instruction->result_loc = result_loc; | ||
| 2456 | 2098 | ||
| 2457 | ir_ref_instruction(options, irb->current_basic_block); | 2099 | ir_ref_inst_gen(target); |
| 2458 | ir_ref_instruction(fn_ref, irb->current_basic_block); | ||
| 2459 | ir_ref_instruction(args, irb->current_basic_block); | ||
| 2460 | 2100 | ||
| 2461 | return &call_instruction->base; | 2101 | return &instruction->base; |
| 2462 | } | 2102 | } |
| 2463 | 2103 | ||
| 2464 | static IrInstSrc *ir_build_async_call_extra(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | 2104 | static IrInstGen *ir_build_error_return_trace_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, |
| 2465 | CallModifier modifier, IrInstSrc *fn_ref, IrInstSrc *ret_ptr, IrInstSrc *new_stack, IrInstSrc *args, ResultLoc *result_loc) | 2105 | IrInstErrorReturnTraceOptional optional, ZigType *result_type) |
| 2466 | { | 2106 | { |
| 2467 | IrInstSrcAsyncCallExtra *call_instruction = ir_build_instruction<IrInstSrcAsyncCallExtra>(irb, scope, source_node); | 2107 | IrInstGenErrorReturnTrace *inst = ir_build_inst_gen<IrInstGenErrorReturnTrace>(&ira->new_irb, scope, source_node); |
| 2468 | call_instruction->modifier = modifier; | 2108 | inst->base.value->type = result_type; |
| 2469 | call_instruction->fn_ref = fn_ref; | 2109 | inst->optional = optional; |
| 2470 | call_instruction->ret_ptr = ret_ptr; | ||
| 2471 | call_instruction->new_stack = new_stack; | ||
| 2472 | call_instruction->args = args; | ||
| 2473 | call_instruction->result_loc = result_loc; | ||
| 2474 | |||
| 2475 | ir_ref_instruction(fn_ref, irb->current_basic_block); | ||
| 2476 | if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, irb->current_basic_block); | ||
| 2477 | ir_ref_instruction(new_stack, irb->current_basic_block); | ||
| 2478 | ir_ref_instruction(args, irb->current_basic_block); | ||
| 2479 | 2110 | ||
| 2480 | return &call_instruction->base; | 2111 | return &inst->base; |
| 2481 | } | 2112 | } |
| 2482 | 2113 | ||
| 2483 | static IrInstSrc *ir_build_call_args(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | 2114 | static IrInstGen *ir_build_atomic_rmw_gen(IrAnalyze *ira, IrInst *source_instr, |
| 2484 | IrInstSrc *options, IrInstSrc *fn_ref, IrInstSrc **args_ptr, size_t args_len, | 2115 | IrInstGen *ptr, IrInstGen *operand, AtomicRmwOp op, AtomicOrder ordering, ZigType *operand_type) |
| 2485 | ResultLoc *result_loc) | ||
| 2486 | { | 2116 | { |
| 2487 | IrInstSrcCallArgs *call_instruction = ir_build_instruction<IrInstSrcCallArgs>(irb, scope, source_node); | 2117 | IrInstGenAtomicRmw *instruction = ir_build_inst_gen<IrInstGenAtomicRmw>(&ira->new_irb, source_instr->scope, source_instr->source_node); |
| 2488 | call_instruction->options = options; | 2118 | instruction->base.value->type = operand_type; |
| 2489 | call_instruction->fn_ref = fn_ref; | ||
| 2490 | call_instruction->args_ptr = args_ptr; | ||
| 2491 | call_instruction->args_len = args_len; | ||
| 2492 | call_instruction->result_loc = result_loc; | ||
| 2493 | |||
| 2494 | ir_ref_instruction(options, irb->current_basic_block); | ||
| 2495 | ir_ref_instruction(fn_ref, irb->current_basic_block); | ||
| 2496 | for (size_t i = 0; i < args_len; i += 1) | ||
| 2497 | ir_ref_instruction(args_ptr[i], irb->current_basic_block); | ||
| 2498 | |||
| 2499 | return &call_instruction->base; | ||
| 2500 | } | ||
| 2501 | |||
| 2502 | static IrInstSrc *ir_build_call_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2503 | ZigFn *fn_entry, IrInstSrc *fn_ref, size_t arg_count, IrInstSrc **args, | ||
| 2504 | IrInstSrc *ret_ptr, CallModifier modifier, bool is_async_call_builtin, | ||
| 2505 | IrInstSrc *new_stack, ResultLoc *result_loc) | ||
| 2506 | { | ||
| 2507 | IrInstSrcCall *call_instruction = ir_build_instruction<IrInstSrcCall>(irb, scope, source_node); | ||
| 2508 | call_instruction->fn_entry = fn_entry; | ||
| 2509 | call_instruction->fn_ref = fn_ref; | ||
| 2510 | call_instruction->args = args; | ||
| 2511 | call_instruction->arg_count = arg_count; | ||
| 2512 | call_instruction->modifier = modifier; | ||
| 2513 | call_instruction->is_async_call_builtin = is_async_call_builtin; | ||
| 2514 | call_instruction->new_stack = new_stack; | ||
| 2515 | call_instruction->result_loc = result_loc; | ||
| 2516 | call_instruction->ret_ptr = ret_ptr; | ||
| 2517 | |||
| 2518 | if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block); | ||
| 2519 | for (size_t i = 0; i < arg_count; i += 1) | ||
| 2520 | ir_ref_instruction(args[i], irb->current_basic_block); | ||
| 2521 | if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, irb->current_basic_block); | ||
| 2522 | if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block); | ||
| 2523 | |||
| 2524 | return &call_instruction->base; | ||
| 2525 | } | ||
| 2526 | |||
| 2527 | static IrInstGenCall *ir_build_call_gen(IrAnalyze *ira, IrInst *source_instruction, | ||
| 2528 | ZigFn *fn_entry, IrInstGen *fn_ref, size_t arg_count, IrInstGen **args, | ||
| 2529 | CallModifier modifier, IrInstGen *new_stack, bool is_async_call_builtin, | ||
| 2530 | IrInstGen *result_loc, ZigType *return_type) | ||
| 2531 | { | ||
| 2532 | IrInstGenCall *call_instruction = ir_build_inst_gen<IrInstGenCall>(&ira->new_irb, | ||
| 2533 | source_instruction->scope, source_instruction->source_node); | ||
| 2534 | call_instruction->base.value->type = return_type; | ||
| 2535 | call_instruction->fn_entry = fn_entry; | ||
| 2536 | call_instruction->fn_ref = fn_ref; | ||
| 2537 | call_instruction->args = args; | ||
| 2538 | call_instruction->arg_count = arg_count; | ||
| 2539 | call_instruction->modifier = modifier; | ||
| 2540 | call_instruction->is_async_call_builtin = is_async_call_builtin; | ||
| 2541 | call_instruction->new_stack = new_stack; | ||
| 2542 | call_instruction->result_loc = result_loc; | ||
| 2543 | |||
| 2544 | if (fn_ref != nullptr) ir_ref_inst_gen(fn_ref); | ||
| 2545 | for (size_t i = 0; i < arg_count; i += 1) | ||
| 2546 | ir_ref_inst_gen(args[i]); | ||
| 2547 | if (new_stack != nullptr) ir_ref_inst_gen(new_stack); | ||
| 2548 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); | ||
| 2549 | |||
| 2550 | return call_instruction; | ||
| 2551 | } | ||
| 2552 | |||
| 2553 | static IrInstSrc *ir_build_phi(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2554 | size_t incoming_count, IrBasicBlockSrc **incoming_blocks, IrInstSrc **incoming_values, | ||
| 2555 | ResultLocPeerParent *peer_parent) | ||
| 2556 | { | ||
| 2557 | assert(incoming_count != 0); | ||
| 2558 | assert(incoming_count != SIZE_MAX); | ||
| 2559 | |||
| 2560 | IrInstSrcPhi *phi_instruction = ir_build_instruction<IrInstSrcPhi>(irb, scope, source_node); | ||
| 2561 | phi_instruction->incoming_count = incoming_count; | ||
| 2562 | phi_instruction->incoming_blocks = incoming_blocks; | ||
| 2563 | phi_instruction->incoming_values = incoming_values; | ||
| 2564 | phi_instruction->peer_parent = peer_parent; | ||
| 2565 | |||
| 2566 | for (size_t i = 0; i < incoming_count; i += 1) { | ||
| 2567 | ir_ref_bb(incoming_blocks[i]); | ||
| 2568 | ir_ref_instruction(incoming_values[i], irb->current_basic_block); | ||
| 2569 | } | ||
| 2570 | |||
| 2571 | return &phi_instruction->base; | ||
| 2572 | } | ||
| 2573 | |||
| 2574 | static IrInstGen *ir_build_phi_gen(IrAnalyze *ira, IrInst *source_instr, size_t incoming_count, | ||
| 2575 | IrBasicBlockGen **incoming_blocks, IrInstGen **incoming_values, ZigType *result_type) | ||
| 2576 | { | ||
| 2577 | assert(incoming_count != 0); | ||
| 2578 | assert(incoming_count != SIZE_MAX); | ||
| 2579 | |||
| 2580 | IrInstGenPhi *phi_instruction = ir_build_inst_gen<IrInstGenPhi>(&ira->new_irb, | ||
| 2581 | source_instr->scope, source_instr->source_node); | ||
| 2582 | phi_instruction->base.value->type = result_type; | ||
| 2583 | phi_instruction->incoming_count = incoming_count; | ||
| 2584 | phi_instruction->incoming_blocks = incoming_blocks; | ||
| 2585 | phi_instruction->incoming_values = incoming_values; | ||
| 2586 | |||
| 2587 | for (size_t i = 0; i < incoming_count; i += 1) { | ||
| 2588 | ir_ref_inst_gen(incoming_values[i]); | ||
| 2589 | } | ||
| 2590 | |||
| 2591 | return &phi_instruction->base; | ||
| 2592 | } | ||
| 2593 | |||
| 2594 | static IrInstSrc *ir_build_br(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2595 | IrBasicBlockSrc *dest_block, IrInstSrc *is_comptime) | ||
| 2596 | { | ||
| 2597 | IrInstSrcBr *inst = ir_build_instruction<IrInstSrcBr>(irb, scope, source_node); | ||
| 2598 | inst->base.is_noreturn = true; | ||
| 2599 | inst->dest_block = dest_block; | ||
| 2600 | inst->is_comptime = is_comptime; | ||
| 2601 | |||
| 2602 | ir_ref_bb(dest_block); | ||
| 2603 | if (is_comptime) ir_ref_instruction(is_comptime, irb->current_basic_block); | ||
| 2604 | |||
| 2605 | return &inst->base; | ||
| 2606 | } | ||
| 2607 | |||
| 2608 | static IrInstGen *ir_build_br_gen(IrAnalyze *ira, IrInst *source_instr, IrBasicBlockGen *dest_block) { | ||
| 2609 | IrInstGenBr *inst = ir_build_inst_noreturn<IrInstGenBr>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 2610 | inst->dest_block = dest_block; | ||
| 2611 | |||
| 2612 | return &inst->base; | ||
| 2613 | } | ||
| 2614 | |||
| 2615 | static IrInstSrc *ir_build_ptr_type_simple(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2616 | IrInstSrc *child_type, bool is_const) | ||
| 2617 | { | ||
| 2618 | IrInstSrcPtrTypeSimple *inst = heap::c_allocator.create<IrInstSrcPtrTypeSimple>(); | ||
| 2619 | inst->base.id = is_const ? IrInstSrcIdPtrTypeSimpleConst : IrInstSrcIdPtrTypeSimple; | ||
| 2620 | inst->base.base.scope = scope; | ||
| 2621 | inst->base.base.source_node = source_node; | ||
| 2622 | inst->base.base.debug_id = exec_next_debug_id(irb->exec); | ||
| 2623 | inst->base.owner_bb = irb->current_basic_block; | ||
| 2624 | ir_instruction_append(irb->current_basic_block, &inst->base); | ||
| 2625 | |||
| 2626 | inst->child_type = child_type; | ||
| 2627 | |||
| 2628 | ir_ref_instruction(child_type, irb->current_basic_block); | ||
| 2629 | |||
| 2630 | return &inst->base; | ||
| 2631 | } | ||
| 2632 | |||
| 2633 | static IrInstSrc *ir_build_ptr_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2634 | IrInstSrc *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, | ||
| 2635 | IrInstSrc *sentinel, IrInstSrc *align_value, | ||
| 2636 | uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero) | ||
| 2637 | { | ||
| 2638 | if (!is_volatile && ptr_len == PtrLenSingle && sentinel == nullptr && align_value == nullptr && | ||
| 2639 | bit_offset_start == 0 && host_int_bytes == 0 && is_allow_zero == 0) | ||
| 2640 | { | ||
| 2641 | return ir_build_ptr_type_simple(irb, scope, source_node, child_type, is_const); | ||
| 2642 | } | ||
| 2643 | |||
| 2644 | IrInstSrcPtrType *inst = ir_build_instruction<IrInstSrcPtrType>(irb, scope, source_node); | ||
| 2645 | inst->sentinel = sentinel; | ||
| 2646 | inst->align_value = align_value; | ||
| 2647 | inst->child_type = child_type; | ||
| 2648 | inst->is_const = is_const; | ||
| 2649 | inst->is_volatile = is_volatile; | ||
| 2650 | inst->ptr_len = ptr_len; | ||
| 2651 | inst->bit_offset_start = bit_offset_start; | ||
| 2652 | inst->host_int_bytes = host_int_bytes; | ||
| 2653 | inst->is_allow_zero = is_allow_zero; | ||
| 2654 | |||
| 2655 | if (sentinel) ir_ref_instruction(sentinel, irb->current_basic_block); | ||
| 2656 | if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); | ||
| 2657 | ir_ref_instruction(child_type, irb->current_basic_block); | ||
| 2658 | |||
| 2659 | return &inst->base; | ||
| 2660 | } | ||
| 2661 | |||
| 2662 | static IrInstSrc *ir_build_un_op_lval(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, | ||
| 2663 | IrInstSrc *value, LVal lval, ResultLoc *result_loc) | ||
| 2664 | { | ||
| 2665 | IrInstSrcUnOp *instruction = ir_build_instruction<IrInstSrcUnOp>(irb, scope, source_node); | ||
| 2666 | instruction->op_id = op_id; | ||
| 2667 | instruction->value = value; | ||
| 2668 | instruction->lval = lval; | ||
| 2669 | instruction->result_loc = result_loc; | ||
| 2670 | |||
| 2671 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 2672 | |||
| 2673 | return &instruction->base; | ||
| 2674 | } | ||
| 2675 | |||
| 2676 | static IrInstSrc *ir_build_un_op(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, | ||
| 2677 | IrInstSrc *value) | ||
| 2678 | { | ||
| 2679 | return ir_build_un_op_lval(irb, scope, source_node, op_id, value, LValNone, nullptr); | ||
| 2680 | } | ||
| 2681 | |||
| 2682 | static IrInstGen *ir_build_negation(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, ZigType *expr_type, bool wrapping) { | ||
| 2683 | IrInstGenNegation *instruction = ir_build_inst_gen<IrInstGenNegation>(&ira->new_irb, | ||
| 2684 | source_instr->scope, source_instr->source_node); | ||
| 2685 | instruction->base.value->type = expr_type; | ||
| 2686 | instruction->operand = operand; | ||
| 2687 | instruction->wrapping = wrapping; | ||
| 2688 | |||
| 2689 | ir_ref_inst_gen(operand); | ||
| 2690 | |||
| 2691 | return &instruction->base; | ||
| 2692 | } | ||
| 2693 | |||
| 2694 | static IrInstGen *ir_build_binary_not(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, | ||
| 2695 | ZigType *expr_type) | ||
| 2696 | { | ||
| 2697 | IrInstGenBinaryNot *instruction = ir_build_inst_gen<IrInstGenBinaryNot>(&ira->new_irb, | ||
| 2698 | source_instr->scope, source_instr->source_node); | ||
| 2699 | instruction->base.value->type = expr_type; | ||
| 2700 | instruction->operand = operand; | ||
| 2701 | |||
| 2702 | ir_ref_inst_gen(operand); | ||
| 2703 | |||
| 2704 | return &instruction->base; | ||
| 2705 | } | ||
| 2706 | |||
| 2707 | static IrInstSrc *ir_build_container_init_list(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2708 | size_t item_count, IrInstSrc **elem_result_loc_list, IrInstSrc *result_loc, | ||
| 2709 | AstNode *init_array_type_source_node) | ||
| 2710 | { | ||
| 2711 | IrInstSrcContainerInitList *container_init_list_instruction = | ||
| 2712 | ir_build_instruction<IrInstSrcContainerInitList>(irb, scope, source_node); | ||
| 2713 | container_init_list_instruction->item_count = item_count; | ||
| 2714 | container_init_list_instruction->elem_result_loc_list = elem_result_loc_list; | ||
| 2715 | container_init_list_instruction->result_loc = result_loc; | ||
| 2716 | container_init_list_instruction->init_array_type_source_node = init_array_type_source_node; | ||
| 2717 | |||
| 2718 | for (size_t i = 0; i < item_count; i += 1) { | ||
| 2719 | ir_ref_instruction(elem_result_loc_list[i], irb->current_basic_block); | ||
| 2720 | } | ||
| 2721 | if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block); | ||
| 2722 | |||
| 2723 | return &container_init_list_instruction->base; | ||
| 2724 | } | ||
| 2725 | |||
| 2726 | static IrInstSrc *ir_build_container_init_fields(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2727 | size_t field_count, IrInstSrcContainerInitFieldsField *fields, IrInstSrc *result_loc) | ||
| 2728 | { | ||
| 2729 | IrInstSrcContainerInitFields *container_init_fields_instruction = | ||
| 2730 | ir_build_instruction<IrInstSrcContainerInitFields>(irb, scope, source_node); | ||
| 2731 | container_init_fields_instruction->field_count = field_count; | ||
| 2732 | container_init_fields_instruction->fields = fields; | ||
| 2733 | container_init_fields_instruction->result_loc = result_loc; | ||
| 2734 | |||
| 2735 | for (size_t i = 0; i < field_count; i += 1) { | ||
| 2736 | ir_ref_instruction(fields[i].result_loc, irb->current_basic_block); | ||
| 2737 | } | ||
| 2738 | if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block); | ||
| 2739 | |||
| 2740 | return &container_init_fields_instruction->base; | ||
| 2741 | } | ||
| 2742 | |||
| 2743 | static IrInstSrc *ir_build_unreachable(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | ||
| 2744 | IrInstSrcUnreachable *inst = ir_build_instruction<IrInstSrcUnreachable>(irb, scope, source_node); | ||
| 2745 | inst->base.is_noreturn = true; | ||
| 2746 | return &inst->base; | ||
| 2747 | } | ||
| 2748 | |||
| 2749 | static IrInstGen *ir_build_unreachable_gen(IrAnalyze *ira, IrInst *source_instr) { | ||
| 2750 | IrInstGenUnreachable *inst = ir_build_inst_noreturn<IrInstGenUnreachable>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 2751 | return &inst->base; | ||
| 2752 | } | ||
| 2753 | |||
| 2754 | static IrInstSrcStorePtr *ir_build_store_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2755 | IrInstSrc *ptr, IrInstSrc *value) | ||
| 2756 | { | ||
| 2757 | IrInstSrcStorePtr *instruction = ir_build_instruction<IrInstSrcStorePtr>(irb, scope, source_node); | ||
| 2758 | instruction->ptr = ptr; | ||
| 2759 | instruction->value = value; | ||
| 2760 | |||
| 2761 | ir_ref_instruction(ptr, irb->current_basic_block); | ||
| 2762 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 2763 | |||
| 2764 | return instruction; | ||
| 2765 | } | ||
| 2766 | |||
| 2767 | static IrInstGen *ir_build_store_ptr_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *ptr, IrInstGen *value) { | ||
| 2768 | IrInstGenStorePtr *instruction = ir_build_inst_void<IrInstGenStorePtr>(&ira->new_irb, | ||
| 2769 | source_instr->scope, source_instr->source_node); | ||
| 2770 | instruction->ptr = ptr; | 2119 | instruction->ptr = ptr; |
| 2771 | instruction->value = value; | 2120 | instruction->op = op; |
| 2121 | instruction->operand = operand; | ||
| 2122 | instruction->ordering = ordering; | ||
| 2772 | 2123 | ||
| 2773 | ir_ref_inst_gen(ptr); | 2124 | ir_ref_inst_gen(ptr); |
| 2774 | ir_ref_inst_gen(value); | 2125 | ir_ref_inst_gen(operand); |
| 2775 | 2126 | ||
| 2776 | return &instruction->base; | 2127 | return &instruction->base; |
| 2777 | } | 2128 | } |
| 2778 | 2129 | ||
| 2779 | static IrInstGen *ir_build_vector_store_elem(IrAnalyze *ira, IrInst *src_inst, | 2130 | static IrInstGen *ir_build_atomic_load_gen(IrAnalyze *ira, IrInst *source_instr, |
| 2780 | IrInstGen *vector_ptr, IrInstGen *index, IrInstGen *value) | 2131 | IrInstGen *ptr, AtomicOrder ordering, ZigType *operand_type) |
| 2781 | { | ||
| 2782 | IrInstGenVectorStoreElem *inst = ir_build_inst_void<IrInstGenVectorStoreElem>( | ||
| 2783 | &ira->new_irb, src_inst->scope, src_inst->source_node); | ||
| 2784 | inst->vector_ptr = vector_ptr; | ||
| 2785 | inst->index = index; | ||
| 2786 | inst->value = value; | ||
| 2787 | |||
| 2788 | ir_ref_inst_gen(vector_ptr); | ||
| 2789 | ir_ref_inst_gen(index); | ||
| 2790 | ir_ref_inst_gen(value); | ||
| 2791 | |||
| 2792 | return &inst->base; | ||
| 2793 | } | ||
| 2794 | |||
| 2795 | static IrInstSrc *ir_build_var_decl_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2796 | ZigVar *var, IrInstSrc *align_value, IrInstSrc *ptr) | ||
| 2797 | { | ||
| 2798 | IrInstSrcDeclVar *inst = ir_build_instruction<IrInstSrcDeclVar>(irb, scope, source_node); | ||
| 2799 | inst->var = var; | ||
| 2800 | inst->align_value = align_value; | ||
| 2801 | inst->ptr = ptr; | ||
| 2802 | |||
| 2803 | if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); | ||
| 2804 | ir_ref_instruction(ptr, irb->current_basic_block); | ||
| 2805 | |||
| 2806 | return &inst->base; | ||
| 2807 | } | ||
| 2808 | |||
| 2809 | static IrInstGen *ir_build_var_decl_gen(IrAnalyze *ira, IrInst *source_instruction, | ||
| 2810 | ZigVar *var, IrInstGen *var_ptr) | ||
| 2811 | { | ||
| 2812 | IrInstGenDeclVar *inst = ir_build_inst_gen<IrInstGenDeclVar>(&ira->new_irb, | ||
| 2813 | source_instruction->scope, source_instruction->source_node); | ||
| 2814 | inst->base.value->special = ConstValSpecialStatic; | ||
| 2815 | inst->base.value->type = ira->codegen->builtin_types.entry_void; | ||
| 2816 | inst->var = var; | ||
| 2817 | inst->var_ptr = var_ptr; | ||
| 2818 | |||
| 2819 | ir_ref_inst_gen(var_ptr); | ||
| 2820 | |||
| 2821 | return &inst->base; | ||
| 2822 | } | ||
| 2823 | |||
| 2824 | static IrInstSrc *ir_build_export(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2825 | IrInstSrc *target, IrInstSrc *options) | ||
| 2826 | { | ||
| 2827 | IrInstSrcExport *export_instruction = ir_build_instruction<IrInstSrcExport>( | ||
| 2828 | irb, scope, source_node); | ||
| 2829 | export_instruction->target = target; | ||
| 2830 | export_instruction->options = options; | ||
| 2831 | |||
| 2832 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 2833 | ir_ref_instruction(options, irb->current_basic_block); | ||
| 2834 | |||
| 2835 | return &export_instruction->base; | ||
| 2836 | } | ||
| 2837 | |||
| 2838 | static IrInstSrc *ir_build_extern(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2839 | IrInstSrc *type, IrInstSrc *options) | ||
| 2840 | { | ||
| 2841 | IrInstSrcExtern *extern_instruction = ir_build_instruction<IrInstSrcExtern>( | ||
| 2842 | irb, scope, source_node); | ||
| 2843 | extern_instruction->type = type; | ||
| 2844 | extern_instruction->options = options; | ||
| 2845 | |||
| 2846 | ir_ref_instruction(type, irb->current_basic_block); | ||
| 2847 | ir_ref_instruction(options, irb->current_basic_block); | ||
| 2848 | |||
| 2849 | return &extern_instruction->base; | ||
| 2850 | } | ||
| 2851 | |||
| 2852 | static IrInstGen *ir_build_extern_gen(IrAnalyze *ira, IrInst *source_instr, Buf *name, | ||
| 2853 | GlobalLinkageId linkage, bool is_thread_local, ZigType *expr_type) | ||
| 2854 | { | 2132 | { |
| 2855 | IrInstGenExtern *instruction = ir_build_inst_gen<IrInstGenExtern>(&ira->new_irb, | 2133 | IrInstGenAtomicLoad *instruction = ir_build_inst_gen<IrInstGenAtomicLoad>(&ira->new_irb, |
| 2856 | source_instr->scope, source_instr->source_node); | 2134 | source_instr->scope, source_instr->source_node); |
| 2857 | instruction->base.value->type = expr_type; | 2135 | instruction->base.value->type = operand_type; |
| 2858 | instruction->name = name; | ||
| 2859 | instruction->linkage = linkage; | ||
| 2860 | instruction->is_thread_local = is_thread_local; | ||
| 2861 | |||
| 2862 | return &instruction->base; | ||
| 2863 | } | ||
| 2864 | |||
| 2865 | static IrInstSrc *ir_build_load_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *ptr) { | ||
| 2866 | IrInstSrcLoadPtr *instruction = ir_build_instruction<IrInstSrcLoadPtr>(irb, scope, source_node); | ||
| 2867 | instruction->ptr = ptr; | ||
| 2868 | |||
| 2869 | ir_ref_instruction(ptr, irb->current_basic_block); | ||
| 2870 | |||
| 2871 | return &instruction->base; | ||
| 2872 | } | ||
| 2873 | |||
| 2874 | static IrInstGen *ir_build_load_ptr_gen(IrAnalyze *ira, IrInst *source_instruction, | ||
| 2875 | IrInstGen *ptr, ZigType *ty, IrInstGen *result_loc) | ||
| 2876 | { | ||
| 2877 | IrInstGenLoadPtr *instruction = ir_build_inst_gen<IrInstGenLoadPtr>( | ||
| 2878 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 2879 | instruction->base.value->type = ty; | ||
| 2880 | instruction->ptr = ptr; | 2136 | instruction->ptr = ptr; |
| 2881 | instruction->result_loc = result_loc; | 2137 | instruction->ordering = ordering; |
| 2882 | |||
| 2883 | ir_ref_inst_gen(ptr); | ||
| 2884 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); | ||
| 2885 | |||
| 2886 | return &instruction->base; | ||
| 2887 | } | ||
| 2888 | |||
| 2889 | static IrInstSrc *ir_build_typeof_n(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2890 | IrInstSrc **values, size_t value_count) | ||
| 2891 | { | ||
| 2892 | assert(value_count >= 2); | ||
| 2893 | |||
| 2894 | IrInstSrcTypeOf *instruction = ir_build_instruction<IrInstSrcTypeOf>(irb, scope, source_node); | ||
| 2895 | instruction->value.list = values; | ||
| 2896 | instruction->value_count = value_count; | ||
| 2897 | |||
| 2898 | for (size_t i = 0; i < value_count; i++) | ||
| 2899 | ir_ref_instruction(values[i], irb->current_basic_block); | ||
| 2900 | |||
| 2901 | return &instruction->base; | ||
| 2902 | } | ||
| 2903 | |||
| 2904 | static IrInstSrc *ir_build_typeof_1(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { | ||
| 2905 | IrInstSrcTypeOf *instruction = ir_build_instruction<IrInstSrcTypeOf>(irb, scope, source_node); | ||
| 2906 | instruction->value.scalar = value; | ||
| 2907 | |||
| 2908 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 2909 | |||
| 2910 | return &instruction->base; | ||
| 2911 | } | ||
| 2912 | |||
| 2913 | static IrInstSrc *ir_build_set_cold(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *is_cold) { | ||
| 2914 | IrInstSrcSetCold *instruction = ir_build_instruction<IrInstSrcSetCold>(irb, scope, source_node); | ||
| 2915 | instruction->is_cold = is_cold; | ||
| 2916 | |||
| 2917 | ir_ref_instruction(is_cold, irb->current_basic_block); | ||
| 2918 | |||
| 2919 | return &instruction->base; | ||
| 2920 | } | ||
| 2921 | |||
| 2922 | static IrInstSrc *ir_build_set_runtime_safety(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2923 | IrInstSrc *safety_on) | ||
| 2924 | { | ||
| 2925 | IrInstSrcSetRuntimeSafety *inst = ir_build_instruction<IrInstSrcSetRuntimeSafety>(irb, scope, source_node); | ||
| 2926 | inst->safety_on = safety_on; | ||
| 2927 | |||
| 2928 | ir_ref_instruction(safety_on, irb->current_basic_block); | ||
| 2929 | |||
| 2930 | return &inst->base; | ||
| 2931 | } | ||
| 2932 | |||
| 2933 | static IrInstSrc *ir_build_set_float_mode(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2934 | IrInstSrc *mode_value) | ||
| 2935 | { | ||
| 2936 | IrInstSrcSetFloatMode *instruction = ir_build_instruction<IrInstSrcSetFloatMode>(irb, scope, source_node); | ||
| 2937 | instruction->mode_value = mode_value; | ||
| 2938 | |||
| 2939 | ir_ref_instruction(mode_value, irb->current_basic_block); | ||
| 2940 | |||
| 2941 | return &instruction->base; | ||
| 2942 | } | ||
| 2943 | |||
| 2944 | static IrInstSrc *ir_build_array_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *size, | ||
| 2945 | IrInstSrc *sentinel, IrInstSrc *child_type) | ||
| 2946 | { | ||
| 2947 | IrInstSrcArrayType *instruction = ir_build_instruction<IrInstSrcArrayType>(irb, scope, source_node); | ||
| 2948 | instruction->size = size; | ||
| 2949 | instruction->sentinel = sentinel; | ||
| 2950 | instruction->child_type = child_type; | ||
| 2951 | |||
| 2952 | ir_ref_instruction(size, irb->current_basic_block); | ||
| 2953 | if (sentinel != nullptr) ir_ref_instruction(sentinel, irb->current_basic_block); | ||
| 2954 | ir_ref_instruction(child_type, irb->current_basic_block); | ||
| 2955 | |||
| 2956 | return &instruction->base; | ||
| 2957 | } | ||
| 2958 | |||
| 2959 | static IrInstSrc *ir_build_anyframe_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2960 | IrInstSrc *payload_type) | ||
| 2961 | { | ||
| 2962 | IrInstSrcAnyFrameType *instruction = ir_build_instruction<IrInstSrcAnyFrameType>(irb, scope, source_node); | ||
| 2963 | instruction->payload_type = payload_type; | ||
| 2964 | |||
| 2965 | if (payload_type != nullptr) ir_ref_instruction(payload_type, irb->current_basic_block); | ||
| 2966 | |||
| 2967 | return &instruction->base; | ||
| 2968 | } | ||
| 2969 | |||
| 2970 | static IrInstSrc *ir_build_slice_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2971 | IrInstSrc *child_type, bool is_const, bool is_volatile, | ||
| 2972 | IrInstSrc *sentinel, IrInstSrc *align_value, bool is_allow_zero) | ||
| 2973 | { | ||
| 2974 | IrInstSrcSliceType *instruction = ir_build_instruction<IrInstSrcSliceType>(irb, scope, source_node); | ||
| 2975 | instruction->is_const = is_const; | ||
| 2976 | instruction->is_volatile = is_volatile; | ||
| 2977 | instruction->child_type = child_type; | ||
| 2978 | instruction->sentinel = sentinel; | ||
| 2979 | instruction->align_value = align_value; | ||
| 2980 | instruction->is_allow_zero = is_allow_zero; | ||
| 2981 | |||
| 2982 | if (sentinel != nullptr) ir_ref_instruction(sentinel, irb->current_basic_block); | ||
| 2983 | if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); | ||
| 2984 | ir_ref_instruction(child_type, irb->current_basic_block); | ||
| 2985 | |||
| 2986 | return &instruction->base; | ||
| 2987 | } | ||
| 2988 | |||
| 2989 | static IrInstSrc *ir_build_asm_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 2990 | IrInstSrc *asm_template, IrInstSrc **input_list, IrInstSrc **output_types, | ||
| 2991 | ZigVar **output_vars, size_t return_count, bool has_side_effects, bool is_global) | ||
| 2992 | { | ||
| 2993 | IrInstSrcAsm *instruction = ir_build_instruction<IrInstSrcAsm>(irb, scope, source_node); | ||
| 2994 | instruction->asm_template = asm_template; | ||
| 2995 | instruction->input_list = input_list; | ||
| 2996 | instruction->output_types = output_types; | ||
| 2997 | instruction->output_vars = output_vars; | ||
| 2998 | instruction->return_count = return_count; | ||
| 2999 | instruction->has_side_effects = has_side_effects; | ||
| 3000 | instruction->is_global = is_global; | ||
| 3001 | |||
| 3002 | assert(source_node->type == NodeTypeAsmExpr); | ||
| 3003 | for (size_t i = 0; i < source_node->data.asm_expr.output_list.length; i += 1) { | ||
| 3004 | IrInstSrc *output_type = output_types[i]; | ||
| 3005 | if (output_type) ir_ref_instruction(output_type, irb->current_basic_block); | ||
| 3006 | } | ||
| 3007 | |||
| 3008 | for (size_t i = 0; i < source_node->data.asm_expr.input_list.length; i += 1) { | ||
| 3009 | IrInstSrc *input_value = input_list[i]; | ||
| 3010 | ir_ref_instruction(input_value, irb->current_basic_block); | ||
| 3011 | } | ||
| 3012 | |||
| 3013 | return &instruction->base; | ||
| 3014 | } | ||
| 3015 | |||
| 3016 | static IrInstGen *ir_build_asm_gen(IrAnalyze *ira, IrInst *source_instr, | ||
| 3017 | Buf *asm_template, AsmToken *token_list, size_t token_list_len, | ||
| 3018 | IrInstGen **input_list, IrInstGen **output_types, ZigVar **output_vars, size_t return_count, | ||
| 3019 | bool has_side_effects, ZigType *return_type) | ||
| 3020 | { | ||
| 3021 | IrInstGenAsm *instruction = ir_build_inst_gen<IrInstGenAsm>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 3022 | instruction->base.value->type = return_type; | ||
| 3023 | instruction->asm_template = asm_template; | ||
| 3024 | instruction->token_list = token_list; | ||
| 3025 | instruction->token_list_len = token_list_len; | ||
| 3026 | instruction->input_list = input_list; | ||
| 3027 | instruction->output_types = output_types; | ||
| 3028 | instruction->output_vars = output_vars; | ||
| 3029 | instruction->return_count = return_count; | ||
| 3030 | instruction->has_side_effects = has_side_effects; | ||
| 3031 | |||
| 3032 | assert(source_instr->source_node->type == NodeTypeAsmExpr); | ||
| 3033 | for (size_t i = 0; i < source_instr->source_node->data.asm_expr.output_list.length; i += 1) { | ||
| 3034 | IrInstGen *output_type = output_types[i]; | ||
| 3035 | if (output_type) ir_ref_inst_gen(output_type); | ||
| 3036 | } | ||
| 3037 | |||
| 3038 | for (size_t i = 0; i < source_instr->source_node->data.asm_expr.input_list.length; i += 1) { | ||
| 3039 | IrInstGen *input_value = input_list[i]; | ||
| 3040 | ir_ref_inst_gen(input_value); | ||
| 3041 | } | ||
| 3042 | |||
| 3043 | return &instruction->base; | ||
| 3044 | } | ||
| 3045 | |||
| 3046 | static IrInstSrc *ir_build_size_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value, | ||
| 3047 | bool bit_size) | ||
| 3048 | { | ||
| 3049 | IrInstSrcSizeOf *instruction = ir_build_instruction<IrInstSrcSizeOf>(irb, scope, source_node); | ||
| 3050 | instruction->type_value = type_value; | ||
| 3051 | instruction->bit_size = bit_size; | ||
| 3052 | |||
| 3053 | ir_ref_instruction(type_value, irb->current_basic_block); | ||
| 3054 | |||
| 3055 | return &instruction->base; | ||
| 3056 | } | ||
| 3057 | |||
| 3058 | static IrInstSrc *ir_build_test_non_null_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3059 | IrInstSrc *value) | ||
| 3060 | { | ||
| 3061 | IrInstSrcTestNonNull *instruction = ir_build_instruction<IrInstSrcTestNonNull>(irb, scope, source_node); | ||
| 3062 | instruction->value = value; | ||
| 3063 | |||
| 3064 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 3065 | |||
| 3066 | return &instruction->base; | ||
| 3067 | } | ||
| 3068 | |||
| 3069 | static IrInstGen *ir_build_test_non_null_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value) { | ||
| 3070 | IrInstGenTestNonNull *inst = ir_build_inst_gen<IrInstGenTestNonNull>(&ira->new_irb, | ||
| 3071 | source_instr->scope, source_instr->source_node); | ||
| 3072 | inst->base.value->type = ira->codegen->builtin_types.entry_bool; | ||
| 3073 | inst->value = value; | ||
| 3074 | |||
| 3075 | ir_ref_inst_gen(value); | ||
| 3076 | |||
| 3077 | return &inst->base; | ||
| 3078 | } | ||
| 3079 | |||
| 3080 | static IrInstSrc *ir_build_optional_unwrap_ptr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3081 | IrInstSrc *base_ptr, bool safety_check_on) | ||
| 3082 | { | ||
| 3083 | IrInstSrcOptionalUnwrapPtr *instruction = ir_build_instruction<IrInstSrcOptionalUnwrapPtr>(irb, scope, source_node); | ||
| 3084 | instruction->base_ptr = base_ptr; | ||
| 3085 | instruction->safety_check_on = safety_check_on; | ||
| 3086 | |||
| 3087 | ir_ref_instruction(base_ptr, irb->current_basic_block); | ||
| 3088 | |||
| 3089 | return &instruction->base; | ||
| 3090 | } | ||
| 3091 | |||
| 3092 | static IrInstGen *ir_build_optional_unwrap_ptr_gen(IrAnalyze *ira, IrInst *source_instr, | ||
| 3093 | IrInstGen *base_ptr, bool safety_check_on, bool initializing, ZigType *result_type) | ||
| 3094 | { | ||
| 3095 | IrInstGenOptionalUnwrapPtr *inst = ir_build_inst_gen<IrInstGenOptionalUnwrapPtr>(&ira->new_irb, | ||
| 3096 | source_instr->scope, source_instr->source_node); | ||
| 3097 | inst->base.value->type = result_type; | ||
| 3098 | inst->base_ptr = base_ptr; | ||
| 3099 | inst->safety_check_on = safety_check_on; | ||
| 3100 | inst->initializing = initializing; | ||
| 3101 | |||
| 3102 | ir_ref_inst_gen(base_ptr); | ||
| 3103 | |||
| 3104 | return &inst->base; | ||
| 3105 | } | ||
| 3106 | |||
| 3107 | static IrInstGen *ir_build_optional_wrap(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_ty, | ||
| 3108 | IrInstGen *operand, IrInstGen *result_loc) | ||
| 3109 | { | ||
| 3110 | IrInstGenOptionalWrap *instruction = ir_build_inst_gen<IrInstGenOptionalWrap>( | ||
| 3111 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 3112 | instruction->base.value->type = result_ty; | ||
| 3113 | instruction->operand = operand; | ||
| 3114 | instruction->result_loc = result_loc; | ||
| 3115 | |||
| 3116 | ir_ref_inst_gen(operand); | ||
| 3117 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); | ||
| 3118 | |||
| 3119 | return &instruction->base; | ||
| 3120 | } | ||
| 3121 | |||
| 3122 | static IrInstGen *ir_build_err_wrap_payload(IrAnalyze *ira, IrInst *source_instruction, | ||
| 3123 | ZigType *result_type, IrInstGen *operand, IrInstGen *result_loc) | ||
| 3124 | { | ||
| 3125 | IrInstGenErrWrapPayload *instruction = ir_build_inst_gen<IrInstGenErrWrapPayload>( | ||
| 3126 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 3127 | instruction->base.value->type = result_type; | ||
| 3128 | instruction->operand = operand; | ||
| 3129 | instruction->result_loc = result_loc; | ||
| 3130 | |||
| 3131 | ir_ref_inst_gen(operand); | ||
| 3132 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); | ||
| 3133 | |||
| 3134 | return &instruction->base; | ||
| 3135 | } | ||
| 3136 | |||
| 3137 | static IrInstGen *ir_build_err_wrap_code(IrAnalyze *ira, IrInst *source_instruction, | ||
| 3138 | ZigType *result_type, IrInstGen *operand, IrInstGen *result_loc) | ||
| 3139 | { | ||
| 3140 | IrInstGenErrWrapCode *instruction = ir_build_inst_gen<IrInstGenErrWrapCode>( | ||
| 3141 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 3142 | instruction->base.value->type = result_type; | ||
| 3143 | instruction->operand = operand; | ||
| 3144 | instruction->result_loc = result_loc; | ||
| 3145 | |||
| 3146 | ir_ref_inst_gen(operand); | ||
| 3147 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); | ||
| 3148 | |||
| 3149 | return &instruction->base; | ||
| 3150 | } | ||
| 3151 | |||
| 3152 | static IrInstSrc *ir_build_clz(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, | ||
| 3153 | IrInstSrc *op) | ||
| 3154 | { | ||
| 3155 | IrInstSrcClz *instruction = ir_build_instruction<IrInstSrcClz>(irb, scope, source_node); | ||
| 3156 | instruction->type = type; | ||
| 3157 | instruction->op = op; | ||
| 3158 | |||
| 3159 | ir_ref_instruction(type, irb->current_basic_block); | ||
| 3160 | ir_ref_instruction(op, irb->current_basic_block); | ||
| 3161 | |||
| 3162 | return &instruction->base; | ||
| 3163 | } | ||
| 3164 | |||
| 3165 | static IrInstGen *ir_build_clz_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *result_type, IrInstGen *op) { | ||
| 3166 | IrInstGenClz *instruction = ir_build_inst_gen<IrInstGenClz>(&ira->new_irb, | ||
| 3167 | source_instr->scope, source_instr->source_node); | ||
| 3168 | instruction->base.value->type = result_type; | ||
| 3169 | instruction->op = op; | ||
| 3170 | |||
| 3171 | ir_ref_inst_gen(op); | ||
| 3172 | |||
| 3173 | return &instruction->base; | ||
| 3174 | } | ||
| 3175 | |||
| 3176 | static IrInstSrc *ir_build_ctz(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, | ||
| 3177 | IrInstSrc *op) | ||
| 3178 | { | ||
| 3179 | IrInstSrcCtz *instruction = ir_build_instruction<IrInstSrcCtz>(irb, scope, source_node); | ||
| 3180 | instruction->type = type; | ||
| 3181 | instruction->op = op; | ||
| 3182 | |||
| 3183 | ir_ref_instruction(type, irb->current_basic_block); | ||
| 3184 | ir_ref_instruction(op, irb->current_basic_block); | ||
| 3185 | |||
| 3186 | return &instruction->base; | ||
| 3187 | } | ||
| 3188 | |||
| 3189 | static IrInstGen *ir_build_ctz_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *result_type, IrInstGen *op) { | ||
| 3190 | IrInstGenCtz *instruction = ir_build_inst_gen<IrInstGenCtz>(&ira->new_irb, | ||
| 3191 | source_instr->scope, source_instr->source_node); | ||
| 3192 | instruction->base.value->type = result_type; | ||
| 3193 | instruction->op = op; | ||
| 3194 | |||
| 3195 | ir_ref_inst_gen(op); | ||
| 3196 | |||
| 3197 | return &instruction->base; | ||
| 3198 | } | ||
| 3199 | |||
| 3200 | static IrInstSrc *ir_build_pop_count(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, | ||
| 3201 | IrInstSrc *op) | ||
| 3202 | { | ||
| 3203 | IrInstSrcPopCount *instruction = ir_build_instruction<IrInstSrcPopCount>(irb, scope, source_node); | ||
| 3204 | instruction->type = type; | ||
| 3205 | instruction->op = op; | ||
| 3206 | |||
| 3207 | ir_ref_instruction(type, irb->current_basic_block); | ||
| 3208 | ir_ref_instruction(op, irb->current_basic_block); | ||
| 3209 | |||
| 3210 | return &instruction->base; | ||
| 3211 | } | ||
| 3212 | |||
| 3213 | static IrInstGen *ir_build_pop_count_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *result_type, | ||
| 3214 | IrInstGen *op) | ||
| 3215 | { | ||
| 3216 | IrInstGenPopCount *instruction = ir_build_inst_gen<IrInstGenPopCount>(&ira->new_irb, | ||
| 3217 | source_instr->scope, source_instr->source_node); | ||
| 3218 | instruction->base.value->type = result_type; | ||
| 3219 | instruction->op = op; | ||
| 3220 | |||
| 3221 | ir_ref_inst_gen(op); | ||
| 3222 | |||
| 3223 | return &instruction->base; | ||
| 3224 | } | ||
| 3225 | |||
| 3226 | static IrInstSrc *ir_build_bswap(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, | ||
| 3227 | IrInstSrc *op) | ||
| 3228 | { | ||
| 3229 | IrInstSrcBswap *instruction = ir_build_instruction<IrInstSrcBswap>(irb, scope, source_node); | ||
| 3230 | instruction->type = type; | ||
| 3231 | instruction->op = op; | ||
| 3232 | |||
| 3233 | ir_ref_instruction(type, irb->current_basic_block); | ||
| 3234 | ir_ref_instruction(op, irb->current_basic_block); | ||
| 3235 | |||
| 3236 | return &instruction->base; | ||
| 3237 | } | ||
| 3238 | |||
| 3239 | static IrInstGen *ir_build_bswap_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *op_type, | ||
| 3240 | IrInstGen *op) | ||
| 3241 | { | ||
| 3242 | IrInstGenBswap *instruction = ir_build_inst_gen<IrInstGenBswap>(&ira->new_irb, | ||
| 3243 | source_instr->scope, source_instr->source_node); | ||
| 3244 | instruction->base.value->type = op_type; | ||
| 3245 | instruction->op = op; | ||
| 3246 | |||
| 3247 | ir_ref_inst_gen(op); | ||
| 3248 | |||
| 3249 | return &instruction->base; | ||
| 3250 | } | ||
| 3251 | |||
| 3252 | static IrInstSrc *ir_build_bit_reverse(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type, | ||
| 3253 | IrInstSrc *op) | ||
| 3254 | { | ||
| 3255 | IrInstSrcBitReverse *instruction = ir_build_instruction<IrInstSrcBitReverse>(irb, scope, source_node); | ||
| 3256 | instruction->type = type; | ||
| 3257 | instruction->op = op; | ||
| 3258 | |||
| 3259 | ir_ref_instruction(type, irb->current_basic_block); | ||
| 3260 | ir_ref_instruction(op, irb->current_basic_block); | ||
| 3261 | |||
| 3262 | return &instruction->base; | ||
| 3263 | } | ||
| 3264 | |||
| 3265 | static IrInstGen *ir_build_bit_reverse_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *int_type, | ||
| 3266 | IrInstGen *op) | ||
| 3267 | { | ||
| 3268 | IrInstGenBitReverse *instruction = ir_build_inst_gen<IrInstGenBitReverse>(&ira->new_irb, | ||
| 3269 | source_instr->scope, source_instr->source_node); | ||
| 3270 | instruction->base.value->type = int_type; | ||
| 3271 | instruction->op = op; | ||
| 3272 | |||
| 3273 | ir_ref_inst_gen(op); | ||
| 3274 | |||
| 3275 | return &instruction->base; | ||
| 3276 | } | ||
| 3277 | |||
| 3278 | static IrInstSrcSwitchBr *ir_build_switch_br_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3279 | IrInstSrc *target_value, IrBasicBlockSrc *else_block, size_t case_count, IrInstSrcSwitchBrCase *cases, | ||
| 3280 | IrInstSrc *is_comptime, IrInstSrc *switch_prongs_void) | ||
| 3281 | { | ||
| 3282 | IrInstSrcSwitchBr *instruction = ir_build_instruction<IrInstSrcSwitchBr>(irb, scope, source_node); | ||
| 3283 | instruction->base.is_noreturn = true; | ||
| 3284 | instruction->target_value = target_value; | ||
| 3285 | instruction->else_block = else_block; | ||
| 3286 | instruction->case_count = case_count; | ||
| 3287 | instruction->cases = cases; | ||
| 3288 | instruction->is_comptime = is_comptime; | ||
| 3289 | instruction->switch_prongs_void = switch_prongs_void; | ||
| 3290 | |||
| 3291 | ir_ref_instruction(target_value, irb->current_basic_block); | ||
| 3292 | ir_ref_instruction(is_comptime, irb->current_basic_block); | ||
| 3293 | ir_ref_bb(else_block); | ||
| 3294 | ir_ref_instruction(switch_prongs_void, irb->current_basic_block); | ||
| 3295 | |||
| 3296 | for (size_t i = 0; i < case_count; i += 1) { | ||
| 3297 | ir_ref_instruction(cases[i].value, irb->current_basic_block); | ||
| 3298 | ir_ref_bb(cases[i].block); | ||
| 3299 | } | ||
| 3300 | |||
| 3301 | return instruction; | ||
| 3302 | } | ||
| 3303 | |||
| 3304 | static IrInstGenSwitchBr *ir_build_switch_br_gen(IrAnalyze *ira, IrInst *source_instr, | ||
| 3305 | IrInstGen *target_value, IrBasicBlockGen *else_block, size_t case_count, IrInstGenSwitchBrCase *cases) | ||
| 3306 | { | ||
| 3307 | IrInstGenSwitchBr *instruction = ir_build_inst_noreturn<IrInstGenSwitchBr>(&ira->new_irb, | ||
| 3308 | source_instr->scope, source_instr->source_node); | ||
| 3309 | instruction->target_value = target_value; | ||
| 3310 | instruction->else_block = else_block; | ||
| 3311 | instruction->case_count = case_count; | ||
| 3312 | instruction->cases = cases; | ||
| 3313 | |||
| 3314 | ir_ref_inst_gen(target_value); | ||
| 3315 | |||
| 3316 | for (size_t i = 0; i < case_count; i += 1) { | ||
| 3317 | ir_ref_inst_gen(cases[i].value); | ||
| 3318 | } | ||
| 3319 | |||
| 3320 | return instruction; | ||
| 3321 | } | ||
| 3322 | |||
| 3323 | static IrInstSrc *ir_build_switch_target(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3324 | IrInstSrc *target_value_ptr) | ||
| 3325 | { | ||
| 3326 | IrInstSrcSwitchTarget *instruction = ir_build_instruction<IrInstSrcSwitchTarget>(irb, scope, source_node); | ||
| 3327 | instruction->target_value_ptr = target_value_ptr; | ||
| 3328 | |||
| 3329 | ir_ref_instruction(target_value_ptr, irb->current_basic_block); | ||
| 3330 | |||
| 3331 | return &instruction->base; | ||
| 3332 | } | ||
| 3333 | |||
| 3334 | static IrInstSrc *ir_build_switch_var(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3335 | IrInstSrc *target_value_ptr, IrInstSrc **prongs_ptr, size_t prongs_len) | ||
| 3336 | { | ||
| 3337 | IrInstSrcSwitchVar *instruction = ir_build_instruction<IrInstSrcSwitchVar>(irb, scope, source_node); | ||
| 3338 | instruction->target_value_ptr = target_value_ptr; | ||
| 3339 | instruction->prongs_ptr = prongs_ptr; | ||
| 3340 | instruction->prongs_len = prongs_len; | ||
| 3341 | |||
| 3342 | ir_ref_instruction(target_value_ptr, irb->current_basic_block); | ||
| 3343 | for (size_t i = 0; i < prongs_len; i += 1) { | ||
| 3344 | ir_ref_instruction(prongs_ptr[i], irb->current_basic_block); | ||
| 3345 | } | ||
| 3346 | |||
| 3347 | return &instruction->base; | ||
| 3348 | } | ||
| 3349 | |||
| 3350 | // For this instruction the switch_br must be set later. | ||
| 3351 | static IrInstSrcSwitchElseVar *ir_build_switch_else_var(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3352 | IrInstSrc *target_value_ptr) | ||
| 3353 | { | ||
| 3354 | IrInstSrcSwitchElseVar *instruction = ir_build_instruction<IrInstSrcSwitchElseVar>(irb, scope, source_node); | ||
| 3355 | instruction->target_value_ptr = target_value_ptr; | ||
| 3356 | |||
| 3357 | ir_ref_instruction(target_value_ptr, irb->current_basic_block); | ||
| 3358 | |||
| 3359 | return instruction; | ||
| 3360 | } | ||
| 3361 | |||
| 3362 | static IrInstGen *ir_build_union_tag(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value, | ||
| 3363 | ZigType *tag_type) | ||
| 3364 | { | ||
| 3365 | IrInstGenUnionTag *instruction = ir_build_inst_gen<IrInstGenUnionTag>(&ira->new_irb, | ||
| 3366 | source_instr->scope, source_instr->source_node); | ||
| 3367 | instruction->value = value; | ||
| 3368 | instruction->base.value->type = tag_type; | ||
| 3369 | |||
| 3370 | ir_ref_inst_gen(value); | ||
| 3371 | |||
| 3372 | return &instruction->base; | ||
| 3373 | } | ||
| 3374 | |||
| 3375 | static IrInstSrc *ir_build_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { | ||
| 3376 | IrInstSrcImport *instruction = ir_build_instruction<IrInstSrcImport>(irb, scope, source_node); | ||
| 3377 | instruction->name = name; | ||
| 3378 | |||
| 3379 | ir_ref_instruction(name, irb->current_basic_block); | ||
| 3380 | |||
| 3381 | return &instruction->base; | ||
| 3382 | } | ||
| 3383 | |||
| 3384 | static IrInstSrc *ir_build_ref_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { | ||
| 3385 | IrInstSrcRef *instruction = ir_build_instruction<IrInstSrcRef>(irb, scope, source_node); | ||
| 3386 | instruction->value = value; | ||
| 3387 | |||
| 3388 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 3389 | |||
| 3390 | return &instruction->base; | ||
| 3391 | } | ||
| 3392 | |||
| 3393 | static IrInstGen *ir_build_ref_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type, | ||
| 3394 | IrInstGen *operand, IrInstGen *result_loc) | ||
| 3395 | { | ||
| 3396 | IrInstGenRef *instruction = ir_build_inst_gen<IrInstGenRef>(&ira->new_irb, | ||
| 3397 | source_instruction->scope, source_instruction->source_node); | ||
| 3398 | instruction->base.value->type = result_type; | ||
| 3399 | instruction->operand = operand; | ||
| 3400 | instruction->result_loc = result_loc; | ||
| 3401 | |||
| 3402 | ir_ref_inst_gen(operand); | ||
| 3403 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); | ||
| 3404 | |||
| 3405 | return &instruction->base; | ||
| 3406 | } | ||
| 3407 | |||
| 3408 | static IrInstSrc *ir_build_compile_err(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *msg) { | ||
| 3409 | IrInstSrcCompileErr *instruction = ir_build_instruction<IrInstSrcCompileErr>(irb, scope, source_node); | ||
| 3410 | instruction->msg = msg; | ||
| 3411 | |||
| 3412 | ir_ref_instruction(msg, irb->current_basic_block); | ||
| 3413 | |||
| 3414 | return &instruction->base; | ||
| 3415 | } | ||
| 3416 | |||
| 3417 | static IrInstSrc *ir_build_compile_log(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3418 | size_t msg_count, IrInstSrc **msg_list) | ||
| 3419 | { | ||
| 3420 | IrInstSrcCompileLog *instruction = ir_build_instruction<IrInstSrcCompileLog>(irb, scope, source_node); | ||
| 3421 | instruction->msg_count = msg_count; | ||
| 3422 | instruction->msg_list = msg_list; | ||
| 3423 | |||
| 3424 | for (size_t i = 0; i < msg_count; i += 1) { | ||
| 3425 | ir_ref_instruction(msg_list[i], irb->current_basic_block); | ||
| 3426 | } | ||
| 3427 | |||
| 3428 | return &instruction->base; | ||
| 3429 | } | ||
| 3430 | |||
| 3431 | static IrInstSrc *ir_build_err_name(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { | ||
| 3432 | IrInstSrcErrName *instruction = ir_build_instruction<IrInstSrcErrName>(irb, scope, source_node); | ||
| 3433 | instruction->value = value; | ||
| 3434 | |||
| 3435 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 3436 | |||
| 3437 | return &instruction->base; | ||
| 3438 | } | ||
| 3439 | |||
| 3440 | static IrInstGen *ir_build_err_name_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value, | ||
| 3441 | ZigType *str_type) | ||
| 3442 | { | ||
| 3443 | IrInstGenErrName *instruction = ir_build_inst_gen<IrInstGenErrName>(&ira->new_irb, | ||
| 3444 | source_instr->scope, source_instr->source_node); | ||
| 3445 | instruction->base.value->type = str_type; | ||
| 3446 | instruction->value = value; | ||
| 3447 | |||
| 3448 | ir_ref_inst_gen(value); | ||
| 3449 | |||
| 3450 | return &instruction->base; | ||
| 3451 | } | ||
| 3452 | |||
| 3453 | static IrInstSrc *ir_build_c_import(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | ||
| 3454 | IrInstSrcCImport *instruction = ir_build_instruction<IrInstSrcCImport>(irb, scope, source_node); | ||
| 3455 | return &instruction->base; | ||
| 3456 | } | ||
| 3457 | |||
| 3458 | static IrInstSrc *ir_build_c_include(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { | ||
| 3459 | IrInstSrcCInclude *instruction = ir_build_instruction<IrInstSrcCInclude>(irb, scope, source_node); | ||
| 3460 | instruction->name = name; | ||
| 3461 | |||
| 3462 | ir_ref_instruction(name, irb->current_basic_block); | ||
| 3463 | |||
| 3464 | return &instruction->base; | ||
| 3465 | } | ||
| 3466 | |||
| 3467 | static IrInstSrc *ir_build_c_define(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name, IrInstSrc *value) { | ||
| 3468 | IrInstSrcCDefine *instruction = ir_build_instruction<IrInstSrcCDefine>(irb, scope, source_node); | ||
| 3469 | instruction->name = name; | ||
| 3470 | instruction->value = value; | ||
| 3471 | |||
| 3472 | ir_ref_instruction(name, irb->current_basic_block); | ||
| 3473 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 3474 | |||
| 3475 | return &instruction->base; | ||
| 3476 | } | ||
| 3477 | |||
| 3478 | static IrInstSrc *ir_build_c_undef(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { | ||
| 3479 | IrInstSrcCUndef *instruction = ir_build_instruction<IrInstSrcCUndef>(irb, scope, source_node); | ||
| 3480 | instruction->name = name; | ||
| 3481 | |||
| 3482 | ir_ref_instruction(name, irb->current_basic_block); | ||
| 3483 | |||
| 3484 | return &instruction->base; | ||
| 3485 | } | ||
| 3486 | |||
| 3487 | static IrInstSrc *ir_build_embed_file(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *name) { | ||
| 3488 | IrInstSrcEmbedFile *instruction = ir_build_instruction<IrInstSrcEmbedFile>(irb, scope, source_node); | ||
| 3489 | instruction->name = name; | ||
| 3490 | |||
| 3491 | ir_ref_instruction(name, irb->current_basic_block); | ||
| 3492 | |||
| 3493 | return &instruction->base; | ||
| 3494 | } | ||
| 3495 | |||
| 3496 | static IrInstSrc *ir_build_cmpxchg_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3497 | IrInstSrc *type_value, IrInstSrc *ptr, IrInstSrc *cmp_value, IrInstSrc *new_value, | ||
| 3498 | IrInstSrc *success_order_value, IrInstSrc *failure_order_value, bool is_weak, ResultLoc *result_loc) | ||
| 3499 | { | ||
| 3500 | IrInstSrcCmpxchg *instruction = ir_build_instruction<IrInstSrcCmpxchg>(irb, scope, source_node); | ||
| 3501 | instruction->type_value = type_value; | ||
| 3502 | instruction->ptr = ptr; | ||
| 3503 | instruction->cmp_value = cmp_value; | ||
| 3504 | instruction->new_value = new_value; | ||
| 3505 | instruction->success_order_value = success_order_value; | ||
| 3506 | instruction->failure_order_value = failure_order_value; | ||
| 3507 | instruction->is_weak = is_weak; | ||
| 3508 | instruction->result_loc = result_loc; | ||
| 3509 | |||
| 3510 | ir_ref_instruction(type_value, irb->current_basic_block); | ||
| 3511 | ir_ref_instruction(ptr, irb->current_basic_block); | ||
| 3512 | ir_ref_instruction(cmp_value, irb->current_basic_block); | ||
| 3513 | ir_ref_instruction(new_value, irb->current_basic_block); | ||
| 3514 | ir_ref_instruction(success_order_value, irb->current_basic_block); | ||
| 3515 | ir_ref_instruction(failure_order_value, irb->current_basic_block); | ||
| 3516 | |||
| 3517 | return &instruction->base; | ||
| 3518 | } | ||
| 3519 | |||
| 3520 | static IrInstGen *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type, | ||
| 3521 | IrInstGen *ptr, IrInstGen *cmp_value, IrInstGen *new_value, | ||
| 3522 | AtomicOrder success_order, AtomicOrder failure_order, bool is_weak, IrInstGen *result_loc) | ||
| 3523 | { | ||
| 3524 | IrInstGenCmpxchg *instruction = ir_build_inst_gen<IrInstGenCmpxchg>(&ira->new_irb, | ||
| 3525 | source_instruction->scope, source_instruction->source_node); | ||
| 3526 | instruction->base.value->type = result_type; | ||
| 3527 | instruction->ptr = ptr; | ||
| 3528 | instruction->cmp_value = cmp_value; | ||
| 3529 | instruction->new_value = new_value; | ||
| 3530 | instruction->success_order = success_order; | ||
| 3531 | instruction->failure_order = failure_order; | ||
| 3532 | instruction->is_weak = is_weak; | ||
| 3533 | instruction->result_loc = result_loc; | ||
| 3534 | |||
| 3535 | ir_ref_inst_gen(ptr); | ||
| 3536 | ir_ref_inst_gen(cmp_value); | ||
| 3537 | ir_ref_inst_gen(new_value); | ||
| 3538 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); | ||
| 3539 | |||
| 3540 | return &instruction->base; | ||
| 3541 | } | ||
| 3542 | |||
| 3543 | static IrInstSrc *ir_build_fence(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *order) { | ||
| 3544 | IrInstSrcFence *instruction = ir_build_instruction<IrInstSrcFence>(irb, scope, source_node); | ||
| 3545 | instruction->order = order; | ||
| 3546 | |||
| 3547 | ir_ref_instruction(order, irb->current_basic_block); | ||
| 3548 | |||
| 3549 | return &instruction->base; | ||
| 3550 | } | ||
| 3551 | |||
| 3552 | static IrInstGen *ir_build_fence_gen(IrAnalyze *ira, IrInst *source_instr, AtomicOrder order) { | ||
| 3553 | IrInstGenFence *instruction = ir_build_inst_void<IrInstGenFence>(&ira->new_irb, | ||
| 3554 | source_instr->scope, source_instr->source_node); | ||
| 3555 | instruction->order = order; | ||
| 3556 | |||
| 3557 | return &instruction->base; | ||
| 3558 | } | ||
| 3559 | |||
| 3560 | static IrInstSrc *ir_build_reduce(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *op, IrInstSrc *value) { | ||
| 3561 | IrInstSrcReduce *instruction = ir_build_instruction<IrInstSrcReduce>(irb, scope, source_node); | ||
| 3562 | instruction->op = op; | ||
| 3563 | instruction->value = value; | ||
| 3564 | |||
| 3565 | ir_ref_instruction(op, irb->current_basic_block); | ||
| 3566 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 3567 | |||
| 3568 | return &instruction->base; | ||
| 3569 | } | ||
| 3570 | |||
| 3571 | static IrInstGen *ir_build_reduce_gen(IrAnalyze *ira, IrInst *source_instruction, ReduceOp op, IrInstGen *value, ZigType *result_type) { | ||
| 3572 | IrInstGenReduce *instruction = ir_build_inst_gen<IrInstGenReduce>(&ira->new_irb, | ||
| 3573 | source_instruction->scope, source_instruction->source_node); | ||
| 3574 | instruction->base.value->type = result_type; | ||
| 3575 | instruction->op = op; | ||
| 3576 | instruction->value = value; | ||
| 3577 | |||
| 3578 | ir_ref_inst_gen(value); | ||
| 3579 | |||
| 3580 | return &instruction->base; | ||
| 3581 | } | ||
| 3582 | |||
| 3583 | static IrInstSrc *ir_build_truncate(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3584 | IrInstSrc *dest_type, IrInstSrc *target) | ||
| 3585 | { | ||
| 3586 | IrInstSrcTruncate *instruction = ir_build_instruction<IrInstSrcTruncate>(irb, scope, source_node); | ||
| 3587 | instruction->dest_type = dest_type; | ||
| 3588 | instruction->target = target; | ||
| 3589 | |||
| 3590 | ir_ref_instruction(dest_type, irb->current_basic_block); | ||
| 3591 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 3592 | |||
| 3593 | return &instruction->base; | ||
| 3594 | } | ||
| 3595 | |||
| 3596 | static IrInstGen *ir_build_truncate_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *dest_type, | ||
| 3597 | IrInstGen *target) | ||
| 3598 | { | ||
| 3599 | IrInstGenTruncate *instruction = ir_build_inst_gen<IrInstGenTruncate>(&ira->new_irb, | ||
| 3600 | source_instr->scope, source_instr->source_node); | ||
| 3601 | instruction->base.value->type = dest_type; | ||
| 3602 | instruction->target = target; | ||
| 3603 | |||
| 3604 | ir_ref_inst_gen(target); | ||
| 3605 | |||
| 3606 | return &instruction->base; | ||
| 3607 | } | ||
| 3608 | |||
| 3609 | static IrInstSrc *ir_build_int_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, | ||
| 3610 | IrInstSrc *target) | ||
| 3611 | { | ||
| 3612 | IrInstSrcIntCast *instruction = ir_build_instruction<IrInstSrcIntCast>(irb, scope, source_node); | ||
| 3613 | instruction->dest_type = dest_type; | ||
| 3614 | instruction->target = target; | ||
| 3615 | |||
| 3616 | ir_ref_instruction(dest_type, irb->current_basic_block); | ||
| 3617 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 3618 | |||
| 3619 | return &instruction->base; | ||
| 3620 | } | ||
| 3621 | |||
| 3622 | static IrInstSrc *ir_build_float_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, | ||
| 3623 | IrInstSrc *target) | ||
| 3624 | { | ||
| 3625 | IrInstSrcFloatCast *instruction = ir_build_instruction<IrInstSrcFloatCast>(irb, scope, source_node); | ||
| 3626 | instruction->dest_type = dest_type; | ||
| 3627 | instruction->target = target; | ||
| 3628 | |||
| 3629 | ir_ref_instruction(dest_type, irb->current_basic_block); | ||
| 3630 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 3631 | |||
| 3632 | return &instruction->base; | ||
| 3633 | } | ||
| 3634 | |||
| 3635 | static IrInstSrc *ir_build_err_set_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3636 | IrInstSrc *dest_type, IrInstSrc *target) | ||
| 3637 | { | ||
| 3638 | IrInstSrcErrSetCast *instruction = ir_build_instruction<IrInstSrcErrSetCast>(irb, scope, source_node); | ||
| 3639 | instruction->dest_type = dest_type; | ||
| 3640 | instruction->target = target; | ||
| 3641 | |||
| 3642 | ir_ref_instruction(dest_type, irb->current_basic_block); | ||
| 3643 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 3644 | |||
| 3645 | return &instruction->base; | ||
| 3646 | } | ||
| 3647 | |||
| 3648 | static IrInstSrc *ir_build_int_to_float(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3649 | IrInstSrc *dest_type, IrInstSrc *target) | ||
| 3650 | { | ||
| 3651 | IrInstSrcIntToFloat *instruction = ir_build_instruction<IrInstSrcIntToFloat>(irb, scope, source_node); | ||
| 3652 | instruction->dest_type = dest_type; | ||
| 3653 | instruction->target = target; | ||
| 3654 | |||
| 3655 | ir_ref_instruction(dest_type, irb->current_basic_block); | ||
| 3656 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 3657 | |||
| 3658 | return &instruction->base; | ||
| 3659 | } | ||
| 3660 | |||
| 3661 | static IrInstSrc *ir_build_float_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3662 | IrInstSrc *dest_type, IrInstSrc *target) | ||
| 3663 | { | ||
| 3664 | IrInstSrcFloatToInt *instruction = ir_build_instruction<IrInstSrcFloatToInt>(irb, scope, source_node); | ||
| 3665 | instruction->dest_type = dest_type; | ||
| 3666 | instruction->target = target; | ||
| 3667 | |||
| 3668 | ir_ref_instruction(dest_type, irb->current_basic_block); | ||
| 3669 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 3670 | |||
| 3671 | return &instruction->base; | ||
| 3672 | } | ||
| 3673 | |||
| 3674 | static IrInstSrc *ir_build_bool_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target) { | ||
| 3675 | IrInstSrcBoolToInt *instruction = ir_build_instruction<IrInstSrcBoolToInt>(irb, scope, source_node); | ||
| 3676 | instruction->target = target; | ||
| 3677 | |||
| 3678 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 3679 | |||
| 3680 | return &instruction->base; | ||
| 3681 | } | ||
| 3682 | |||
| 3683 | static IrInstSrc *ir_build_vector_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *len, | ||
| 3684 | IrInstSrc *elem_type) | ||
| 3685 | { | ||
| 3686 | IrInstSrcVectorType *instruction = ir_build_instruction<IrInstSrcVectorType>(irb, scope, source_node); | ||
| 3687 | instruction->len = len; | ||
| 3688 | instruction->elem_type = elem_type; | ||
| 3689 | |||
| 3690 | ir_ref_instruction(len, irb->current_basic_block); | ||
| 3691 | ir_ref_instruction(elem_type, irb->current_basic_block); | ||
| 3692 | |||
| 3693 | return &instruction->base; | ||
| 3694 | } | ||
| 3695 | |||
| 3696 | static IrInstSrc *ir_build_shuffle_vector(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3697 | IrInstSrc *scalar_type, IrInstSrc *a, IrInstSrc *b, IrInstSrc *mask) | ||
| 3698 | { | ||
| 3699 | IrInstSrcShuffleVector *instruction = ir_build_instruction<IrInstSrcShuffleVector>(irb, scope, source_node); | ||
| 3700 | instruction->scalar_type = scalar_type; | ||
| 3701 | instruction->a = a; | ||
| 3702 | instruction->b = b; | ||
| 3703 | instruction->mask = mask; | ||
| 3704 | |||
| 3705 | if (scalar_type != nullptr) ir_ref_instruction(scalar_type, irb->current_basic_block); | ||
| 3706 | ir_ref_instruction(a, irb->current_basic_block); | ||
| 3707 | ir_ref_instruction(b, irb->current_basic_block); | ||
| 3708 | ir_ref_instruction(mask, irb->current_basic_block); | ||
| 3709 | |||
| 3710 | return &instruction->base; | ||
| 3711 | } | ||
| 3712 | |||
| 3713 | static IrInstGen *ir_build_shuffle_vector_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, | ||
| 3714 | ZigType *result_type, IrInstGen *a, IrInstGen *b, IrInstGen *mask) | ||
| 3715 | { | ||
| 3716 | IrInstGenShuffleVector *inst = ir_build_inst_gen<IrInstGenShuffleVector>(&ira->new_irb, scope, source_node); | ||
| 3717 | inst->base.value->type = result_type; | ||
| 3718 | inst->a = a; | ||
| 3719 | inst->b = b; | ||
| 3720 | inst->mask = mask; | ||
| 3721 | |||
| 3722 | ir_ref_inst_gen(a); | ||
| 3723 | ir_ref_inst_gen(b); | ||
| 3724 | ir_ref_inst_gen(mask); | ||
| 3725 | |||
| 3726 | return &inst->base; | ||
| 3727 | } | ||
| 3728 | |||
| 3729 | static IrInstSrc *ir_build_splat_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3730 | IrInstSrc *len, IrInstSrc *scalar) | ||
| 3731 | { | ||
| 3732 | IrInstSrcSplat *instruction = ir_build_instruction<IrInstSrcSplat>(irb, scope, source_node); | ||
| 3733 | instruction->len = len; | ||
| 3734 | instruction->scalar = scalar; | ||
| 3735 | |||
| 3736 | ir_ref_instruction(len, irb->current_basic_block); | ||
| 3737 | ir_ref_instruction(scalar, irb->current_basic_block); | ||
| 3738 | |||
| 3739 | return &instruction->base; | ||
| 3740 | } | ||
| 3741 | |||
| 3742 | static IrInstGen *ir_build_splat_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *result_type, | ||
| 3743 | IrInstGen *scalar) | ||
| 3744 | { | ||
| 3745 | IrInstGenSplat *instruction = ir_build_inst_gen<IrInstGenSplat>( | ||
| 3746 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 3747 | instruction->base.value->type = result_type; | ||
| 3748 | instruction->scalar = scalar; | ||
| 3749 | |||
| 3750 | ir_ref_inst_gen(scalar); | ||
| 3751 | |||
| 3752 | return &instruction->base; | ||
| 3753 | } | ||
| 3754 | |||
| 3755 | static IrInstSrc *ir_build_bool_not(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { | ||
| 3756 | IrInstSrcBoolNot *instruction = ir_build_instruction<IrInstSrcBoolNot>(irb, scope, source_node); | ||
| 3757 | instruction->value = value; | ||
| 3758 | |||
| 3759 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 3760 | |||
| 3761 | return &instruction->base; | ||
| 3762 | } | ||
| 3763 | |||
| 3764 | static IrInstGen *ir_build_bool_not_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *value) { | ||
| 3765 | IrInstGenBoolNot *instruction = ir_build_inst_gen<IrInstGenBoolNot>(&ira->new_irb, | ||
| 3766 | source_instr->scope, source_instr->source_node); | ||
| 3767 | instruction->base.value->type = ira->codegen->builtin_types.entry_bool; | ||
| 3768 | instruction->value = value; | ||
| 3769 | |||
| 3770 | ir_ref_inst_gen(value); | ||
| 3771 | |||
| 3772 | return &instruction->base; | ||
| 3773 | } | ||
| 3774 | |||
| 3775 | static IrInstSrc *ir_build_memset_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3776 | IrInstSrc *dest_ptr, IrInstSrc *byte, IrInstSrc *count) | ||
| 3777 | { | ||
| 3778 | IrInstSrcMemset *instruction = ir_build_instruction<IrInstSrcMemset>(irb, scope, source_node); | ||
| 3779 | instruction->dest_ptr = dest_ptr; | ||
| 3780 | instruction->byte = byte; | ||
| 3781 | instruction->count = count; | ||
| 3782 | |||
| 3783 | ir_ref_instruction(dest_ptr, irb->current_basic_block); | ||
| 3784 | ir_ref_instruction(byte, irb->current_basic_block); | ||
| 3785 | ir_ref_instruction(count, irb->current_basic_block); | ||
| 3786 | |||
| 3787 | return &instruction->base; | ||
| 3788 | } | ||
| 3789 | |||
| 3790 | static IrInstGen *ir_build_memset_gen(IrAnalyze *ira, IrInst *source_instr, | ||
| 3791 | IrInstGen *dest_ptr, IrInstGen *byte, IrInstGen *count) | ||
| 3792 | { | ||
| 3793 | IrInstGenMemset *instruction = ir_build_inst_void<IrInstGenMemset>(&ira->new_irb, | ||
| 3794 | source_instr->scope, source_instr->source_node); | ||
| 3795 | instruction->dest_ptr = dest_ptr; | ||
| 3796 | instruction->byte = byte; | ||
| 3797 | instruction->count = count; | ||
| 3798 | |||
| 3799 | ir_ref_inst_gen(dest_ptr); | ||
| 3800 | ir_ref_inst_gen(byte); | ||
| 3801 | ir_ref_inst_gen(count); | ||
| 3802 | |||
| 3803 | return &instruction->base; | ||
| 3804 | } | ||
| 3805 | |||
| 3806 | static IrInstSrc *ir_build_memcpy_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3807 | IrInstSrc *dest_ptr, IrInstSrc *src_ptr, IrInstSrc *count) | ||
| 3808 | { | ||
| 3809 | IrInstSrcMemcpy *instruction = ir_build_instruction<IrInstSrcMemcpy>(irb, scope, source_node); | ||
| 3810 | instruction->dest_ptr = dest_ptr; | ||
| 3811 | instruction->src_ptr = src_ptr; | ||
| 3812 | instruction->count = count; | ||
| 3813 | |||
| 3814 | ir_ref_instruction(dest_ptr, irb->current_basic_block); | ||
| 3815 | ir_ref_instruction(src_ptr, irb->current_basic_block); | ||
| 3816 | ir_ref_instruction(count, irb->current_basic_block); | ||
| 3817 | |||
| 3818 | return &instruction->base; | ||
| 3819 | } | ||
| 3820 | |||
| 3821 | static IrInstGen *ir_build_memcpy_gen(IrAnalyze *ira, IrInst *source_instr, | ||
| 3822 | IrInstGen *dest_ptr, IrInstGen *src_ptr, IrInstGen *count) | ||
| 3823 | { | ||
| 3824 | IrInstGenMemcpy *instruction = ir_build_inst_void<IrInstGenMemcpy>(&ira->new_irb, | ||
| 3825 | source_instr->scope, source_instr->source_node); | ||
| 3826 | instruction->dest_ptr = dest_ptr; | ||
| 3827 | instruction->src_ptr = src_ptr; | ||
| 3828 | instruction->count = count; | ||
| 3829 | |||
| 3830 | ir_ref_inst_gen(dest_ptr); | ||
| 3831 | ir_ref_inst_gen(src_ptr); | ||
| 3832 | ir_ref_inst_gen(count); | ||
| 3833 | |||
| 3834 | return &instruction->base; | ||
| 3835 | } | ||
| 3836 | |||
| 3837 | static IrInstSrc *ir_build_slice_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3838 | IrInstSrc *ptr, IrInstSrc *start, IrInstSrc *end, IrInstSrc *sentinel, | ||
| 3839 | bool safety_check_on, ResultLoc *result_loc) | ||
| 3840 | { | ||
| 3841 | IrInstSrcSlice *instruction = ir_build_instruction<IrInstSrcSlice>(irb, scope, source_node); | ||
| 3842 | instruction->ptr = ptr; | ||
| 3843 | instruction->start = start; | ||
| 3844 | instruction->end = end; | ||
| 3845 | instruction->sentinel = sentinel; | ||
| 3846 | instruction->safety_check_on = safety_check_on; | ||
| 3847 | instruction->result_loc = result_loc; | ||
| 3848 | |||
| 3849 | ir_ref_instruction(ptr, irb->current_basic_block); | ||
| 3850 | ir_ref_instruction(start, irb->current_basic_block); | ||
| 3851 | if (end) ir_ref_instruction(end, irb->current_basic_block); | ||
| 3852 | if (sentinel) ir_ref_instruction(sentinel, irb->current_basic_block); | ||
| 3853 | |||
| 3854 | return &instruction->base; | ||
| 3855 | } | ||
| 3856 | |||
| 3857 | static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction, ZigType *slice_type, | ||
| 3858 | IrInstGen *ptr, IrInstGen *start, IrInstGen *end, bool safety_check_on, IrInstGen *result_loc, | ||
| 3859 | ZigValue *sentinel) | ||
| 3860 | { | ||
| 3861 | IrInstGenSlice *instruction = ir_build_inst_gen<IrInstGenSlice>( | ||
| 3862 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 3863 | instruction->base.value->type = slice_type; | ||
| 3864 | instruction->ptr = ptr; | ||
| 3865 | instruction->start = start; | ||
| 3866 | instruction->end = end; | ||
| 3867 | instruction->safety_check_on = safety_check_on; | ||
| 3868 | instruction->result_loc = result_loc; | ||
| 3869 | instruction->sentinel = sentinel; | ||
| 3870 | |||
| 3871 | ir_ref_inst_gen(ptr); | ||
| 3872 | ir_ref_inst_gen(start); | ||
| 3873 | if (end != nullptr) ir_ref_inst_gen(end); | ||
| 3874 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); | ||
| 3875 | |||
| 3876 | return &instruction->base; | ||
| 3877 | } | ||
| 3878 | |||
| 3879 | static IrInstSrc *ir_build_breakpoint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | ||
| 3880 | IrInstSrcBreakpoint *instruction = ir_build_instruction<IrInstSrcBreakpoint>(irb, scope, source_node); | ||
| 3881 | return &instruction->base; | ||
| 3882 | } | ||
| 3883 | |||
| 3884 | static IrInstGen *ir_build_breakpoint_gen(IrAnalyze *ira, IrInst *source_instr) { | ||
| 3885 | IrInstGenBreakpoint *instruction = ir_build_inst_void<IrInstGenBreakpoint>(&ira->new_irb, | ||
| 3886 | source_instr->scope, source_instr->source_node); | ||
| 3887 | return &instruction->base; | ||
| 3888 | } | ||
| 3889 | |||
| 3890 | static IrInstSrc *ir_build_return_address_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | ||
| 3891 | IrInstSrcReturnAddress *instruction = ir_build_instruction<IrInstSrcReturnAddress>(irb, scope, source_node); | ||
| 3892 | return &instruction->base; | ||
| 3893 | } | ||
| 3894 | |||
| 3895 | static IrInstGen *ir_build_return_address_gen(IrAnalyze *ira, IrInst *source_instr) { | ||
| 3896 | IrInstGenReturnAddress *inst = ir_build_inst_gen<IrInstGenReturnAddress>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 3897 | inst->base.value->type = ira->codegen->builtin_types.entry_usize; | ||
| 3898 | return &inst->base; | ||
| 3899 | } | ||
| 3900 | |||
| 3901 | static IrInstSrc *ir_build_frame_address_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | ||
| 3902 | IrInstSrcFrameAddress *inst = ir_build_instruction<IrInstSrcFrameAddress>(irb, scope, source_node); | ||
| 3903 | return &inst->base; | ||
| 3904 | } | ||
| 3905 | |||
| 3906 | static IrInstGen *ir_build_frame_address_gen(IrAnalyze *ira, IrInst *source_instr) { | ||
| 3907 | IrInstGenFrameAddress *inst = ir_build_inst_gen<IrInstGenFrameAddress>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 3908 | inst->base.value->type = ira->codegen->builtin_types.entry_usize; | ||
| 3909 | return &inst->base; | ||
| 3910 | } | ||
| 3911 | |||
| 3912 | static IrInstSrc *ir_build_handle_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | ||
| 3913 | IrInstSrcFrameHandle *inst = ir_build_instruction<IrInstSrcFrameHandle>(irb, scope, source_node); | ||
| 3914 | return &inst->base; | ||
| 3915 | } | ||
| 3916 | |||
| 3917 | static IrInstGen *ir_build_handle_gen(IrAnalyze *ira, IrInst *source_instr, ZigType *ty) { | ||
| 3918 | IrInstGenFrameHandle *inst = ir_build_inst_gen<IrInstGenFrameHandle>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 3919 | inst->base.value->type = ty; | ||
| 3920 | return &inst->base; | ||
| 3921 | } | ||
| 3922 | |||
| 3923 | static IrInstSrc *ir_build_frame_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *fn) { | ||
| 3924 | IrInstSrcFrameType *inst = ir_build_instruction<IrInstSrcFrameType>(irb, scope, source_node); | ||
| 3925 | inst->fn = fn; | ||
| 3926 | |||
| 3927 | ir_ref_instruction(fn, irb->current_basic_block); | ||
| 3928 | |||
| 3929 | return &inst->base; | ||
| 3930 | } | ||
| 3931 | |||
| 3932 | static IrInstSrc *ir_build_frame_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *fn) { | ||
| 3933 | IrInstSrcFrameSize *inst = ir_build_instruction<IrInstSrcFrameSize>(irb, scope, source_node); | ||
| 3934 | inst->fn = fn; | ||
| 3935 | |||
| 3936 | ir_ref_instruction(fn, irb->current_basic_block); | ||
| 3937 | |||
| 3938 | return &inst->base; | ||
| 3939 | } | ||
| 3940 | |||
| 3941 | static IrInstGen *ir_build_frame_size_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *fn) | ||
| 3942 | { | ||
| 3943 | IrInstGenFrameSize *inst = ir_build_inst_gen<IrInstGenFrameSize>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 3944 | inst->base.value->type = ira->codegen->builtin_types.entry_usize; | ||
| 3945 | inst->fn = fn; | ||
| 3946 | |||
| 3947 | ir_ref_inst_gen(fn); | ||
| 3948 | |||
| 3949 | return &inst->base; | ||
| 3950 | } | ||
| 3951 | |||
| 3952 | static IrInstSrc *ir_build_overflow_op_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 3953 | IrOverflowOp op, IrInstSrc *type_value, IrInstSrc *op1, IrInstSrc *op2, IrInstSrc *result_ptr) | ||
| 3954 | { | ||
| 3955 | IrInstSrcOverflowOp *instruction = ir_build_instruction<IrInstSrcOverflowOp>(irb, scope, source_node); | ||
| 3956 | instruction->op = op; | ||
| 3957 | instruction->type_value = type_value; | ||
| 3958 | instruction->op1 = op1; | ||
| 3959 | instruction->op2 = op2; | ||
| 3960 | instruction->result_ptr = result_ptr; | ||
| 3961 | |||
| 3962 | ir_ref_instruction(type_value, irb->current_basic_block); | ||
| 3963 | ir_ref_instruction(op1, irb->current_basic_block); | ||
| 3964 | ir_ref_instruction(op2, irb->current_basic_block); | ||
| 3965 | ir_ref_instruction(result_ptr, irb->current_basic_block); | ||
| 3966 | |||
| 3967 | return &instruction->base; | ||
| 3968 | } | ||
| 3969 | |||
| 3970 | static IrInstGen *ir_build_overflow_op_gen(IrAnalyze *ira, IrInst *source_instr, | ||
| 3971 | IrOverflowOp op, IrInstGen *op1, IrInstGen *op2, IrInstGen *result_ptr, | ||
| 3972 | ZigType *result_ptr_type) | ||
| 3973 | { | ||
| 3974 | IrInstGenOverflowOp *instruction = ir_build_inst_gen<IrInstGenOverflowOp>(&ira->new_irb, | ||
| 3975 | source_instr->scope, source_instr->source_node); | ||
| 3976 | instruction->base.value->type = ira->codegen->builtin_types.entry_bool; | ||
| 3977 | instruction->op = op; | ||
| 3978 | instruction->op1 = op1; | ||
| 3979 | instruction->op2 = op2; | ||
| 3980 | instruction->result_ptr = result_ptr; | ||
| 3981 | instruction->result_ptr_type = result_ptr_type; | ||
| 3982 | |||
| 3983 | ir_ref_inst_gen(op1); | ||
| 3984 | ir_ref_inst_gen(op2); | ||
| 3985 | ir_ref_inst_gen(result_ptr); | ||
| 3986 | |||
| 3987 | return &instruction->base; | ||
| 3988 | } | ||
| 3989 | |||
| 3990 | static IrInstSrc *ir_build_float_op_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *operand, | ||
| 3991 | BuiltinFnId fn_id) | ||
| 3992 | { | ||
| 3993 | IrInstSrcFloatOp *instruction = ir_build_instruction<IrInstSrcFloatOp>(irb, scope, source_node); | ||
| 3994 | instruction->operand = operand; | ||
| 3995 | instruction->fn_id = fn_id; | ||
| 3996 | |||
| 3997 | ir_ref_instruction(operand, irb->current_basic_block); | ||
| 3998 | |||
| 3999 | return &instruction->base; | ||
| 4000 | } | ||
| 4001 | |||
| 4002 | static IrInstGen *ir_build_float_op_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, | ||
| 4003 | BuiltinFnId fn_id, ZigType *operand_type) | ||
| 4004 | { | ||
| 4005 | IrInstGenFloatOp *instruction = ir_build_inst_gen<IrInstGenFloatOp>(&ira->new_irb, | ||
| 4006 | source_instr->scope, source_instr->source_node); | ||
| 4007 | instruction->base.value->type = operand_type; | ||
| 4008 | instruction->operand = operand; | ||
| 4009 | instruction->fn_id = fn_id; | ||
| 4010 | |||
| 4011 | ir_ref_inst_gen(operand); | ||
| 4012 | |||
| 4013 | return &instruction->base; | ||
| 4014 | } | ||
| 4015 | |||
| 4016 | static IrInstSrc *ir_build_mul_add_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4017 | IrInstSrc *type_value, IrInstSrc *op1, IrInstSrc *op2, IrInstSrc *op3) | ||
| 4018 | { | ||
| 4019 | IrInstSrcMulAdd *instruction = ir_build_instruction<IrInstSrcMulAdd>(irb, scope, source_node); | ||
| 4020 | instruction->type_value = type_value; | ||
| 4021 | instruction->op1 = op1; | ||
| 4022 | instruction->op2 = op2; | ||
| 4023 | instruction->op3 = op3; | ||
| 4024 | |||
| 4025 | ir_ref_instruction(type_value, irb->current_basic_block); | ||
| 4026 | ir_ref_instruction(op1, irb->current_basic_block); | ||
| 4027 | ir_ref_instruction(op2, irb->current_basic_block); | ||
| 4028 | ir_ref_instruction(op3, irb->current_basic_block); | ||
| 4029 | |||
| 4030 | return &instruction->base; | ||
| 4031 | } | ||
| 4032 | |||
| 4033 | static IrInstGen *ir_build_mul_add_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *op1, IrInstGen *op2, | ||
| 4034 | IrInstGen *op3, ZigType *expr_type) | ||
| 4035 | { | ||
| 4036 | IrInstGenMulAdd *instruction = ir_build_inst_gen<IrInstGenMulAdd>(&ira->new_irb, | ||
| 4037 | source_instr->scope, source_instr->source_node); | ||
| 4038 | instruction->base.value->type = expr_type; | ||
| 4039 | instruction->op1 = op1; | ||
| 4040 | instruction->op2 = op2; | ||
| 4041 | instruction->op3 = op3; | ||
| 4042 | |||
| 4043 | ir_ref_inst_gen(op1); | ||
| 4044 | ir_ref_inst_gen(op2); | ||
| 4045 | ir_ref_inst_gen(op3); | ||
| 4046 | |||
| 4047 | return &instruction->base; | ||
| 4048 | } | ||
| 4049 | |||
| 4050 | static IrInstSrc *ir_build_align_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { | ||
| 4051 | IrInstSrcAlignOf *instruction = ir_build_instruction<IrInstSrcAlignOf>(irb, scope, source_node); | ||
| 4052 | instruction->type_value = type_value; | ||
| 4053 | |||
| 4054 | ir_ref_instruction(type_value, irb->current_basic_block); | ||
| 4055 | |||
| 4056 | return &instruction->base; | ||
| 4057 | } | ||
| 4058 | |||
| 4059 | static IrInstSrc *ir_build_test_err_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4060 | IrInstSrc *base_ptr, bool resolve_err_set, bool base_ptr_is_payload) | ||
| 4061 | { | ||
| 4062 | IrInstSrcTestErr *instruction = ir_build_instruction<IrInstSrcTestErr>(irb, scope, source_node); | ||
| 4063 | instruction->base_ptr = base_ptr; | ||
| 4064 | instruction->resolve_err_set = resolve_err_set; | ||
| 4065 | instruction->base_ptr_is_payload = base_ptr_is_payload; | ||
| 4066 | |||
| 4067 | ir_ref_instruction(base_ptr, irb->current_basic_block); | ||
| 4068 | |||
| 4069 | return &instruction->base; | ||
| 4070 | } | ||
| 4071 | |||
| 4072 | static IrInstGen *ir_build_test_err_gen(IrAnalyze *ira, IrInst *source_instruction, IrInstGen *err_union) { | ||
| 4073 | IrInstGenTestErr *instruction = ir_build_inst_gen<IrInstGenTestErr>( | ||
| 4074 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 4075 | instruction->base.value->type = ira->codegen->builtin_types.entry_bool; | ||
| 4076 | instruction->err_union = err_union; | ||
| 4077 | |||
| 4078 | ir_ref_inst_gen(err_union); | ||
| 4079 | |||
| 4080 | return &instruction->base; | ||
| 4081 | } | ||
| 4082 | |||
| 4083 | static IrInstSrc *ir_build_unwrap_err_code_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4084 | IrInstSrc *err_union_ptr) | ||
| 4085 | { | ||
| 4086 | IrInstSrcUnwrapErrCode *inst = ir_build_instruction<IrInstSrcUnwrapErrCode>(irb, scope, source_node); | ||
| 4087 | inst->err_union_ptr = err_union_ptr; | ||
| 4088 | |||
| 4089 | ir_ref_instruction(err_union_ptr, irb->current_basic_block); | ||
| 4090 | |||
| 4091 | return &inst->base; | ||
| 4092 | } | ||
| 4093 | |||
| 4094 | static IrInstGen *ir_build_unwrap_err_code_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, | ||
| 4095 | IrInstGen *err_union_ptr, ZigType *result_type) | ||
| 4096 | { | ||
| 4097 | IrInstGenUnwrapErrCode *inst = ir_build_inst_gen<IrInstGenUnwrapErrCode>(&ira->new_irb, scope, source_node); | ||
| 4098 | inst->base.value->type = result_type; | ||
| 4099 | inst->err_union_ptr = err_union_ptr; | ||
| 4100 | |||
| 4101 | ir_ref_inst_gen(err_union_ptr); | ||
| 4102 | |||
| 4103 | return &inst->base; | ||
| 4104 | } | ||
| 4105 | |||
| 4106 | static IrInstSrc *ir_build_unwrap_err_payload_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4107 | IrInstSrc *value, bool safety_check_on, bool initializing) | ||
| 4108 | { | ||
| 4109 | IrInstSrcUnwrapErrPayload *inst = ir_build_instruction<IrInstSrcUnwrapErrPayload>(irb, scope, source_node); | ||
| 4110 | inst->value = value; | ||
| 4111 | inst->safety_check_on = safety_check_on; | ||
| 4112 | inst->initializing = initializing; | ||
| 4113 | |||
| 4114 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 4115 | |||
| 4116 | return &inst->base; | ||
| 4117 | } | ||
| 4118 | |||
| 4119 | static IrInstGen *ir_build_unwrap_err_payload_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, | ||
| 4120 | IrInstGen *value, bool safety_check_on, bool initializing, ZigType *result_type) | ||
| 4121 | { | ||
| 4122 | IrInstGenUnwrapErrPayload *inst = ir_build_inst_gen<IrInstGenUnwrapErrPayload>(&ira->new_irb, scope, source_node); | ||
| 4123 | inst->base.value->type = result_type; | ||
| 4124 | inst->value = value; | ||
| 4125 | inst->safety_check_on = safety_check_on; | ||
| 4126 | inst->initializing = initializing; | ||
| 4127 | |||
| 4128 | ir_ref_inst_gen(value); | ||
| 4129 | |||
| 4130 | return &inst->base; | ||
| 4131 | } | ||
| 4132 | |||
| 4133 | static IrInstSrc *ir_build_fn_proto(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4134 | IrInstSrc **param_types, IrInstSrc *align_value, IrInstSrc *callconv_value, | ||
| 4135 | IrInstSrc *return_type, bool is_var_args) | ||
| 4136 | { | ||
| 4137 | IrInstSrcFnProto *instruction = ir_build_instruction<IrInstSrcFnProto>(irb, scope, source_node); | ||
| 4138 | instruction->param_types = param_types; | ||
| 4139 | instruction->align_value = align_value; | ||
| 4140 | instruction->callconv_value = callconv_value; | ||
| 4141 | instruction->return_type = return_type; | ||
| 4142 | instruction->is_var_args = is_var_args; | ||
| 4143 | |||
| 4144 | assert(source_node->type == NodeTypeFnProto); | ||
| 4145 | size_t param_count = source_node->data.fn_proto.params.length; | ||
| 4146 | if (is_var_args) param_count -= 1; | ||
| 4147 | for (size_t i = 0; i < param_count; i += 1) { | ||
| 4148 | if (param_types[i] != nullptr) ir_ref_instruction(param_types[i], irb->current_basic_block); | ||
| 4149 | } | ||
| 4150 | if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); | ||
| 4151 | if (callconv_value != nullptr) ir_ref_instruction(callconv_value, irb->current_basic_block); | ||
| 4152 | ir_ref_instruction(return_type, irb->current_basic_block); | ||
| 4153 | |||
| 4154 | return &instruction->base; | ||
| 4155 | } | ||
| 4156 | |||
| 4157 | static IrInstSrc *ir_build_test_comptime(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *value) { | ||
| 4158 | IrInstSrcTestComptime *instruction = ir_build_instruction<IrInstSrcTestComptime>(irb, scope, source_node); | ||
| 4159 | instruction->value = value; | ||
| 4160 | |||
| 4161 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 4162 | |||
| 4163 | return &instruction->base; | ||
| 4164 | } | ||
| 4165 | |||
| 4166 | static IrInstSrc *ir_build_ptr_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4167 | IrInstSrc *dest_type, IrInstSrc *ptr, bool safety_check_on) | ||
| 4168 | { | ||
| 4169 | IrInstSrcPtrCast *instruction = ir_build_instruction<IrInstSrcPtrCast>( | ||
| 4170 | irb, scope, source_node); | ||
| 4171 | instruction->dest_type = dest_type; | ||
| 4172 | instruction->ptr = ptr; | ||
| 4173 | instruction->safety_check_on = safety_check_on; | ||
| 4174 | |||
| 4175 | ir_ref_instruction(dest_type, irb->current_basic_block); | ||
| 4176 | ir_ref_instruction(ptr, irb->current_basic_block); | ||
| 4177 | |||
| 4178 | return &instruction->base; | ||
| 4179 | } | ||
| 4180 | |||
| 4181 | static IrInstGen *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInst *source_instruction, | ||
| 4182 | ZigType *ptr_type, IrInstGen *ptr, bool safety_check_on) | ||
| 4183 | { | ||
| 4184 | IrInstGenPtrCast *instruction = ir_build_inst_gen<IrInstGenPtrCast>( | ||
| 4185 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 4186 | instruction->base.value->type = ptr_type; | ||
| 4187 | instruction->ptr = ptr; | ||
| 4188 | instruction->safety_check_on = safety_check_on; | ||
| 4189 | |||
| 4190 | ir_ref_inst_gen(ptr); | ||
| 4191 | |||
| 4192 | return &instruction->base; | ||
| 4193 | } | ||
| 4194 | |||
| 4195 | static IrInstSrc *ir_build_implicit_cast(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4196 | IrInstSrc *operand, ResultLocCast *result_loc_cast) | ||
| 4197 | { | ||
| 4198 | IrInstSrcImplicitCast *instruction = ir_build_instruction<IrInstSrcImplicitCast>(irb, scope, source_node); | ||
| 4199 | instruction->operand = operand; | ||
| 4200 | instruction->result_loc_cast = result_loc_cast; | ||
| 4201 | |||
| 4202 | ir_ref_instruction(operand, irb->current_basic_block); | ||
| 4203 | |||
| 4204 | return &instruction->base; | ||
| 4205 | } | ||
| 4206 | |||
| 4207 | static IrInstSrc *ir_build_bit_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4208 | IrInstSrc *operand, ResultLocBitCast *result_loc_bit_cast) | ||
| 4209 | { | ||
| 4210 | IrInstSrcBitCast *instruction = ir_build_instruction<IrInstSrcBitCast>(irb, scope, source_node); | ||
| 4211 | instruction->operand = operand; | ||
| 4212 | instruction->result_loc_bit_cast = result_loc_bit_cast; | ||
| 4213 | |||
| 4214 | ir_ref_instruction(operand, irb->current_basic_block); | ||
| 4215 | |||
| 4216 | return &instruction->base; | ||
| 4217 | } | ||
| 4218 | |||
| 4219 | static IrInstGen *ir_build_bit_cast_gen(IrAnalyze *ira, IrInst *source_instruction, | ||
| 4220 | IrInstGen *operand, ZigType *ty) | ||
| 4221 | { | ||
| 4222 | IrInstGenBitCast *instruction = ir_build_inst_gen<IrInstGenBitCast>( | ||
| 4223 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 4224 | instruction->base.value->type = ty; | ||
| 4225 | instruction->operand = operand; | ||
| 4226 | |||
| 4227 | ir_ref_inst_gen(operand); | ||
| 4228 | |||
| 4229 | return &instruction->base; | ||
| 4230 | } | ||
| 4231 | |||
| 4232 | static IrInstGen *ir_build_widen_or_shorten(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, | ||
| 4233 | ZigType *result_type) | ||
| 4234 | { | ||
| 4235 | IrInstGenWidenOrShorten *inst = ir_build_inst_gen<IrInstGenWidenOrShorten>(&ira->new_irb, scope, source_node); | ||
| 4236 | inst->base.value->type = result_type; | ||
| 4237 | inst->target = target; | ||
| 4238 | |||
| 4239 | ir_ref_inst_gen(target); | ||
| 4240 | |||
| 4241 | return &inst->base; | ||
| 4242 | } | ||
| 4243 | |||
| 4244 | static IrInstSrc *ir_build_int_to_ptr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4245 | IrInstSrc *dest_type, IrInstSrc *target) | ||
| 4246 | { | ||
| 4247 | IrInstSrcIntToPtr *instruction = ir_build_instruction<IrInstSrcIntToPtr>(irb, scope, source_node); | ||
| 4248 | instruction->dest_type = dest_type; | ||
| 4249 | instruction->target = target; | ||
| 4250 | |||
| 4251 | ir_ref_instruction(dest_type, irb->current_basic_block); | ||
| 4252 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 4253 | |||
| 4254 | return &instruction->base; | ||
| 4255 | } | ||
| 4256 | |||
| 4257 | static IrInstGen *ir_build_int_to_ptr_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, | ||
| 4258 | IrInstGen *target, ZigType *ptr_type) | ||
| 4259 | { | ||
| 4260 | IrInstGenIntToPtr *instruction = ir_build_inst_gen<IrInstGenIntToPtr>(&ira->new_irb, scope, source_node); | ||
| 4261 | instruction->base.value->type = ptr_type; | ||
| 4262 | instruction->target = target; | ||
| 4263 | |||
| 4264 | ir_ref_inst_gen(target); | ||
| 4265 | |||
| 4266 | return &instruction->base; | ||
| 4267 | } | ||
| 4268 | |||
| 4269 | static IrInstSrc *ir_build_ptr_to_int_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4270 | IrInstSrc *target) | ||
| 4271 | { | ||
| 4272 | IrInstSrcPtrToInt *inst = ir_build_instruction<IrInstSrcPtrToInt>(irb, scope, source_node); | ||
| 4273 | inst->target = target; | ||
| 4274 | |||
| 4275 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 4276 | |||
| 4277 | return &inst->base; | ||
| 4278 | } | ||
| 4279 | |||
| 4280 | static IrInstGen *ir_build_ptr_to_int_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target) { | ||
| 4281 | IrInstGenPtrToInt *inst = ir_build_inst_gen<IrInstGenPtrToInt>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 4282 | inst->base.value->type = ira->codegen->builtin_types.entry_usize; | ||
| 4283 | inst->target = target; | ||
| 4284 | |||
| 4285 | ir_ref_inst_gen(target); | ||
| 4286 | |||
| 4287 | return &inst->base; | ||
| 4288 | } | ||
| 4289 | |||
| 4290 | static IrInstSrc *ir_build_int_to_enum_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4291 | IrInstSrc *dest_type, IrInstSrc *target) | ||
| 4292 | { | ||
| 4293 | IrInstSrcIntToEnum *instruction = ir_build_instruction<IrInstSrcIntToEnum>(irb, scope, source_node); | ||
| 4294 | instruction->dest_type = dest_type; | ||
| 4295 | instruction->target = target; | ||
| 4296 | |||
| 4297 | if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block); | ||
| 4298 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 4299 | |||
| 4300 | return &instruction->base; | ||
| 4301 | } | ||
| 4302 | |||
| 4303 | static IrInstGen *ir_build_int_to_enum_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, | ||
| 4304 | ZigType *dest_type, IrInstGen *target) | ||
| 4305 | { | ||
| 4306 | IrInstGenIntToEnum *instruction = ir_build_inst_gen<IrInstGenIntToEnum>(&ira->new_irb, scope, source_node); | ||
| 4307 | instruction->base.value->type = dest_type; | ||
| 4308 | instruction->target = target; | ||
| 4309 | |||
| 4310 | ir_ref_inst_gen(target); | ||
| 4311 | |||
| 4312 | return &instruction->base; | ||
| 4313 | } | ||
| 4314 | |||
| 4315 | static IrInstSrc *ir_build_enum_to_int(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4316 | IrInstSrc *target) | ||
| 4317 | { | ||
| 4318 | IrInstSrcEnumToInt *instruction = ir_build_instruction<IrInstSrcEnumToInt>( | ||
| 4319 | irb, scope, source_node); | ||
| 4320 | instruction->target = target; | ||
| 4321 | |||
| 4322 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 4323 | |||
| 4324 | return &instruction->base; | ||
| 4325 | } | ||
| 4326 | |||
| 4327 | static IrInstSrc *ir_build_int_to_err_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4328 | IrInstSrc *target) | ||
| 4329 | { | ||
| 4330 | IrInstSrcIntToErr *instruction = ir_build_instruction<IrInstSrcIntToErr>(irb, scope, source_node); | ||
| 4331 | instruction->target = target; | ||
| 4332 | |||
| 4333 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 4334 | |||
| 4335 | return &instruction->base; | ||
| 4336 | } | ||
| 4337 | |||
| 4338 | static IrInstGen *ir_build_int_to_err_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, | ||
| 4339 | ZigType *wanted_type) | ||
| 4340 | { | ||
| 4341 | IrInstGenIntToErr *instruction = ir_build_inst_gen<IrInstGenIntToErr>(&ira->new_irb, scope, source_node); | ||
| 4342 | instruction->base.value->type = wanted_type; | ||
| 4343 | instruction->target = target; | ||
| 4344 | |||
| 4345 | ir_ref_inst_gen(target); | ||
| 4346 | |||
| 4347 | return &instruction->base; | ||
| 4348 | } | ||
| 4349 | |||
| 4350 | static IrInstSrc *ir_build_err_to_int_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4351 | IrInstSrc *target) | ||
| 4352 | { | ||
| 4353 | IrInstSrcErrToInt *instruction = ir_build_instruction<IrInstSrcErrToInt>( | ||
| 4354 | irb, scope, source_node); | ||
| 4355 | instruction->target = target; | ||
| 4356 | |||
| 4357 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 4358 | |||
| 4359 | return &instruction->base; | ||
| 4360 | } | ||
| 4361 | |||
| 4362 | static IrInstGen *ir_build_err_to_int_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, | ||
| 4363 | ZigType *wanted_type) | ||
| 4364 | { | ||
| 4365 | IrInstGenErrToInt *instruction = ir_build_inst_gen<IrInstGenErrToInt>(&ira->new_irb, scope, source_node); | ||
| 4366 | instruction->base.value->type = wanted_type; | ||
| 4367 | instruction->target = target; | ||
| 4368 | |||
| 4369 | ir_ref_inst_gen(target); | ||
| 4370 | |||
| 4371 | return &instruction->base; | ||
| 4372 | } | ||
| 4373 | |||
| 4374 | static IrInstSrc *ir_build_check_switch_prongs(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4375 | IrInstSrc *target_value, IrInstSrcCheckSwitchProngsRange *ranges, size_t range_count, | ||
| 4376 | AstNode* else_prong, bool have_underscore_prong) | ||
| 4377 | { | ||
| 4378 | IrInstSrcCheckSwitchProngs *instruction = heap::c_allocator.create<IrInstSrcCheckSwitchProngs>(); | ||
| 4379 | instruction->base.id = have_underscore_prong ? | ||
| 4380 | IrInstSrcIdCheckSwitchProngsUnderYes : IrInstSrcIdCheckSwitchProngsUnderNo; | ||
| 4381 | instruction->base.base.scope = scope; | ||
| 4382 | instruction->base.base.source_node = source_node; | ||
| 4383 | instruction->base.base.debug_id = exec_next_debug_id(irb->exec); | ||
| 4384 | instruction->base.owner_bb = irb->current_basic_block; | ||
| 4385 | ir_instruction_append(irb->current_basic_block, &instruction->base); | ||
| 4386 | |||
| 4387 | instruction->target_value = target_value; | ||
| 4388 | instruction->ranges = ranges; | ||
| 4389 | instruction->range_count = range_count; | ||
| 4390 | instruction->else_prong = else_prong; | ||
| 4391 | |||
| 4392 | ir_ref_instruction(target_value, irb->current_basic_block); | ||
| 4393 | for (size_t i = 0; i < range_count; i += 1) { | ||
| 4394 | ir_ref_instruction(ranges[i].start, irb->current_basic_block); | ||
| 4395 | ir_ref_instruction(ranges[i].end, irb->current_basic_block); | ||
| 4396 | } | ||
| 4397 | |||
| 4398 | return &instruction->base; | ||
| 4399 | } | ||
| 4400 | |||
| 4401 | static IrInstSrc *ir_build_check_statement_is_void(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4402 | IrInstSrc* statement_value) | ||
| 4403 | { | ||
| 4404 | IrInstSrcCheckStatementIsVoid *instruction = ir_build_instruction<IrInstSrcCheckStatementIsVoid>( | ||
| 4405 | irb, scope, source_node); | ||
| 4406 | instruction->statement_value = statement_value; | ||
| 4407 | |||
| 4408 | ir_ref_instruction(statement_value, irb->current_basic_block); | ||
| 4409 | |||
| 4410 | return &instruction->base; | ||
| 4411 | } | ||
| 4412 | |||
| 4413 | static IrInstSrc *ir_build_type_name(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4414 | IrInstSrc *type_value) | ||
| 4415 | { | ||
| 4416 | IrInstSrcTypeName *instruction = ir_build_instruction<IrInstSrcTypeName>(irb, scope, source_node); | ||
| 4417 | instruction->type_value = type_value; | ||
| 4418 | |||
| 4419 | ir_ref_instruction(type_value, irb->current_basic_block); | ||
| 4420 | |||
| 4421 | return &instruction->base; | ||
| 4422 | } | ||
| 4423 | |||
| 4424 | static IrInstSrc *ir_build_decl_ref(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Tld *tld, LVal lval) { | ||
| 4425 | IrInstSrcDeclRef *instruction = ir_build_instruction<IrInstSrcDeclRef>(irb, scope, source_node); | ||
| 4426 | instruction->tld = tld; | ||
| 4427 | instruction->lval = lval; | ||
| 4428 | |||
| 4429 | return &instruction->base; | ||
| 4430 | } | ||
| 4431 | |||
| 4432 | static IrInstSrc *ir_build_panic_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *msg) { | ||
| 4433 | IrInstSrcPanic *instruction = ir_build_instruction<IrInstSrcPanic>(irb, scope, source_node); | ||
| 4434 | instruction->base.is_noreturn = true; | ||
| 4435 | instruction->msg = msg; | ||
| 4436 | |||
| 4437 | ir_ref_instruction(msg, irb->current_basic_block); | ||
| 4438 | |||
| 4439 | return &instruction->base; | ||
| 4440 | } | ||
| 4441 | |||
| 4442 | static IrInstGen *ir_build_panic_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *msg) { | ||
| 4443 | IrInstGenPanic *instruction = ir_build_inst_noreturn<IrInstGenPanic>(&ira->new_irb, | ||
| 4444 | source_instr->scope, source_instr->source_node); | ||
| 4445 | instruction->msg = msg; | ||
| 4446 | |||
| 4447 | ir_ref_inst_gen(msg); | ||
| 4448 | |||
| 4449 | return &instruction->base; | ||
| 4450 | } | ||
| 4451 | |||
| 4452 | static IrInstSrc *ir_build_tag_name_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target) { | ||
| 4453 | IrInstSrcTagName *instruction = ir_build_instruction<IrInstSrcTagName>(irb, scope, source_node); | ||
| 4454 | instruction->target = target; | ||
| 4455 | |||
| 4456 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 4457 | |||
| 4458 | return &instruction->base; | ||
| 4459 | } | ||
| 4460 | |||
| 4461 | static IrInstGen *ir_build_tag_name_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target, | ||
| 4462 | ZigType *result_type) | ||
| 4463 | { | ||
| 4464 | IrInstGenTagName *instruction = ir_build_inst_gen<IrInstGenTagName>(&ira->new_irb, | ||
| 4465 | source_instr->scope, source_instr->source_node); | ||
| 4466 | instruction->base.value->type = result_type; | ||
| 4467 | instruction->target = target; | ||
| 4468 | |||
| 4469 | ir_ref_inst_gen(target); | ||
| 4470 | |||
| 4471 | return &instruction->base; | ||
| 4472 | } | ||
| 4473 | |||
| 4474 | static IrInstSrc *ir_build_field_parent_ptr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4475 | IrInstSrc *type_value, IrInstSrc *field_name, IrInstSrc *field_ptr) | ||
| 4476 | { | ||
| 4477 | IrInstSrcFieldParentPtr *inst = ir_build_instruction<IrInstSrcFieldParentPtr>( | ||
| 4478 | irb, scope, source_node); | ||
| 4479 | inst->type_value = type_value; | ||
| 4480 | inst->field_name = field_name; | ||
| 4481 | inst->field_ptr = field_ptr; | ||
| 4482 | |||
| 4483 | ir_ref_instruction(type_value, irb->current_basic_block); | ||
| 4484 | ir_ref_instruction(field_name, irb->current_basic_block); | ||
| 4485 | ir_ref_instruction(field_ptr, irb->current_basic_block); | ||
| 4486 | |||
| 4487 | return &inst->base; | ||
| 4488 | } | ||
| 4489 | |||
| 4490 | static IrInstGen *ir_build_field_parent_ptr_gen(IrAnalyze *ira, IrInst *source_instr, | ||
| 4491 | IrInstGen *field_ptr, TypeStructField *field, ZigType *result_type) | ||
| 4492 | { | ||
| 4493 | IrInstGenFieldParentPtr *inst = ir_build_inst_gen<IrInstGenFieldParentPtr>(&ira->new_irb, | ||
| 4494 | source_instr->scope, source_instr->source_node); | ||
| 4495 | inst->base.value->type = result_type; | ||
| 4496 | inst->field_ptr = field_ptr; | ||
| 4497 | inst->field = field; | ||
| 4498 | |||
| 4499 | ir_ref_inst_gen(field_ptr); | ||
| 4500 | |||
| 4501 | return &inst->base; | ||
| 4502 | } | ||
| 4503 | |||
| 4504 | static IrInstSrc *ir_build_byte_offset_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4505 | IrInstSrc *type_value, IrInstSrc *field_name) | ||
| 4506 | { | ||
| 4507 | IrInstSrcByteOffsetOf *instruction = ir_build_instruction<IrInstSrcByteOffsetOf>(irb, scope, source_node); | ||
| 4508 | instruction->type_value = type_value; | ||
| 4509 | instruction->field_name = field_name; | ||
| 4510 | |||
| 4511 | ir_ref_instruction(type_value, irb->current_basic_block); | ||
| 4512 | ir_ref_instruction(field_name, irb->current_basic_block); | ||
| 4513 | |||
| 4514 | return &instruction->base; | ||
| 4515 | } | ||
| 4516 | |||
| 4517 | static IrInstSrc *ir_build_bit_offset_of(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4518 | IrInstSrc *type_value, IrInstSrc *field_name) | ||
| 4519 | { | ||
| 4520 | IrInstSrcBitOffsetOf *instruction = ir_build_instruction<IrInstSrcBitOffsetOf>(irb, scope, source_node); | ||
| 4521 | instruction->type_value = type_value; | ||
| 4522 | instruction->field_name = field_name; | ||
| 4523 | |||
| 4524 | ir_ref_instruction(type_value, irb->current_basic_block); | ||
| 4525 | ir_ref_instruction(field_name, irb->current_basic_block); | ||
| 4526 | |||
| 4527 | return &instruction->base; | ||
| 4528 | } | ||
| 4529 | |||
| 4530 | static IrInstSrc *ir_build_type_info(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value) { | ||
| 4531 | IrInstSrcTypeInfo *instruction = ir_build_instruction<IrInstSrcTypeInfo>(irb, scope, source_node); | ||
| 4532 | instruction->type_value = type_value; | ||
| 4533 | |||
| 4534 | ir_ref_instruction(type_value, irb->current_basic_block); | ||
| 4535 | |||
| 4536 | return &instruction->base; | ||
| 4537 | } | ||
| 4538 | |||
| 4539 | static IrInstSrc *ir_build_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_info) { | ||
| 4540 | IrInstSrcType *instruction = ir_build_instruction<IrInstSrcType>(irb, scope, source_node); | ||
| 4541 | instruction->type_info = type_info; | ||
| 4542 | |||
| 4543 | ir_ref_instruction(type_info, irb->current_basic_block); | ||
| 4544 | |||
| 4545 | return &instruction->base; | ||
| 4546 | } | ||
| 4547 | |||
| 4548 | static IrInstSrc *ir_build_set_eval_branch_quota(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4549 | IrInstSrc *new_quota) | ||
| 4550 | { | ||
| 4551 | IrInstSrcSetEvalBranchQuota *instruction = ir_build_instruction<IrInstSrcSetEvalBranchQuota>(irb, scope, source_node); | ||
| 4552 | instruction->new_quota = new_quota; | ||
| 4553 | |||
| 4554 | ir_ref_instruction(new_quota, irb->current_basic_block); | ||
| 4555 | |||
| 4556 | return &instruction->base; | ||
| 4557 | } | ||
| 4558 | |||
| 4559 | static IrInstSrc *ir_build_align_cast_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4560 | IrInstSrc *align_bytes, IrInstSrc *target) | ||
| 4561 | { | ||
| 4562 | IrInstSrcAlignCast *instruction = ir_build_instruction<IrInstSrcAlignCast>(irb, scope, source_node); | ||
| 4563 | instruction->align_bytes = align_bytes; | ||
| 4564 | instruction->target = target; | ||
| 4565 | |||
| 4566 | ir_ref_instruction(align_bytes, irb->current_basic_block); | ||
| 4567 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 4568 | |||
| 4569 | return &instruction->base; | ||
| 4570 | } | ||
| 4571 | |||
| 4572 | static IrInstGen *ir_build_align_cast_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, IrInstGen *target, | ||
| 4573 | ZigType *result_type) | ||
| 4574 | { | ||
| 4575 | IrInstGenAlignCast *instruction = ir_build_inst_gen<IrInstGenAlignCast>(&ira->new_irb, scope, source_node); | ||
| 4576 | instruction->base.value->type = result_type; | ||
| 4577 | instruction->target = target; | ||
| 4578 | |||
| 4579 | ir_ref_inst_gen(target); | ||
| 4580 | |||
| 4581 | return &instruction->base; | ||
| 4582 | } | ||
| 4583 | |||
| 4584 | static IrInstSrc *ir_build_resolve_result(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4585 | ResultLoc *result_loc, IrInstSrc *ty) | ||
| 4586 | { | ||
| 4587 | IrInstSrcResolveResult *instruction = ir_build_instruction<IrInstSrcResolveResult>(irb, scope, source_node); | ||
| 4588 | instruction->result_loc = result_loc; | ||
| 4589 | instruction->ty = ty; | ||
| 4590 | |||
| 4591 | if (ty != nullptr) ir_ref_instruction(ty, irb->current_basic_block); | ||
| 4592 | |||
| 4593 | return &instruction->base; | ||
| 4594 | } | ||
| 4595 | |||
| 4596 | static IrInstSrc *ir_build_reset_result(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4597 | ResultLoc *result_loc) | ||
| 4598 | { | ||
| 4599 | IrInstSrcResetResult *instruction = ir_build_instruction<IrInstSrcResetResult>(irb, scope, source_node); | ||
| 4600 | instruction->result_loc = result_loc; | ||
| 4601 | instruction->base.is_gen = true; | ||
| 4602 | |||
| 4603 | return &instruction->base; | ||
| 4604 | } | ||
| 4605 | |||
| 4606 | static IrInstSrc *ir_build_set_align_stack(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4607 | IrInstSrc *align_bytes) | ||
| 4608 | { | ||
| 4609 | IrInstSrcSetAlignStack *instruction = ir_build_instruction<IrInstSrcSetAlignStack>(irb, scope, source_node); | ||
| 4610 | instruction->align_bytes = align_bytes; | ||
| 4611 | |||
| 4612 | ir_ref_instruction(align_bytes, irb->current_basic_block); | ||
| 4613 | |||
| 4614 | return &instruction->base; | ||
| 4615 | } | ||
| 4616 | |||
| 4617 | static IrInstSrc *ir_build_arg_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4618 | IrInstSrc *fn_type, IrInstSrc *arg_index, bool allow_var) | ||
| 4619 | { | ||
| 4620 | IrInstSrcArgType *instruction = heap::c_allocator.create<IrInstSrcArgType>(); | ||
| 4621 | instruction->base.id = allow_var ? | ||
| 4622 | IrInstSrcIdArgTypeAllowVarTrue : IrInstSrcIdArgTypeAllowVarFalse; | ||
| 4623 | instruction->base.base.scope = scope; | ||
| 4624 | instruction->base.base.source_node = source_node; | ||
| 4625 | instruction->base.base.debug_id = exec_next_debug_id(irb->exec); | ||
| 4626 | instruction->base.owner_bb = irb->current_basic_block; | ||
| 4627 | ir_instruction_append(irb->current_basic_block, &instruction->base); | ||
| 4628 | |||
| 4629 | instruction->fn_type = fn_type; | ||
| 4630 | instruction->arg_index = arg_index; | ||
| 4631 | |||
| 4632 | ir_ref_instruction(fn_type, irb->current_basic_block); | ||
| 4633 | ir_ref_instruction(arg_index, irb->current_basic_block); | ||
| 4634 | |||
| 4635 | return &instruction->base; | ||
| 4636 | } | ||
| 4637 | |||
| 4638 | static IrInstSrc *ir_build_error_return_trace_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4639 | IrInstErrorReturnTraceOptional optional) | ||
| 4640 | { | ||
| 4641 | IrInstSrcErrorReturnTrace *inst = ir_build_instruction<IrInstSrcErrorReturnTrace>(irb, scope, source_node); | ||
| 4642 | inst->optional = optional; | ||
| 4643 | |||
| 4644 | return &inst->base; | ||
| 4645 | } | ||
| 4646 | |||
| 4647 | static IrInstGen *ir_build_error_return_trace_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, | ||
| 4648 | IrInstErrorReturnTraceOptional optional, ZigType *result_type) | ||
| 4649 | { | ||
| 4650 | IrInstGenErrorReturnTrace *inst = ir_build_inst_gen<IrInstGenErrorReturnTrace>(&ira->new_irb, scope, source_node); | ||
| 4651 | inst->base.value->type = result_type; | ||
| 4652 | inst->optional = optional; | ||
| 4653 | |||
| 4654 | return &inst->base; | ||
| 4655 | } | ||
| 4656 | |||
| 4657 | static IrInstSrc *ir_build_error_union(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4658 | IrInstSrc *err_set, IrInstSrc *payload) | ||
| 4659 | { | ||
| 4660 | IrInstSrcErrorUnion *instruction = ir_build_instruction<IrInstSrcErrorUnion>(irb, scope, source_node); | ||
| 4661 | instruction->err_set = err_set; | ||
| 4662 | instruction->payload = payload; | ||
| 4663 | |||
| 4664 | ir_ref_instruction(err_set, irb->current_basic_block); | ||
| 4665 | ir_ref_instruction(payload, irb->current_basic_block); | ||
| 4666 | |||
| 4667 | return &instruction->base; | ||
| 4668 | } | ||
| 4669 | |||
| 4670 | static IrInstSrc *ir_build_atomic_rmw_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4671 | IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *op, IrInstSrc *operand, | ||
| 4672 | IrInstSrc *ordering) | ||
| 4673 | { | ||
| 4674 | IrInstSrcAtomicRmw *instruction = ir_build_instruction<IrInstSrcAtomicRmw>(irb, scope, source_node); | ||
| 4675 | instruction->operand_type = operand_type; | ||
| 4676 | instruction->ptr = ptr; | ||
| 4677 | instruction->op = op; | ||
| 4678 | instruction->operand = operand; | ||
| 4679 | instruction->ordering = ordering; | ||
| 4680 | |||
| 4681 | ir_ref_instruction(operand_type, irb->current_basic_block); | ||
| 4682 | ir_ref_instruction(ptr, irb->current_basic_block); | ||
| 4683 | ir_ref_instruction(op, irb->current_basic_block); | ||
| 4684 | ir_ref_instruction(operand, irb->current_basic_block); | ||
| 4685 | ir_ref_instruction(ordering, irb->current_basic_block); | ||
| 4686 | |||
| 4687 | return &instruction->base; | ||
| 4688 | } | ||
| 4689 | |||
| 4690 | static IrInstGen *ir_build_atomic_rmw_gen(IrAnalyze *ira, IrInst *source_instr, | ||
| 4691 | IrInstGen *ptr, IrInstGen *operand, AtomicRmwOp op, AtomicOrder ordering, ZigType *operand_type) | ||
| 4692 | { | ||
| 4693 | IrInstGenAtomicRmw *instruction = ir_build_inst_gen<IrInstGenAtomicRmw>(&ira->new_irb, source_instr->scope, source_instr->source_node); | ||
| 4694 | instruction->base.value->type = operand_type; | ||
| 4695 | instruction->ptr = ptr; | ||
| 4696 | instruction->op = op; | ||
| 4697 | instruction->operand = operand; | ||
| 4698 | instruction->ordering = ordering; | ||
| 4699 | |||
| 4700 | ir_ref_inst_gen(ptr); | ||
| 4701 | ir_ref_inst_gen(operand); | ||
| 4702 | |||
| 4703 | return &instruction->base; | ||
| 4704 | } | ||
| 4705 | |||
| 4706 | static IrInstSrc *ir_build_atomic_load_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4707 | IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *ordering) | ||
| 4708 | { | ||
| 4709 | IrInstSrcAtomicLoad *instruction = ir_build_instruction<IrInstSrcAtomicLoad>(irb, scope, source_node); | ||
| 4710 | instruction->operand_type = operand_type; | ||
| 4711 | instruction->ptr = ptr; | ||
| 4712 | instruction->ordering = ordering; | ||
| 4713 | |||
| 4714 | ir_ref_instruction(operand_type, irb->current_basic_block); | ||
| 4715 | ir_ref_instruction(ptr, irb->current_basic_block); | ||
| 4716 | ir_ref_instruction(ordering, irb->current_basic_block); | ||
| 4717 | |||
| 4718 | return &instruction->base; | ||
| 4719 | } | ||
| 4720 | |||
| 4721 | static IrInstGen *ir_build_atomic_load_gen(IrAnalyze *ira, IrInst *source_instr, | ||
| 4722 | IrInstGen *ptr, AtomicOrder ordering, ZigType *operand_type) | ||
| 4723 | { | ||
| 4724 | IrInstGenAtomicLoad *instruction = ir_build_inst_gen<IrInstGenAtomicLoad>(&ira->new_irb, | ||
| 4725 | source_instr->scope, source_instr->source_node); | ||
| 4726 | instruction->base.value->type = operand_type; | ||
| 4727 | instruction->ptr = ptr; | ||
| 4728 | instruction->ordering = ordering; | ||
| 4729 | |||
| 4730 | ir_ref_inst_gen(ptr); | ||
| 4731 | |||
| 4732 | return &instruction->base; | ||
| 4733 | } | ||
| 4734 | |||
| 4735 | static IrInstSrc *ir_build_atomic_store_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4736 | IrInstSrc *operand_type, IrInstSrc *ptr, IrInstSrc *value, IrInstSrc *ordering) | ||
| 4737 | { | ||
| 4738 | IrInstSrcAtomicStore *instruction = ir_build_instruction<IrInstSrcAtomicStore>(irb, scope, source_node); | ||
| 4739 | instruction->operand_type = operand_type; | ||
| 4740 | instruction->ptr = ptr; | ||
| 4741 | instruction->value = value; | ||
| 4742 | instruction->ordering = ordering; | ||
| 4743 | |||
| 4744 | ir_ref_instruction(operand_type, irb->current_basic_block); | ||
| 4745 | ir_ref_instruction(ptr, irb->current_basic_block); | ||
| 4746 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 4747 | ir_ref_instruction(ordering, irb->current_basic_block); | ||
| 4748 | |||
| 4749 | return &instruction->base; | ||
| 4750 | } | ||
| 4751 | |||
| 4752 | static IrInstGen *ir_build_atomic_store_gen(IrAnalyze *ira, IrInst *source_instr, | ||
| 4753 | IrInstGen *ptr, IrInstGen *value, AtomicOrder ordering) | ||
| 4754 | { | ||
| 4755 | IrInstGenAtomicStore *instruction = ir_build_inst_void<IrInstGenAtomicStore>(&ira->new_irb, | ||
| 4756 | source_instr->scope, source_instr->source_node); | ||
| 4757 | instruction->ptr = ptr; | ||
| 4758 | instruction->value = value; | ||
| 4759 | instruction->ordering = ordering; | ||
| 4760 | |||
| 4761 | ir_ref_inst_gen(ptr); | ||
| 4762 | ir_ref_inst_gen(value); | ||
| 4763 | |||
| 4764 | return &instruction->base; | ||
| 4765 | } | ||
| 4766 | |||
| 4767 | static IrInstSrc *ir_build_save_err_ret_addr_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | ||
| 4768 | IrInstSrcSaveErrRetAddr *inst = ir_build_instruction<IrInstSrcSaveErrRetAddr>(irb, scope, source_node); | ||
| 4769 | return &inst->base; | ||
| 4770 | } | ||
| 4771 | |||
| 4772 | static IrInstGen *ir_build_save_err_ret_addr_gen(IrAnalyze *ira, IrInst *source_instr) { | ||
| 4773 | IrInstGenSaveErrRetAddr *inst = ir_build_inst_void<IrInstGenSaveErrRetAddr>(&ira->new_irb, | ||
| 4774 | source_instr->scope, source_instr->source_node); | ||
| 4775 | return &inst->base; | ||
| 4776 | } | ||
| 4777 | |||
| 4778 | static IrInstSrc *ir_build_add_implicit_return_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4779 | IrInstSrc *value, ResultLocReturn *result_loc_ret) | ||
| 4780 | { | ||
| 4781 | IrInstSrcAddImplicitReturnType *inst = ir_build_instruction<IrInstSrcAddImplicitReturnType>(irb, scope, source_node); | ||
| 4782 | inst->value = value; | ||
| 4783 | inst->result_loc_ret = result_loc_ret; | ||
| 4784 | |||
| 4785 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 4786 | |||
| 4787 | return &inst->base; | ||
| 4788 | } | ||
| 4789 | |||
| 4790 | static IrInstSrc *ir_build_has_decl(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4791 | IrInstSrc *container, IrInstSrc *name) | ||
| 4792 | { | ||
| 4793 | IrInstSrcHasDecl *instruction = ir_build_instruction<IrInstSrcHasDecl>(irb, scope, source_node); | ||
| 4794 | instruction->container = container; | ||
| 4795 | instruction->name = name; | ||
| 4796 | |||
| 4797 | ir_ref_instruction(container, irb->current_basic_block); | ||
| 4798 | ir_ref_instruction(name, irb->current_basic_block); | ||
| 4799 | |||
| 4800 | return &instruction->base; | ||
| 4801 | } | ||
| 4802 | |||
| 4803 | static IrInstSrc *ir_build_undeclared_identifier(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, Buf *name) { | ||
| 4804 | IrInstSrcUndeclaredIdent *instruction = ir_build_instruction<IrInstSrcUndeclaredIdent>(irb, scope, source_node); | ||
| 4805 | instruction->name = name; | ||
| 4806 | |||
| 4807 | return &instruction->base; | ||
| 4808 | } | ||
| 4809 | |||
| 4810 | static IrInstSrc *ir_build_check_runtime_scope(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *scope_is_comptime, IrInstSrc *is_comptime) { | ||
| 4811 | IrInstSrcCheckRuntimeScope *instruction = ir_build_instruction<IrInstSrcCheckRuntimeScope>(irb, scope, source_node); | ||
| 4812 | instruction->scope_is_comptime = scope_is_comptime; | ||
| 4813 | instruction->is_comptime = is_comptime; | ||
| 4814 | |||
| 4815 | ir_ref_instruction(scope_is_comptime, irb->current_basic_block); | ||
| 4816 | ir_ref_instruction(is_comptime, irb->current_basic_block); | ||
| 4817 | |||
| 4818 | return &instruction->base; | ||
| 4819 | } | ||
| 4820 | |||
| 4821 | static IrInstSrc *ir_build_union_init_named_field(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4822 | IrInstSrc *union_type, IrInstSrc *field_name, IrInstSrc *field_result_loc, IrInstSrc *result_loc) | ||
| 4823 | { | ||
| 4824 | IrInstSrcUnionInitNamedField *instruction = ir_build_instruction<IrInstSrcUnionInitNamedField>(irb, scope, source_node); | ||
| 4825 | instruction->union_type = union_type; | ||
| 4826 | instruction->field_name = field_name; | ||
| 4827 | instruction->field_result_loc = field_result_loc; | ||
| 4828 | instruction->result_loc = result_loc; | ||
| 4829 | |||
| 4830 | ir_ref_instruction(union_type, irb->current_basic_block); | ||
| 4831 | ir_ref_instruction(field_name, irb->current_basic_block); | ||
| 4832 | ir_ref_instruction(field_result_loc, irb->current_basic_block); | ||
| 4833 | if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block); | ||
| 4834 | |||
| 4835 | return &instruction->base; | ||
| 4836 | } | ||
| 4837 | |||
| 4838 | |||
| 4839 | static IrInstGen *ir_build_vector_to_array(IrAnalyze *ira, IrInst *source_instruction, | ||
| 4840 | ZigType *result_type, IrInstGen *vector, IrInstGen *result_loc) | ||
| 4841 | { | ||
| 4842 | IrInstGenVectorToArray *instruction = ir_build_inst_gen<IrInstGenVectorToArray>(&ira->new_irb, | ||
| 4843 | source_instruction->scope, source_instruction->source_node); | ||
| 4844 | instruction->base.value->type = result_type; | ||
| 4845 | instruction->vector = vector; | ||
| 4846 | instruction->result_loc = result_loc; | ||
| 4847 | |||
| 4848 | ir_ref_inst_gen(vector); | ||
| 4849 | ir_ref_inst_gen(result_loc); | ||
| 4850 | |||
| 4851 | return &instruction->base; | ||
| 4852 | } | ||
| 4853 | |||
| 4854 | static IrInstGen *ir_build_ptr_of_array_to_slice(IrAnalyze *ira, IrInst *source_instruction, | ||
| 4855 | ZigType *result_type, IrInstGen *operand, IrInstGen *result_loc) | ||
| 4856 | { | ||
| 4857 | IrInstGenPtrOfArrayToSlice *instruction = ir_build_inst_gen<IrInstGenPtrOfArrayToSlice>(&ira->new_irb, | ||
| 4858 | source_instruction->scope, source_instruction->source_node); | ||
| 4859 | instruction->base.value->type = result_type; | ||
| 4860 | instruction->operand = operand; | ||
| 4861 | instruction->result_loc = result_loc; | ||
| 4862 | |||
| 4863 | ir_ref_inst_gen(operand); | ||
| 4864 | ir_ref_inst_gen(result_loc); | ||
| 4865 | |||
| 4866 | return &instruction->base; | ||
| 4867 | } | ||
| 4868 | |||
| 4869 | static IrInstGen *ir_build_array_to_vector(IrAnalyze *ira, IrInst *source_instruction, | ||
| 4870 | IrInstGen *array, ZigType *result_type) | ||
| 4871 | { | ||
| 4872 | IrInstGenArrayToVector *instruction = ir_build_inst_gen<IrInstGenArrayToVector>(&ira->new_irb, | ||
| 4873 | source_instruction->scope, source_instruction->source_node); | ||
| 4874 | instruction->base.value->type = result_type; | ||
| 4875 | instruction->array = array; | ||
| 4876 | |||
| 4877 | ir_ref_inst_gen(array); | ||
| 4878 | |||
| 4879 | return &instruction->base; | ||
| 4880 | } | ||
| 4881 | |||
| 4882 | static IrInstGen *ir_build_assert_zero(IrAnalyze *ira, IrInst *source_instruction, | ||
| 4883 | IrInstGen *target) | ||
| 4884 | { | ||
| 4885 | IrInstGenAssertZero *instruction = ir_build_inst_gen<IrInstGenAssertZero>(&ira->new_irb, | ||
| 4886 | source_instruction->scope, source_instruction->source_node); | ||
| 4887 | instruction->base.value->type = ira->codegen->builtin_types.entry_void; | ||
| 4888 | instruction->target = target; | ||
| 4889 | |||
| 4890 | ir_ref_inst_gen(target); | ||
| 4891 | |||
| 4892 | return &instruction->base; | ||
| 4893 | } | ||
| 4894 | |||
| 4895 | static IrInstGen *ir_build_assert_non_null(IrAnalyze *ira, IrInst *source_instruction, | ||
| 4896 | IrInstGen *target) | ||
| 4897 | { | ||
| 4898 | IrInstGenAssertNonNull *instruction = ir_build_inst_gen<IrInstGenAssertNonNull>(&ira->new_irb, | ||
| 4899 | source_instruction->scope, source_instruction->source_node); | ||
| 4900 | instruction->base.value->type = ira->codegen->builtin_types.entry_void; | ||
| 4901 | instruction->target = target; | ||
| 4902 | |||
| 4903 | ir_ref_inst_gen(target); | ||
| 4904 | |||
| 4905 | return &instruction->base; | ||
| 4906 | } | ||
| 4907 | |||
| 4908 | static IrInstSrc *ir_build_alloca_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4909 | IrInstSrc *align, const char *name_hint, IrInstSrc *is_comptime) | ||
| 4910 | { | ||
| 4911 | IrInstSrcAlloca *instruction = ir_build_instruction<IrInstSrcAlloca>(irb, scope, source_node); | ||
| 4912 | instruction->base.is_gen = true; | ||
| 4913 | instruction->align = align; | ||
| 4914 | instruction->name_hint = name_hint; | ||
| 4915 | instruction->is_comptime = is_comptime; | ||
| 4916 | |||
| 4917 | if (align != nullptr) ir_ref_instruction(align, irb->current_basic_block); | ||
| 4918 | if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block); | ||
| 4919 | |||
| 4920 | return &instruction->base; | ||
| 4921 | } | ||
| 4922 | |||
| 4923 | static IrInstGenAlloca *ir_build_alloca_gen(IrAnalyze *ira, IrInst *source_instruction, | ||
| 4924 | uint32_t align, const char *name_hint) | ||
| 4925 | { | ||
| 4926 | IrInstGenAlloca *instruction = ir_create_inst_gen<IrInstGenAlloca>(&ira->new_irb, | ||
| 4927 | source_instruction->scope, source_instruction->source_node); | ||
| 4928 | instruction->align = align; | ||
| 4929 | instruction->name_hint = name_hint; | ||
| 4930 | |||
| 4931 | return instruction; | ||
| 4932 | } | ||
| 4933 | |||
| 4934 | static IrInstSrc *ir_build_end_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4935 | IrInstSrc *value, ResultLoc *result_loc) | ||
| 4936 | { | ||
| 4937 | IrInstSrcEndExpr *instruction = ir_build_instruction<IrInstSrcEndExpr>(irb, scope, source_node); | ||
| 4938 | instruction->base.is_gen = true; | ||
| 4939 | instruction->value = value; | ||
| 4940 | instruction->result_loc = result_loc; | ||
| 4941 | |||
| 4942 | ir_ref_instruction(value, irb->current_basic_block); | ||
| 4943 | |||
| 4944 | return &instruction->base; | ||
| 4945 | } | ||
| 4946 | |||
| 4947 | static IrInstSrcSuspendBegin *ir_build_suspend_begin_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | ||
| 4948 | return ir_build_instruction<IrInstSrcSuspendBegin>(irb, scope, source_node); | ||
| 4949 | } | ||
| 4950 | |||
| 4951 | static IrInstGen *ir_build_suspend_begin_gen(IrAnalyze *ira, IrInst *source_instr) { | ||
| 4952 | IrInstGenSuspendBegin *inst = ir_build_inst_void<IrInstGenSuspendBegin>(&ira->new_irb, | ||
| 4953 | source_instr->scope, source_instr->source_node); | ||
| 4954 | return &inst->base; | ||
| 4955 | } | ||
| 4956 | |||
| 4957 | static IrInstSrc *ir_build_suspend_finish_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4958 | IrInstSrcSuspendBegin *begin) | ||
| 4959 | { | ||
| 4960 | IrInstSrcSuspendFinish *inst = ir_build_instruction<IrInstSrcSuspendFinish>(irb, scope, source_node); | ||
| 4961 | inst->begin = begin; | ||
| 4962 | |||
| 4963 | ir_ref_instruction(&begin->base, irb->current_basic_block); | ||
| 4964 | |||
| 4965 | return &inst->base; | ||
| 4966 | } | ||
| 4967 | |||
| 4968 | static IrInstGen *ir_build_suspend_finish_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGenSuspendBegin *begin) { | ||
| 4969 | IrInstGenSuspendFinish *inst = ir_build_inst_void<IrInstGenSuspendFinish>(&ira->new_irb, | ||
| 4970 | source_instr->scope, source_instr->source_node); | ||
| 4971 | inst->begin = begin; | ||
| 4972 | |||
| 4973 | ir_ref_inst_gen(&begin->base); | ||
| 4974 | |||
| 4975 | return &inst->base; | ||
| 4976 | } | ||
| 4977 | |||
| 4978 | static IrInstSrc *ir_build_await_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 4979 | IrInstSrc *frame, ResultLoc *result_loc, bool is_nosuspend) | ||
| 4980 | { | ||
| 4981 | IrInstSrcAwait *instruction = ir_build_instruction<IrInstSrcAwait>(irb, scope, source_node); | ||
| 4982 | instruction->frame = frame; | ||
| 4983 | instruction->result_loc = result_loc; | ||
| 4984 | instruction->is_nosuspend = is_nosuspend; | ||
| 4985 | |||
| 4986 | ir_ref_instruction(frame, irb->current_basic_block); | ||
| 4987 | |||
| 4988 | return &instruction->base; | ||
| 4989 | } | ||
| 4990 | |||
| 4991 | static IrInstGenAwait *ir_build_await_gen(IrAnalyze *ira, IrInst *source_instruction, | ||
| 4992 | IrInstGen *frame, ZigType *result_type, IrInstGen *result_loc, bool is_nosuspend) | ||
| 4993 | { | ||
| 4994 | IrInstGenAwait *instruction = ir_build_inst_gen<IrInstGenAwait>(&ira->new_irb, | ||
| 4995 | source_instruction->scope, source_instruction->source_node); | ||
| 4996 | instruction->base.value->type = result_type; | ||
| 4997 | instruction->frame = frame; | ||
| 4998 | instruction->result_loc = result_loc; | ||
| 4999 | instruction->is_nosuspend = is_nosuspend; | ||
| 5000 | |||
| 5001 | ir_ref_inst_gen(frame); | ||
| 5002 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); | ||
| 5003 | |||
| 5004 | return instruction; | ||
| 5005 | } | ||
| 5006 | |||
| 5007 | static IrInstSrc *ir_build_resume_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *frame) { | ||
| 5008 | IrInstSrcResume *instruction = ir_build_instruction<IrInstSrcResume>(irb, scope, source_node); | ||
| 5009 | instruction->frame = frame; | ||
| 5010 | |||
| 5011 | ir_ref_instruction(frame, irb->current_basic_block); | ||
| 5012 | |||
| 5013 | return &instruction->base; | ||
| 5014 | } | ||
| 5015 | |||
| 5016 | static IrInstGen *ir_build_resume_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *frame) { | ||
| 5017 | IrInstGenResume *instruction = ir_build_inst_void<IrInstGenResume>(&ira->new_irb, | ||
| 5018 | source_instr->scope, source_instr->source_node); | ||
| 5019 | instruction->frame = frame; | ||
| 5020 | |||
| 5021 | ir_ref_inst_gen(frame); | ||
| 5022 | |||
| 5023 | return &instruction->base; | ||
| 5024 | } | ||
| 5025 | |||
| 5026 | static IrInstSrcSpillBegin *ir_build_spill_begin_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 5027 | IrInstSrc *operand, SpillId spill_id) | ||
| 5028 | { | ||
| 5029 | IrInstSrcSpillBegin *instruction = ir_build_instruction<IrInstSrcSpillBegin>(irb, scope, source_node); | ||
| 5030 | instruction->operand = operand; | ||
| 5031 | instruction->spill_id = spill_id; | ||
| 5032 | |||
| 5033 | ir_ref_instruction(operand, irb->current_basic_block); | ||
| 5034 | |||
| 5035 | return instruction; | ||
| 5036 | } | ||
| 5037 | |||
| 5038 | static IrInstGen *ir_build_spill_begin_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, | ||
| 5039 | SpillId spill_id) | ||
| 5040 | { | ||
| 5041 | IrInstGenSpillBegin *instruction = ir_build_inst_void<IrInstGenSpillBegin>(&ira->new_irb, | ||
| 5042 | source_instr->scope, source_instr->source_node); | ||
| 5043 | instruction->operand = operand; | ||
| 5044 | instruction->spill_id = spill_id; | ||
| 5045 | |||
| 5046 | ir_ref_inst_gen(operand); | ||
| 5047 | |||
| 5048 | return &instruction->base; | ||
| 5049 | } | ||
| 5050 | |||
| 5051 | static IrInstSrc *ir_build_spill_end_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 5052 | IrInstSrcSpillBegin *begin) | ||
| 5053 | { | ||
| 5054 | IrInstSrcSpillEnd *instruction = ir_build_instruction<IrInstSrcSpillEnd>(irb, scope, source_node); | ||
| 5055 | instruction->begin = begin; | ||
| 5056 | |||
| 5057 | ir_ref_instruction(&begin->base, irb->current_basic_block); | ||
| 5058 | |||
| 5059 | return &instruction->base; | ||
| 5060 | } | ||
| 5061 | |||
| 5062 | static IrInstGen *ir_build_spill_end_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGenSpillBegin *begin, | ||
| 5063 | ZigType *result_type) | ||
| 5064 | { | ||
| 5065 | IrInstGenSpillEnd *instruction = ir_build_inst_gen<IrInstGenSpillEnd>(&ira->new_irb, | ||
| 5066 | source_instr->scope, source_instr->source_node); | ||
| 5067 | instruction->base.value->type = result_type; | ||
| 5068 | instruction->begin = begin; | ||
| 5069 | |||
| 5070 | ir_ref_inst_gen(&begin->base); | ||
| 5071 | |||
| 5072 | return &instruction->base; | ||
| 5073 | } | ||
| 5074 | |||
| 5075 | static IrInstGen *ir_build_vector_extract_elem(IrAnalyze *ira, IrInst *source_instruction, | ||
| 5076 | IrInstGen *vector, IrInstGen *index) | ||
| 5077 | { | ||
| 5078 | IrInstGenVectorExtractElem *instruction = ir_build_inst_gen<IrInstGenVectorExtractElem>( | ||
| 5079 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 5080 | instruction->base.value->type = vector->value->type->data.vector.elem_type; | ||
| 5081 | instruction->vector = vector; | ||
| 5082 | instruction->index = index; | ||
| 5083 | |||
| 5084 | ir_ref_inst_gen(vector); | ||
| 5085 | ir_ref_inst_gen(index); | ||
| 5086 | |||
| 5087 | return &instruction->base; | ||
| 5088 | } | ||
| 5089 | |||
| 5090 | static IrInstSrc *ir_build_wasm_memory_size_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *index) { | ||
| 5091 | IrInstSrcWasmMemorySize *instruction = ir_build_instruction<IrInstSrcWasmMemorySize>(irb, scope, source_node); | ||
| 5092 | instruction->index = index; | ||
| 5093 | |||
| 5094 | ir_ref_instruction(index, irb->current_basic_block); | ||
| 5095 | |||
| 5096 | return &instruction->base; | ||
| 5097 | } | ||
| 5098 | |||
| 5099 | static IrInstGen *ir_build_wasm_memory_size_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *index) { | ||
| 5100 | IrInstGenWasmMemorySize *instruction = ir_build_inst_gen<IrInstGenWasmMemorySize>(&ira->new_irb, | ||
| 5101 | source_instr->scope, source_instr->source_node); | ||
| 5102 | instruction->base.value->type = ira->codegen->builtin_types.entry_u32; | ||
| 5103 | instruction->index = index; | ||
| 5104 | |||
| 5105 | ir_ref_inst_gen(index); | ||
| 5106 | |||
| 5107 | return &instruction->base; | ||
| 5108 | } | ||
| 5109 | |||
| 5110 | static IrInstSrc *ir_build_wasm_memory_grow_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *index, IrInstSrc *delta) { | ||
| 5111 | IrInstSrcWasmMemoryGrow *instruction = ir_build_instruction<IrInstSrcWasmMemoryGrow>(irb, scope, source_node); | ||
| 5112 | instruction->index = index; | ||
| 5113 | instruction->delta = delta; | ||
| 5114 | |||
| 5115 | ir_ref_instruction(index, irb->current_basic_block); | ||
| 5116 | ir_ref_instruction(delta, irb->current_basic_block); | ||
| 5117 | |||
| 5118 | return &instruction->base; | ||
| 5119 | } | ||
| 5120 | |||
| 5121 | static IrInstGen *ir_build_wasm_memory_grow_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *index, IrInstGen *delta) { | ||
| 5122 | IrInstGenWasmMemoryGrow *instruction = ir_build_inst_gen<IrInstGenWasmMemoryGrow>(&ira->new_irb, | ||
| 5123 | source_instr->scope, source_instr->source_node); | ||
| 5124 | instruction->base.value->type = ira->codegen->builtin_types.entry_i32; | ||
| 5125 | instruction->index = index; | ||
| 5126 | instruction->delta = delta; | ||
| 5127 | |||
| 5128 | ir_ref_inst_gen(index); | ||
| 5129 | ir_ref_inst_gen(delta); | ||
| 5130 | |||
| 5131 | return &instruction->base; | ||
| 5132 | } | ||
| 5133 | |||
| 5134 | static IrInstSrc *ir_build_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) { | ||
| 5135 | IrInstSrcSrc *instruction = ir_build_instruction<IrInstSrcSrc>(irb, scope, source_node); | ||
| 5136 | |||
| 5137 | return &instruction->base; | ||
| 5138 | } | ||
| 5139 | |||
| 5140 | static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | ||
| 5141 | results[ReturnKindUnconditional] = 0; | ||
| 5142 | results[ReturnKindError] = 0; | ||
| 5143 | |||
| 5144 | Scope *scope = inner_scope; | ||
| 5145 | |||
| 5146 | while (scope != outer_scope) { | ||
| 5147 | assert(scope); | ||
| 5148 | switch (scope->id) { | ||
| 5149 | case ScopeIdDefer: { | ||
| 5150 | AstNode *defer_node = scope->source_node; | ||
| 5151 | assert(defer_node->type == NodeTypeDefer); | ||
| 5152 | ReturnKind defer_kind = defer_node->data.defer.kind; | ||
| 5153 | results[defer_kind] += 1; | ||
| 5154 | scope = scope->parent; | ||
| 5155 | continue; | ||
| 5156 | } | ||
| 5157 | case ScopeIdDecls: | ||
| 5158 | case ScopeIdFnDef: | ||
| 5159 | return; | ||
| 5160 | case ScopeIdBlock: | ||
| 5161 | case ScopeIdVarDecl: | ||
| 5162 | case ScopeIdLoop: | ||
| 5163 | case ScopeIdSuspend: | ||
| 5164 | case ScopeIdCompTime: | ||
| 5165 | case ScopeIdNoSuspend: | ||
| 5166 | case ScopeIdRuntime: | ||
| 5167 | case ScopeIdTypeOf: | ||
| 5168 | case ScopeIdExpr: | ||
| 5169 | scope = scope->parent; | ||
| 5170 | continue; | ||
| 5171 | case ScopeIdDeferExpr: | ||
| 5172 | case ScopeIdCImport: | ||
| 5173 | zig_unreachable(); | ||
| 5174 | } | ||
| 5175 | } | ||
| 5176 | } | ||
| 5177 | |||
| 5178 | static IrInstSrc *ir_mark_gen(IrInstSrc *instruction) { | ||
| 5179 | instruction->is_gen = true; | ||
| 5180 | return instruction; | ||
| 5181 | } | ||
| 5182 | |||
| 5183 | static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, bool *is_noreturn, IrInstSrc *err_value) { | ||
| 5184 | Scope *scope = inner_scope; | ||
| 5185 | if (is_noreturn != nullptr) *is_noreturn = false; | ||
| 5186 | while (scope != outer_scope) { | ||
| 5187 | if (!scope) | ||
| 5188 | return true; | ||
| 5189 | |||
| 5190 | switch (scope->id) { | ||
| 5191 | case ScopeIdDefer: { | ||
| 5192 | AstNode *defer_node = scope->source_node; | ||
| 5193 | assert(defer_node->type == NodeTypeDefer); | ||
| 5194 | ReturnKind defer_kind = defer_node->data.defer.kind; | ||
| 5195 | AstNode *defer_expr_node = defer_node->data.defer.expr; | ||
| 5196 | AstNode *defer_var_node = defer_node->data.defer.err_payload; | ||
| 5197 | |||
| 5198 | if (defer_kind == ReturnKindError && err_value == nullptr) { | ||
| 5199 | // This is an `errdefer` but we're generating code for a | ||
| 5200 | // `return` that doesn't return an error, skip it | ||
| 5201 | scope = scope->parent; | ||
| 5202 | continue; | ||
| 5203 | } | ||
| 5204 | |||
| 5205 | Scope *defer_expr_scope = defer_node->data.defer.expr_scope; | ||
| 5206 | if (defer_var_node != nullptr) { | ||
| 5207 | assert(defer_kind == ReturnKindError); | ||
| 5208 | assert(defer_var_node->type == NodeTypeSymbol); | ||
| 5209 | Buf *var_name = defer_var_node->data.symbol_expr.symbol; | ||
| 5210 | |||
| 5211 | if (defer_expr_node->type == NodeTypeUnreachable) { | ||
| 5212 | add_node_error(irb->codegen, defer_var_node, | ||
| 5213 | buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); | ||
| 5214 | return false; | ||
| 5215 | } | ||
| 5216 | |||
| 5217 | IrInstSrc *is_comptime; | ||
| 5218 | if (ir_should_inline(irb->exec, defer_expr_scope)) { | ||
| 5219 | is_comptime = ir_build_const_bool(irb, defer_expr_scope, | ||
| 5220 | defer_expr_node, true); | ||
| 5221 | } else { | ||
| 5222 | is_comptime = ir_build_test_comptime(irb, defer_expr_scope, | ||
| 5223 | defer_expr_node, err_value); | ||
| 5224 | } | ||
| 5225 | |||
| 5226 | ZigVar *err_var = ir_create_var(irb, defer_var_node, defer_expr_scope, | ||
| 5227 | var_name, true, true, false, is_comptime); | ||
| 5228 | build_decl_var_and_init(irb, defer_expr_scope, defer_var_node, err_var, err_value, | ||
| 5229 | buf_ptr(var_name), is_comptime); | ||
| 5230 | |||
| 5231 | defer_expr_scope = err_var->child_scope; | ||
| 5232 | } | ||
| 5233 | |||
| 5234 | IrInstSrc *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope); | ||
| 5235 | if (defer_expr_value == irb->codegen->invalid_inst_src) | ||
| 5236 | return irb->codegen->invalid_inst_src; | ||
| 5237 | |||
| 5238 | if (defer_expr_value->is_noreturn) { | ||
| 5239 | if (is_noreturn != nullptr) *is_noreturn = true; | ||
| 5240 | } else { | ||
| 5241 | ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, | ||
| 5242 | defer_expr_value)); | ||
| 5243 | } | ||
| 5244 | scope = scope->parent; | ||
| 5245 | continue; | ||
| 5246 | } | ||
| 5247 | case ScopeIdDecls: | ||
| 5248 | case ScopeIdFnDef: | ||
| 5249 | return true; | ||
| 5250 | case ScopeIdBlock: | ||
| 5251 | case ScopeIdVarDecl: | ||
| 5252 | case ScopeIdLoop: | ||
| 5253 | case ScopeIdSuspend: | ||
| 5254 | case ScopeIdCompTime: | ||
| 5255 | case ScopeIdNoSuspend: | ||
| 5256 | case ScopeIdRuntime: | ||
| 5257 | case ScopeIdTypeOf: | ||
| 5258 | case ScopeIdExpr: | ||
| 5259 | scope = scope->parent; | ||
| 5260 | continue; | ||
| 5261 | case ScopeIdDeferExpr: | ||
| 5262 | case ScopeIdCImport: | ||
| 5263 | zig_unreachable(); | ||
| 5264 | } | ||
| 5265 | } | ||
| 5266 | return true; | ||
| 5267 | } | ||
| 5268 | |||
| 5269 | static void ir_set_cursor_at_end_gen(IrBuilderGen *irb, IrBasicBlockGen *basic_block) { | ||
| 5270 | assert(basic_block); | ||
| 5271 | irb->current_basic_block = basic_block; | ||
| 5272 | } | ||
| 5273 | |||
| 5274 | static void ir_set_cursor_at_end(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block) { | ||
| 5275 | assert(basic_block); | ||
| 5276 | irb->current_basic_block = basic_block; | ||
| 5277 | } | ||
| 5278 | |||
| 5279 | static void ir_append_basic_block_gen(IrBuilderGen *irb, IrBasicBlockGen *bb) { | ||
| 5280 | assert(!bb->already_appended); | ||
| 5281 | bb->already_appended = true; | ||
| 5282 | irb->exec->basic_block_list.append(bb); | ||
| 5283 | } | ||
| 5284 | |||
| 5285 | static void ir_set_cursor_at_end_and_append_block_gen(IrBuilderGen *irb, IrBasicBlockGen *basic_block) { | ||
| 5286 | ir_append_basic_block_gen(irb, basic_block); | ||
| 5287 | ir_set_cursor_at_end_gen(irb, basic_block); | ||
| 5288 | } | ||
| 5289 | |||
| 5290 | static void ir_set_cursor_at_end_and_append_block(IrBuilderSrc *irb, IrBasicBlockSrc *basic_block) { | ||
| 5291 | basic_block->index = irb->exec->basic_block_list.length; | ||
| 5292 | irb->exec->basic_block_list.append(basic_block); | ||
| 5293 | ir_set_cursor_at_end(irb, basic_block); | ||
| 5294 | } | ||
| 5295 | |||
| 5296 | static ScopeSuspend *get_scope_suspend(Scope *scope) { | ||
| 5297 | while (scope) { | ||
| 5298 | if (scope->id == ScopeIdSuspend) | ||
| 5299 | return (ScopeSuspend *)scope; | ||
| 5300 | if (scope->id == ScopeIdFnDef) | ||
| 5301 | return nullptr; | ||
| 5302 | |||
| 5303 | scope = scope->parent; | ||
| 5304 | } | ||
| 5305 | return nullptr; | ||
| 5306 | } | ||
| 5307 | |||
| 5308 | static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) { | ||
| 5309 | while (scope) { | ||
| 5310 | if (scope->id == ScopeIdDeferExpr) | ||
| 5311 | return (ScopeDeferExpr *)scope; | ||
| 5312 | if (scope->id == ScopeIdFnDef) | ||
| 5313 | return nullptr; | ||
| 5314 | |||
| 5315 | scope = scope->parent; | ||
| 5316 | } | ||
| 5317 | return nullptr; | ||
| 5318 | } | ||
| 5319 | |||
| 5320 | static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { | ||
| 5321 | assert(node->type == NodeTypeReturnExpr); | ||
| 5322 | |||
| 5323 | ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(scope); | ||
| 5324 | if (scope_defer_expr) { | ||
| 5325 | if (!scope_defer_expr->reported_err) { | ||
| 5326 | add_node_error(irb->codegen, node, buf_sprintf("cannot return from defer expression")); | ||
| 5327 | scope_defer_expr->reported_err = true; | ||
| 5328 | } | ||
| 5329 | return irb->codegen->invalid_inst_src; | ||
| 5330 | } | ||
| 5331 | |||
| 5332 | Scope *outer_scope = irb->exec->begin_scope; | ||
| 5333 | |||
| 5334 | AstNode *expr_node = node->data.return_expr.expr; | ||
| 5335 | switch (node->data.return_expr.kind) { | ||
| 5336 | case ReturnKindUnconditional: | ||
| 5337 | { | ||
| 5338 | ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>(); | ||
| 5339 | result_loc_ret->base.id = ResultLocIdReturn; | ||
| 5340 | ir_build_reset_result(irb, scope, node, &result_loc_ret->base); | ||
| 5341 | |||
| 5342 | IrInstSrc *return_value; | ||
| 5343 | if (expr_node) { | ||
| 5344 | // Temporarily set this so that if we return a type it gets the name of the function | ||
| 5345 | ZigFn *prev_name_fn = irb->exec->name_fn; | ||
| 5346 | irb->exec->name_fn = exec_fn_entry(irb->exec); | ||
| 5347 | return_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, &result_loc_ret->base); | ||
| 5348 | irb->exec->name_fn = prev_name_fn; | ||
| 5349 | if (return_value == irb->codegen->invalid_inst_src) | ||
| 5350 | return irb->codegen->invalid_inst_src; | ||
| 5351 | } else { | ||
| 5352 | return_value = ir_build_const_void(irb, scope, node); | ||
| 5353 | ir_build_end_expr(irb, scope, node, return_value, &result_loc_ret->base); | ||
| 5354 | } | ||
| 5355 | |||
| 5356 | ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, return_value, result_loc_ret)); | ||
| 5357 | |||
| 5358 | size_t defer_counts[2]; | ||
| 5359 | ir_count_defers(irb, scope, outer_scope, defer_counts); | ||
| 5360 | bool have_err_defers = defer_counts[ReturnKindError] > 0; | ||
| 5361 | if (!have_err_defers && !irb->codegen->have_err_ret_tracing) { | ||
| 5362 | // only generate unconditional defers | ||
| 5363 | if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, nullptr)) | ||
| 5364 | return irb->codegen->invalid_inst_src; | ||
| 5365 | IrInstSrc *result = ir_build_return_src(irb, scope, node, nullptr); | ||
| 5366 | result_loc_ret->base.source_instruction = result; | ||
| 5367 | return result; | ||
| 5368 | } | ||
| 5369 | bool should_inline = ir_should_inline(irb->exec, scope); | ||
| 5370 | |||
| 5371 | IrBasicBlockSrc *err_block = ir_create_basic_block(irb, scope, "ErrRetErr"); | ||
| 5372 | IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, scope, "ErrRetOk"); | ||
| 5373 | |||
| 5374 | IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node, return_value, false, true); | ||
| 5375 | |||
| 5376 | IrInstSrc *is_comptime; | ||
| 5377 | if (should_inline) { | ||
| 5378 | is_comptime = ir_build_const_bool(irb, scope, node, should_inline); | ||
| 5379 | } else { | ||
| 5380 | is_comptime = ir_build_test_comptime(irb, scope, node, is_err); | ||
| 5381 | } | ||
| 5382 | |||
| 5383 | ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime)); | ||
| 5384 | IrBasicBlockSrc *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt"); | ||
| 5385 | |||
| 5386 | ir_set_cursor_at_end_and_append_block(irb, err_block); | ||
| 5387 | if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, return_value)) | ||
| 5388 | return irb->codegen->invalid_inst_src; | ||
| 5389 | if (irb->codegen->have_err_ret_tracing && !should_inline) { | ||
| 5390 | ir_build_save_err_ret_addr_src(irb, scope, node); | ||
| 5391 | } | ||
| 5392 | ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); | ||
| 5393 | |||
| 5394 | ir_set_cursor_at_end_and_append_block(irb, ok_block); | ||
| 5395 | if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, nullptr)) | ||
| 5396 | return irb->codegen->invalid_inst_src; | ||
| 5397 | ir_build_br(irb, scope, node, ret_stmt_block, is_comptime); | ||
| 5398 | |||
| 5399 | ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block); | ||
| 5400 | IrInstSrc *result = ir_build_return_src(irb, scope, node, nullptr); | ||
| 5401 | result_loc_ret->base.source_instruction = result; | ||
| 5402 | return result; | ||
| 5403 | } | ||
| 5404 | case ReturnKindError: | ||
| 5405 | { | ||
| 5406 | assert(expr_node); | ||
| 5407 | IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); | ||
| 5408 | if (err_union_ptr == irb->codegen->invalid_inst_src) | ||
| 5409 | return irb->codegen->invalid_inst_src; | ||
| 5410 | IrInstSrc *is_err_val = ir_build_test_err_src(irb, scope, node, err_union_ptr, true, false); | ||
| 5411 | |||
| 5412 | IrBasicBlockSrc *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn"); | ||
| 5413 | IrBasicBlockSrc *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue"); | ||
| 5414 | IrInstSrc *is_comptime; | ||
| 5415 | bool should_inline = ir_should_inline(irb->exec, scope); | ||
| 5416 | if (should_inline) { | ||
| 5417 | is_comptime = ir_build_const_bool(irb, scope, node, true); | ||
| 5418 | } else { | ||
| 5419 | is_comptime = ir_build_test_comptime(irb, scope, node, is_err_val); | ||
| 5420 | } | ||
| 5421 | ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime)); | ||
| 5422 | |||
| 5423 | ir_set_cursor_at_end_and_append_block(irb, return_block); | ||
| 5424 | IrInstSrc *err_val_ptr = ir_build_unwrap_err_code_src(irb, scope, node, err_union_ptr); | ||
| 5425 | IrInstSrc *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); | ||
| 5426 | ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, node, err_val, nullptr)); | ||
| 5427 | IrInstSrcSpillBegin *spill_begin = ir_build_spill_begin_src(irb, scope, node, err_val, | ||
| 5428 | SpillIdRetErrCode); | ||
| 5429 | ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>(); | ||
| 5430 | result_loc_ret->base.id = ResultLocIdReturn; | ||
| 5431 | ir_build_reset_result(irb, scope, node, &result_loc_ret->base); | ||
| 5432 | ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base); | ||
| 5433 | |||
| 5434 | bool is_noreturn = false; | ||
| 5435 | if (!ir_gen_defers_for_block(irb, scope, outer_scope, &is_noreturn, err_val)) { | ||
| 5436 | return irb->codegen->invalid_inst_src; | ||
| 5437 | } | ||
| 5438 | if (!is_noreturn) { | ||
| 5439 | if (irb->codegen->have_err_ret_tracing && !should_inline) { | ||
| 5440 | ir_build_save_err_ret_addr_src(irb, scope, node); | ||
| 5441 | } | ||
| 5442 | err_val = ir_build_spill_end_src(irb, scope, node, spill_begin); | ||
| 5443 | IrInstSrc *ret_inst = ir_build_return_src(irb, scope, node, err_val); | ||
| 5444 | result_loc_ret->base.source_instruction = ret_inst; | ||
| 5445 | } | ||
| 5446 | |||
| 5447 | ir_set_cursor_at_end_and_append_block(irb, continue_block); | ||
| 5448 | IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(irb, scope, node, err_union_ptr, false, false); | ||
| 5449 | if (lval == LValPtr) | ||
| 5450 | return unwrapped_ptr; | ||
| 5451 | else | ||
| 5452 | return ir_expr_wrap(irb, scope, ir_build_load_ptr(irb, scope, node, unwrapped_ptr), result_loc); | ||
| 5453 | } | ||
| 5454 | } | ||
| 5455 | zig_unreachable(); | ||
| 5456 | } | ||
| 5457 | |||
| 5458 | static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope, | ||
| 5459 | Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime, | ||
| 5460 | bool skip_name_check) | ||
| 5461 | { | ||
| 5462 | ZigVar *variable_entry = heap::c_allocator.create<ZigVar>(); | ||
| 5463 | variable_entry->parent_scope = parent_scope; | ||
| 5464 | variable_entry->shadowable = is_shadowable; | ||
| 5465 | variable_entry->is_comptime = is_comptime; | ||
| 5466 | variable_entry->src_arg_index = SIZE_MAX; | ||
| 5467 | variable_entry->const_value = codegen->pass1_arena->create<ZigValue>(); | ||
| 5468 | |||
| 5469 | if (is_comptime != nullptr) { | ||
| 5470 | is_comptime->base.ref_count += 1; | ||
| 5471 | } | ||
| 5472 | |||
| 5473 | if (name) { | ||
| 5474 | variable_entry->name = strdup(buf_ptr(name)); | ||
| 5475 | |||
| 5476 | if (!skip_name_check) { | ||
| 5477 | ZigVar *existing_var = find_variable(codegen, parent_scope, name, nullptr); | ||
| 5478 | if (existing_var && !existing_var->shadowable) { | ||
| 5479 | if (existing_var->var_type == nullptr || !type_is_invalid(existing_var->var_type)) { | ||
| 5480 | ErrorMsg *msg = add_node_error(codegen, node, | ||
| 5481 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); | ||
| 5482 | add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); | ||
| 5483 | } | ||
| 5484 | variable_entry->var_type = codegen->builtin_types.entry_invalid; | ||
| 5485 | } else { | ||
| 5486 | ZigType *type; | ||
| 5487 | if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) { | ||
| 5488 | add_node_error(codegen, node, | ||
| 5489 | buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name))); | ||
| 5490 | variable_entry->var_type = codegen->builtin_types.entry_invalid; | ||
| 5491 | } else { | ||
| 5492 | Tld *tld = find_decl(codegen, parent_scope, name); | ||
| 5493 | if (tld != nullptr) { | ||
| 5494 | bool want_err_msg = true; | ||
| 5495 | if (tld->id == TldIdVar) { | ||
| 5496 | ZigVar *var = reinterpret_cast<TldVar *>(tld)->var; | ||
| 5497 | if (var != nullptr && var->var_type != nullptr && type_is_invalid(var->var_type)) { | ||
| 5498 | want_err_msg = false; | ||
| 5499 | } | ||
| 5500 | } | ||
| 5501 | if (want_err_msg) { | ||
| 5502 | ErrorMsg *msg = add_node_error(codegen, node, | ||
| 5503 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); | ||
| 5504 | add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here")); | ||
| 5505 | } | ||
| 5506 | variable_entry->var_type = codegen->builtin_types.entry_invalid; | ||
| 5507 | } | ||
| 5508 | } | ||
| 5509 | } | ||
| 5510 | } | ||
| 5511 | } else { | ||
| 5512 | assert(is_shadowable); | ||
| 5513 | // TODO make this name not actually be in scope. user should be able to make a variable called "_anon" | ||
| 5514 | // might already be solved, let's just make sure it has test coverage | ||
| 5515 | // maybe we put a prefix on this so the debug info doesn't clobber user debug info for same named variables | ||
| 5516 | variable_entry->name = "_anon"; | ||
| 5517 | } | ||
| 5518 | |||
| 5519 | variable_entry->src_is_const = src_is_const; | ||
| 5520 | variable_entry->gen_is_const = gen_is_const; | ||
| 5521 | variable_entry->decl_node = node; | ||
| 5522 | variable_entry->child_scope = create_var_scope(codegen, node, parent_scope, variable_entry); | ||
| 5523 | |||
| 5524 | return variable_entry; | ||
| 5525 | } | ||
| 5526 | |||
| 5527 | // Set name to nullptr to make the variable anonymous (not visible to programmer). | ||
| 5528 | // After you call this function var->child_scope has the variable in scope | ||
| 5529 | static ZigVar *ir_create_var(IrBuilderSrc *irb, AstNode *node, Scope *scope, Buf *name, | ||
| 5530 | bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime) | ||
| 5531 | { | ||
| 5532 | bool is_underscored = name ? buf_eql_str(name, "_") : false; | ||
| 5533 | ZigVar *var = create_local_var(irb->codegen, node, scope, | ||
| 5534 | (is_underscored ? nullptr : name), src_is_const, gen_is_const, | ||
| 5535 | (is_underscored ? true : is_shadowable), is_comptime, false); | ||
| 5536 | assert(var->child_scope); | ||
| 5537 | return var; | ||
| 5538 | } | ||
| 5539 | |||
| 5540 | static ResultLocPeer *create_peer_result(ResultLocPeerParent *peer_parent) { | ||
| 5541 | ResultLocPeer *result = heap::c_allocator.create<ResultLocPeer>(); | ||
| 5542 | result->base.id = ResultLocIdPeer; | ||
| 5543 | result->base.source_instruction = peer_parent->base.source_instruction; | ||
| 5544 | result->parent = peer_parent; | ||
| 5545 | result->base.allow_write_through_const = peer_parent->parent->allow_write_through_const; | ||
| 5546 | return result; | ||
| 5547 | } | ||
| 5548 | |||
| 5549 | static bool is_duplicate_label(CodeGen *g, Scope *scope, AstNode *node, Buf *name) { | ||
| 5550 | if (name == nullptr) return false; | ||
| 5551 | |||
| 5552 | for (;;) { | ||
| 5553 | if (scope == nullptr || scope->id == ScopeIdFnDef) { | ||
| 5554 | break; | ||
| 5555 | } else if (scope->id == ScopeIdBlock || scope->id == ScopeIdLoop) { | ||
| 5556 | Buf *this_block_name = scope->id == ScopeIdBlock ? ((ScopeBlock *)scope)->name : ((ScopeLoop *)scope)->name; | ||
| 5557 | if (this_block_name != nullptr && buf_eql_buf(name, this_block_name)) { | ||
| 5558 | ErrorMsg *msg = add_node_error(g, node, buf_sprintf("redeclaration of label '%s'", buf_ptr(name))); | ||
| 5559 | add_error_note(g, msg, scope->source_node, buf_sprintf("previous declaration is here")); | ||
| 5560 | return true; | ||
| 5561 | } | ||
| 5562 | } | ||
| 5563 | scope = scope->parent; | ||
| 5564 | } | ||
| 5565 | return false; | ||
| 5566 | } | ||
| 5567 | |||
| 5568 | static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *block_node, LVal lval, | ||
| 5569 | ResultLoc *result_loc) | ||
| 5570 | { | ||
| 5571 | assert(block_node->type == NodeTypeBlock); | ||
| 5572 | |||
| 5573 | ZigList<IrInstSrc *> incoming_values = {0}; | ||
| 5574 | ZigList<IrBasicBlockSrc *> incoming_blocks = {0}; | ||
| 5575 | |||
| 5576 | if (is_duplicate_label(irb->codegen, parent_scope, block_node, block_node->data.block.name)) | ||
| 5577 | return irb->codegen->invalid_inst_src; | ||
| 5578 | |||
| 5579 | ScopeBlock *scope_block = create_block_scope(irb->codegen, block_node, parent_scope); | ||
| 5580 | |||
| 5581 | Scope *outer_block_scope = &scope_block->base; | ||
| 5582 | Scope *child_scope = outer_block_scope; | ||
| 5583 | |||
| 5584 | ZigFn *fn_entry = scope_fn_entry(parent_scope); | ||
| 5585 | if (fn_entry && fn_entry->child_scope == parent_scope) { | ||
| 5586 | fn_entry->def_scope = scope_block; | ||
| 5587 | } | ||
| 5588 | |||
| 5589 | if (block_node->data.block.statements.length == 0) { | ||
| 5590 | if (scope_block->name != nullptr) { | ||
| 5591 | add_node_error(irb->codegen, block_node, buf_sprintf("unused block label")); | ||
| 5592 | } | ||
| 5593 | // {} | ||
| 5594 | return ir_lval_wrap(irb, parent_scope, ir_build_const_void(irb, child_scope, block_node), lval, result_loc); | ||
| 5595 | } | ||
| 5596 | |||
| 5597 | if (block_node->data.block.name != nullptr) { | ||
| 5598 | scope_block->lval = lval; | ||
| 5599 | scope_block->incoming_blocks = &incoming_blocks; | ||
| 5600 | scope_block->incoming_values = &incoming_values; | ||
| 5601 | scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd"); | ||
| 5602 | scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, | ||
| 5603 | ir_should_inline(irb->exec, parent_scope)); | ||
| 5604 | |||
| 5605 | scope_block->peer_parent = heap::c_allocator.create<ResultLocPeerParent>(); | ||
| 5606 | scope_block->peer_parent->base.id = ResultLocIdPeerParent; | ||
| 5607 | scope_block->peer_parent->base.source_instruction = scope_block->is_comptime; | ||
| 5608 | scope_block->peer_parent->base.allow_write_through_const = result_loc->allow_write_through_const; | ||
| 5609 | scope_block->peer_parent->end_bb = scope_block->end_block; | ||
| 5610 | scope_block->peer_parent->is_comptime = scope_block->is_comptime; | ||
| 5611 | scope_block->peer_parent->parent = result_loc; | ||
| 5612 | ir_build_reset_result(irb, parent_scope, block_node, &scope_block->peer_parent->base); | ||
| 5613 | } | ||
| 5614 | |||
| 5615 | bool is_continuation_unreachable = false; | ||
| 5616 | bool found_invalid_inst = false; | ||
| 5617 | IrInstSrc *noreturn_return_value = nullptr; | ||
| 5618 | for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { | ||
| 5619 | AstNode *statement_node = block_node->data.block.statements.at(i); | ||
| 5620 | |||
| 5621 | IrInstSrc *statement_value = ir_gen_node(irb, statement_node, child_scope); | ||
| 5622 | if (statement_value == irb->codegen->invalid_inst_src) { | ||
| 5623 | // keep generating all the elements of the block in case of error, | ||
| 5624 | // we want to collect other compile errors | ||
| 5625 | found_invalid_inst = true; | ||
| 5626 | continue; | ||
| 5627 | } | ||
| 5628 | |||
| 5629 | is_continuation_unreachable = instr_is_unreachable(statement_value); | ||
| 5630 | if (is_continuation_unreachable) { | ||
| 5631 | // keep the last noreturn statement value around in case we need to return it | ||
| 5632 | noreturn_return_value = statement_value; | ||
| 5633 | } | ||
| 5634 | // This logic must be kept in sync with | ||
| 5635 | // [STMT_EXPR_TEST_THING] <--- (search this token) | ||
| 5636 | if (statement_node->type == NodeTypeDefer) { | ||
| 5637 | // defer starts a new scope | ||
| 5638 | child_scope = statement_node->data.defer.child_scope; | ||
| 5639 | assert(child_scope); | ||
| 5640 | } else if (statement_value->id == IrInstSrcIdDeclVar) { | ||
| 5641 | // variable declarations start a new scope | ||
| 5642 | IrInstSrcDeclVar *decl_var_instruction = (IrInstSrcDeclVar *)statement_value; | ||
| 5643 | child_scope = decl_var_instruction->var->child_scope; | ||
| 5644 | } else if (!is_continuation_unreachable) { | ||
| 5645 | // this statement's value must be void | ||
| 5646 | ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, statement_node, statement_value)); | ||
| 5647 | } | ||
| 5648 | } | ||
| 5649 | |||
| 5650 | if (scope_block->name != nullptr && scope_block->name_used == false) { | ||
| 5651 | add_node_error(irb->codegen, block_node, buf_sprintf("unused block label")); | ||
| 5652 | } | ||
| 5653 | |||
| 5654 | if (found_invalid_inst) | ||
| 5655 | return irb->codegen->invalid_inst_src; | ||
| 5656 | |||
| 5657 | if (is_continuation_unreachable) { | ||
| 5658 | assert(noreturn_return_value != nullptr); | ||
| 5659 | if (block_node->data.block.name == nullptr || incoming_blocks.length == 0) { | ||
| 5660 | return noreturn_return_value; | ||
| 5661 | } | ||
| 5662 | |||
| 5663 | if (scope_block->peer_parent != nullptr && scope_block->peer_parent->peers.length != 0) { | ||
| 5664 | scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block; | ||
| 5665 | } | ||
| 5666 | ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block); | ||
| 5667 | IrInstSrc *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, | ||
| 5668 | incoming_blocks.items, incoming_values.items, scope_block->peer_parent); | ||
| 5669 | return ir_expr_wrap(irb, parent_scope, phi, result_loc); | ||
| 5670 | } else { | ||
| 5671 | incoming_blocks.append(irb->current_basic_block); | ||
| 5672 | IrInstSrc *else_expr_result = ir_mark_gen(ir_build_const_void(irb, parent_scope, block_node)); | ||
| 5673 | |||
| 5674 | if (scope_block->peer_parent != nullptr) { | ||
| 5675 | ResultLocPeer *peer_result = create_peer_result(scope_block->peer_parent); | ||
| 5676 | scope_block->peer_parent->peers.append(peer_result); | ||
| 5677 | ir_build_end_expr(irb, parent_scope, block_node, else_expr_result, &peer_result->base); | ||
| 5678 | |||
| 5679 | if (scope_block->peer_parent->peers.length != 0) { | ||
| 5680 | scope_block->peer_parent->peers.last()->next_bb = scope_block->end_block; | ||
| 5681 | } | ||
| 5682 | } | ||
| 5683 | |||
| 5684 | incoming_values.append(else_expr_result); | ||
| 5685 | } | ||
| 5686 | |||
| 5687 | bool is_return_from_fn = block_node == irb->main_block_node; | ||
| 5688 | if (!is_return_from_fn) { | ||
| 5689 | if (!ir_gen_defers_for_block(irb, child_scope, outer_block_scope, nullptr, nullptr)) | ||
| 5690 | return irb->codegen->invalid_inst_src; | ||
| 5691 | } | ||
| 5692 | |||
| 5693 | IrInstSrc *result; | ||
| 5694 | if (block_node->data.block.name != nullptr) { | ||
| 5695 | ir_mark_gen(ir_build_br(irb, parent_scope, block_node, scope_block->end_block, scope_block->is_comptime)); | ||
| 5696 | ir_set_cursor_at_end_and_append_block(irb, scope_block->end_block); | ||
| 5697 | IrInstSrc *phi = ir_build_phi(irb, parent_scope, block_node, incoming_blocks.length, | ||
| 5698 | incoming_blocks.items, incoming_values.items, scope_block->peer_parent); | ||
| 5699 | result = ir_expr_wrap(irb, parent_scope, phi, result_loc); | ||
| 5700 | } else { | ||
| 5701 | IrInstSrc *void_inst = ir_mark_gen(ir_build_const_void(irb, child_scope, block_node)); | ||
| 5702 | result = ir_lval_wrap(irb, parent_scope, void_inst, lval, result_loc); | ||
| 5703 | } | ||
| 5704 | if (!is_return_from_fn) | ||
| 5705 | return result; | ||
| 5706 | |||
| 5707 | // no need for save_err_ret_addr because this cannot return error | ||
| 5708 | // only generate unconditional defers | ||
| 5709 | |||
| 5710 | ir_mark_gen(ir_build_add_implicit_return_type(irb, child_scope, block_node, result, nullptr)); | ||
| 5711 | ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>(); | ||
| 5712 | result_loc_ret->base.id = ResultLocIdReturn; | ||
| 5713 | ir_build_reset_result(irb, parent_scope, block_node, &result_loc_ret->base); | ||
| 5714 | ir_mark_gen(ir_build_end_expr(irb, parent_scope, block_node, result, &result_loc_ret->base)); | ||
| 5715 | if (!ir_gen_defers_for_block(irb, child_scope, outer_block_scope, nullptr, nullptr)) | ||
| 5716 | return irb->codegen->invalid_inst_src; | ||
| 5717 | return ir_mark_gen(ir_build_return_src(irb, child_scope, result->base.source_node, result)); | ||
| 5718 | } | ||
| 5719 | |||
| 5720 | static IrInstSrc *ir_gen_bin_op_id(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrBinOp op_id) { | ||
| 5721 | Scope *inner_scope = scope; | ||
| 5722 | if (op_id == IrBinOpArrayCat || op_id == IrBinOpArrayMult) { | ||
| 5723 | inner_scope = create_comptime_scope(irb->codegen, node, scope); | ||
| 5724 | } | ||
| 5725 | |||
| 5726 | IrInstSrc *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, inner_scope); | ||
| 5727 | IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, inner_scope); | ||
| 5728 | |||
| 5729 | if (op1 == irb->codegen->invalid_inst_src || op2 == irb->codegen->invalid_inst_src) | ||
| 5730 | return irb->codegen->invalid_inst_src; | ||
| 5731 | |||
| 5732 | return ir_build_bin_op(irb, scope, node, op_id, op1, op2, true); | ||
| 5733 | } | ||
| 5734 | |||
| 5735 | static IrInstSrc *ir_gen_merge_err_sets(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 5736 | IrInstSrc *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); | ||
| 5737 | IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); | ||
| 5738 | |||
| 5739 | if (op1 == irb->codegen->invalid_inst_src || op2 == irb->codegen->invalid_inst_src) | ||
| 5740 | return irb->codegen->invalid_inst_src; | ||
| 5741 | |||
| 5742 | // TODO only pass type_name when the || operator is the top level AST node in the var decl expr | ||
| 5743 | Buf bare_name = BUF_INIT; | ||
| 5744 | Buf *type_name = get_anon_type_name(irb->codegen, irb->exec, "error", scope, node, &bare_name); | ||
| 5745 | |||
| 5746 | return ir_build_merge_err_sets(irb, scope, node, op1, op2, type_name); | ||
| 5747 | } | ||
| 5748 | |||
| 5749 | static IrInstSrc *ir_gen_assign(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 5750 | IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); | ||
| 5751 | if (lvalue == irb->codegen->invalid_inst_src) | ||
| 5752 | return irb->codegen->invalid_inst_src; | ||
| 5753 | |||
| 5754 | ResultLocInstruction *result_loc_inst = heap::c_allocator.create<ResultLocInstruction>(); | ||
| 5755 | result_loc_inst->base.id = ResultLocIdInstruction; | ||
| 5756 | result_loc_inst->base.source_instruction = lvalue; | ||
| 5757 | ir_ref_instruction(lvalue, irb->current_basic_block); | ||
| 5758 | ir_build_reset_result(irb, scope, node, &result_loc_inst->base); | ||
| 5759 | |||
| 5760 | IrInstSrc *rvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op2, scope, LValNone, | ||
| 5761 | &result_loc_inst->base); | ||
| 5762 | if (rvalue == irb->codegen->invalid_inst_src) | ||
| 5763 | return irb->codegen->invalid_inst_src; | ||
| 5764 | |||
| 5765 | return ir_build_const_void(irb, scope, node); | ||
| 5766 | } | ||
| 5767 | |||
| 5768 | static IrInstSrc *ir_gen_assign_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrBinOp op_id) { | ||
| 5769 | IrInstSrc *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValAssign, nullptr); | ||
| 5770 | if (lvalue == irb->codegen->invalid_inst_src) | ||
| 5771 | return lvalue; | ||
| 5772 | IrInstSrc *op1 = ir_build_load_ptr(irb, scope, node->data.bin_op_expr.op1, lvalue); | ||
| 5773 | IrInstSrc *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); | ||
| 5774 | if (op2 == irb->codegen->invalid_inst_src) | ||
| 5775 | return op2; | ||
| 5776 | IrInstSrc *result = ir_build_bin_op(irb, scope, node, op_id, op1, op2, true); | ||
| 5777 | ir_build_store_ptr(irb, scope, node, lvalue, result); | ||
| 5778 | return ir_build_const_void(irb, scope, node); | ||
| 5779 | } | ||
| 5780 | |||
| 5781 | static IrInstSrc *ir_gen_bool_or(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 5782 | assert(node->type == NodeTypeBinOpExpr); | ||
| 5783 | |||
| 5784 | IrInstSrc *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); | ||
| 5785 | if (val1 == irb->codegen->invalid_inst_src) | ||
| 5786 | return irb->codegen->invalid_inst_src; | ||
| 5787 | IrBasicBlockSrc *post_val1_block = irb->current_basic_block; | ||
| 5788 | |||
| 5789 | IrInstSrc *is_comptime; | ||
| 5790 | if (ir_should_inline(irb->exec, scope)) { | ||
| 5791 | is_comptime = ir_build_const_bool(irb, scope, node, true); | ||
| 5792 | } else { | ||
| 5793 | is_comptime = ir_build_test_comptime(irb, scope, node, val1); | ||
| 5794 | } | ||
| 5795 | |||
| 5796 | // block for when val1 == false | ||
| 5797 | IrBasicBlockSrc *false_block = ir_create_basic_block(irb, scope, "BoolOrFalse"); | ||
| 5798 | // block for when val1 == true (don't even evaluate the second part) | ||
| 5799 | IrBasicBlockSrc *true_block = ir_create_basic_block(irb, scope, "BoolOrTrue"); | ||
| 5800 | |||
| 5801 | ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime); | ||
| 5802 | |||
| 5803 | ir_set_cursor_at_end_and_append_block(irb, false_block); | ||
| 5804 | IrInstSrc *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); | ||
| 5805 | if (val2 == irb->codegen->invalid_inst_src) | ||
| 5806 | return irb->codegen->invalid_inst_src; | ||
| 5807 | IrBasicBlockSrc *post_val2_block = irb->current_basic_block; | ||
| 5808 | |||
| 5809 | ir_build_br(irb, scope, node, true_block, is_comptime); | ||
| 5810 | |||
| 5811 | ir_set_cursor_at_end_and_append_block(irb, true_block); | ||
| 5812 | |||
| 5813 | IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2); | ||
| 5814 | incoming_values[0] = val1; | ||
| 5815 | incoming_values[1] = val2; | ||
| 5816 | IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate<IrBasicBlockSrc *>(2); | ||
| 5817 | incoming_blocks[0] = post_val1_block; | ||
| 5818 | incoming_blocks[1] = post_val2_block; | ||
| 5819 | |||
| 5820 | return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr); | ||
| 5821 | } | ||
| 5822 | |||
| 5823 | static IrInstSrc *ir_gen_bool_and(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 5824 | assert(node->type == NodeTypeBinOpExpr); | ||
| 5825 | |||
| 5826 | IrInstSrc *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); | ||
| 5827 | if (val1 == irb->codegen->invalid_inst_src) | ||
| 5828 | return irb->codegen->invalid_inst_src; | ||
| 5829 | IrBasicBlockSrc *post_val1_block = irb->current_basic_block; | ||
| 5830 | |||
| 5831 | IrInstSrc *is_comptime; | ||
| 5832 | if (ir_should_inline(irb->exec, scope)) { | ||
| 5833 | is_comptime = ir_build_const_bool(irb, scope, node, true); | ||
| 5834 | } else { | ||
| 5835 | is_comptime = ir_build_test_comptime(irb, scope, node, val1); | ||
| 5836 | } | ||
| 5837 | |||
| 5838 | // block for when val1 == true | ||
| 5839 | IrBasicBlockSrc *true_block = ir_create_basic_block(irb, scope, "BoolAndTrue"); | ||
| 5840 | // block for when val1 == false (don't even evaluate the second part) | ||
| 5841 | IrBasicBlockSrc *false_block = ir_create_basic_block(irb, scope, "BoolAndFalse"); | ||
| 5842 | |||
| 5843 | ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_comptime); | ||
| 5844 | |||
| 5845 | ir_set_cursor_at_end_and_append_block(irb, true_block); | ||
| 5846 | IrInstSrc *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); | ||
| 5847 | if (val2 == irb->codegen->invalid_inst_src) | ||
| 5848 | return irb->codegen->invalid_inst_src; | ||
| 5849 | IrBasicBlockSrc *post_val2_block = irb->current_basic_block; | ||
| 5850 | |||
| 5851 | ir_build_br(irb, scope, node, false_block, is_comptime); | ||
| 5852 | |||
| 5853 | ir_set_cursor_at_end_and_append_block(irb, false_block); | ||
| 5854 | |||
| 5855 | IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2); | ||
| 5856 | incoming_values[0] = val1; | ||
| 5857 | incoming_values[1] = val2; | ||
| 5858 | IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate<IrBasicBlockSrc *>(2); | ||
| 5859 | incoming_blocks[0] = post_val1_block; | ||
| 5860 | incoming_blocks[1] = post_val2_block; | ||
| 5861 | |||
| 5862 | return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, nullptr); | ||
| 5863 | } | ||
| 5864 | |||
| 5865 | static ResultLocPeerParent *ir_build_result_peers(IrBuilderSrc *irb, IrInstSrc *cond_br_inst, | ||
| 5866 | IrBasicBlockSrc *end_block, ResultLoc *parent, IrInstSrc *is_comptime) | ||
| 5867 | { | ||
| 5868 | ResultLocPeerParent *peer_parent = heap::c_allocator.create<ResultLocPeerParent>(); | ||
| 5869 | peer_parent->base.id = ResultLocIdPeerParent; | ||
| 5870 | peer_parent->base.source_instruction = cond_br_inst; | ||
| 5871 | peer_parent->base.allow_write_through_const = parent->allow_write_through_const; | ||
| 5872 | peer_parent->end_bb = end_block; | ||
| 5873 | peer_parent->is_comptime = is_comptime; | ||
| 5874 | peer_parent->parent = parent; | ||
| 5875 | |||
| 5876 | IrInstSrc *popped_inst = irb->current_basic_block->instruction_list.pop(); | ||
| 5877 | ir_assert(popped_inst == cond_br_inst, &cond_br_inst->base); | ||
| 5878 | |||
| 5879 | ir_build_reset_result(irb, cond_br_inst->base.scope, cond_br_inst->base.source_node, &peer_parent->base); | ||
| 5880 | irb->current_basic_block->instruction_list.append(popped_inst); | ||
| 5881 | |||
| 5882 | return peer_parent; | ||
| 5883 | } | ||
| 5884 | |||
| 5885 | static ResultLocPeerParent *ir_build_binary_result_peers(IrBuilderSrc *irb, IrInstSrc *cond_br_inst, | ||
| 5886 | IrBasicBlockSrc *else_block, IrBasicBlockSrc *end_block, ResultLoc *parent, IrInstSrc *is_comptime) | ||
| 5887 | { | ||
| 5888 | ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, parent, is_comptime); | ||
| 5889 | |||
| 5890 | peer_parent->peers.append(create_peer_result(peer_parent)); | ||
| 5891 | peer_parent->peers.last()->next_bb = else_block; | ||
| 5892 | |||
| 5893 | peer_parent->peers.append(create_peer_result(peer_parent)); | ||
| 5894 | peer_parent->peers.last()->next_bb = end_block; | ||
| 5895 | |||
| 5896 | return peer_parent; | ||
| 5897 | } | ||
| 5898 | |||
| 5899 | static IrInstSrc *ir_gen_orelse(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, | ||
| 5900 | ResultLoc *result_loc) | ||
| 5901 | { | ||
| 5902 | assert(node->type == NodeTypeBinOpExpr); | ||
| 5903 | |||
| 5904 | AstNode *op1_node = node->data.bin_op_expr.op1; | ||
| 5905 | AstNode *op2_node = node->data.bin_op_expr.op2; | ||
| 5906 | |||
| 5907 | IrInstSrc *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPtr, nullptr); | ||
| 5908 | if (maybe_ptr == irb->codegen->invalid_inst_src) | ||
| 5909 | return irb->codegen->invalid_inst_src; | ||
| 5910 | |||
| 5911 | IrInstSrc *maybe_val = ir_build_load_ptr(irb, parent_scope, node, maybe_ptr); | ||
| 5912 | IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, parent_scope, node, maybe_val); | ||
| 5913 | |||
| 5914 | IrInstSrc *is_comptime; | ||
| 5915 | if (ir_should_inline(irb->exec, parent_scope)) { | ||
| 5916 | is_comptime = ir_build_const_bool(irb, parent_scope, node, true); | ||
| 5917 | } else { | ||
| 5918 | is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_non_null); | ||
| 5919 | } | ||
| 5920 | |||
| 5921 | IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, parent_scope, "OptionalNonNull"); | ||
| 5922 | IrBasicBlockSrc *null_block = ir_create_basic_block(irb, parent_scope, "OptionalNull"); | ||
| 5923 | IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "OptionalEnd"); | ||
| 5924 | IrInstSrc *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_comptime); | ||
| 5925 | |||
| 5926 | ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block, | ||
| 5927 | result_loc, is_comptime); | ||
| 5928 | |||
| 5929 | ir_set_cursor_at_end_and_append_block(irb, null_block); | ||
| 5930 | IrInstSrc *null_result = ir_gen_node_extra(irb, op2_node, parent_scope, LValNone, | ||
| 5931 | &peer_parent->peers.at(0)->base); | ||
| 5932 | if (null_result == irb->codegen->invalid_inst_src) | ||
| 5933 | return irb->codegen->invalid_inst_src; | ||
| 5934 | IrBasicBlockSrc *after_null_block = irb->current_basic_block; | ||
| 5935 | if (!instr_is_unreachable(null_result)) | ||
| 5936 | ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); | ||
| 5937 | |||
| 5938 | ir_set_cursor_at_end_and_append_block(irb, ok_block); | ||
| 5939 | IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false); | ||
| 5940 | IrInstSrc *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); | ||
| 5941 | ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); | ||
| 5942 | IrBasicBlockSrc *after_ok_block = irb->current_basic_block; | ||
| 5943 | ir_build_br(irb, parent_scope, node, end_block, is_comptime); | ||
| 5944 | |||
| 5945 | ir_set_cursor_at_end_and_append_block(irb, end_block); | ||
| 5946 | IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2); | ||
| 5947 | incoming_values[0] = null_result; | ||
| 5948 | incoming_values[1] = unwrapped_payload; | ||
| 5949 | IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate<IrBasicBlockSrc *>(2); | ||
| 5950 | incoming_blocks[0] = after_null_block; | ||
| 5951 | incoming_blocks[1] = after_ok_block; | ||
| 5952 | IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); | ||
| 5953 | return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); | ||
| 5954 | } | ||
| 5955 | |||
| 5956 | static IrInstSrc *ir_gen_error_union(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { | ||
| 5957 | assert(node->type == NodeTypeBinOpExpr); | ||
| 5958 | |||
| 5959 | AstNode *op1_node = node->data.bin_op_expr.op1; | ||
| 5960 | AstNode *op2_node = node->data.bin_op_expr.op2; | ||
| 5961 | |||
| 5962 | IrInstSrc *err_set = ir_gen_node(irb, op1_node, parent_scope); | ||
| 5963 | if (err_set == irb->codegen->invalid_inst_src) | ||
| 5964 | return irb->codegen->invalid_inst_src; | ||
| 5965 | |||
| 5966 | IrInstSrc *payload = ir_gen_node(irb, op2_node, parent_scope); | ||
| 5967 | if (payload == irb->codegen->invalid_inst_src) | ||
| 5968 | return irb->codegen->invalid_inst_src; | ||
| 5969 | |||
| 5970 | return ir_build_error_union(irb, parent_scope, node, err_set, payload); | ||
| 5971 | } | ||
| 5972 | |||
| 5973 | static IrInstSrc *ir_gen_bin_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { | ||
| 5974 | assert(node->type == NodeTypeBinOpExpr); | ||
| 5975 | |||
| 5976 | BinOpType bin_op_type = node->data.bin_op_expr.bin_op; | ||
| 5977 | switch (bin_op_type) { | ||
| 5978 | case BinOpTypeInvalid: | ||
| 5979 | zig_unreachable(); | ||
| 5980 | case BinOpTypeAssign: | ||
| 5981 | return ir_lval_wrap(irb, scope, ir_gen_assign(irb, scope, node), lval, result_loc); | ||
| 5982 | case BinOpTypeAssignTimes: | ||
| 5983 | return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMult), lval, result_loc); | ||
| 5984 | case BinOpTypeAssignTimesWrap: | ||
| 5985 | return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpMultWrap), lval, result_loc); | ||
| 5986 | case BinOpTypeAssignDiv: | ||
| 5987 | return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpDivUnspecified), lval, result_loc); | ||
| 5988 | case BinOpTypeAssignMod: | ||
| 5989 | return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpRemUnspecified), lval, result_loc); | ||
| 5990 | case BinOpTypeAssignPlus: | ||
| 5991 | return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpAdd), lval, result_loc); | ||
| 5992 | case BinOpTypeAssignPlusWrap: | ||
| 5993 | return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpAddWrap), lval, result_loc); | ||
| 5994 | case BinOpTypeAssignMinus: | ||
| 5995 | return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpSub), lval, result_loc); | ||
| 5996 | case BinOpTypeAssignMinusWrap: | ||
| 5997 | return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpSubWrap), lval, result_loc); | ||
| 5998 | case BinOpTypeAssignBitShiftLeft: | ||
| 5999 | return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); | ||
| 6000 | case BinOpTypeAssignBitShiftRight: | ||
| 6001 | return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); | ||
| 6002 | case BinOpTypeAssignBitAnd: | ||
| 6003 | return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinAnd), lval, result_loc); | ||
| 6004 | case BinOpTypeAssignBitXor: | ||
| 6005 | return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinXor), lval, result_loc); | ||
| 6006 | case BinOpTypeAssignBitOr: | ||
| 6007 | return ir_lval_wrap(irb, scope, ir_gen_assign_op(irb, scope, node, IrBinOpBinOr), lval, result_loc); | ||
| 6008 | case BinOpTypeBoolOr: | ||
| 6009 | return ir_lval_wrap(irb, scope, ir_gen_bool_or(irb, scope, node), lval, result_loc); | ||
| 6010 | case BinOpTypeBoolAnd: | ||
| 6011 | return ir_lval_wrap(irb, scope, ir_gen_bool_and(irb, scope, node), lval, result_loc); | ||
| 6012 | case BinOpTypeCmpEq: | ||
| 6013 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpEq), lval, result_loc); | ||
| 6014 | case BinOpTypeCmpNotEq: | ||
| 6015 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpNotEq), lval, result_loc); | ||
| 6016 | case BinOpTypeCmpLessThan: | ||
| 6017 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessThan), lval, result_loc); | ||
| 6018 | case BinOpTypeCmpGreaterThan: | ||
| 6019 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterThan), lval, result_loc); | ||
| 6020 | case BinOpTypeCmpLessOrEq: | ||
| 6021 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpLessOrEq), lval, result_loc); | ||
| 6022 | case BinOpTypeCmpGreaterOrEq: | ||
| 6023 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpGreaterOrEq), lval, result_loc); | ||
| 6024 | case BinOpTypeBinOr: | ||
| 6025 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinOr), lval, result_loc); | ||
| 6026 | case BinOpTypeBinXor: | ||
| 6027 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinXor), lval, result_loc); | ||
| 6028 | case BinOpTypeBinAnd: | ||
| 6029 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBinAnd), lval, result_loc); | ||
| 6030 | case BinOpTypeBitShiftLeft: | ||
| 6031 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftLeftLossy), lval, result_loc); | ||
| 6032 | case BinOpTypeBitShiftRight: | ||
| 6033 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpBitShiftRightLossy), lval, result_loc); | ||
| 6034 | case BinOpTypeAdd: | ||
| 6035 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpAdd), lval, result_loc); | ||
| 6036 | case BinOpTypeAddWrap: | ||
| 6037 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpAddWrap), lval, result_loc); | ||
| 6038 | case BinOpTypeSub: | ||
| 6039 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpSub), lval, result_loc); | ||
| 6040 | case BinOpTypeSubWrap: | ||
| 6041 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpSubWrap), lval, result_loc); | ||
| 6042 | case BinOpTypeMult: | ||
| 6043 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMult), lval, result_loc); | ||
| 6044 | case BinOpTypeMultWrap: | ||
| 6045 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpMultWrap), lval, result_loc); | ||
| 6046 | case BinOpTypeDiv: | ||
| 6047 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpDivUnspecified), lval, result_loc); | ||
| 6048 | case BinOpTypeMod: | ||
| 6049 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpRemUnspecified), lval, result_loc); | ||
| 6050 | case BinOpTypeArrayCat: | ||
| 6051 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayCat), lval, result_loc); | ||
| 6052 | case BinOpTypeArrayMult: | ||
| 6053 | return ir_lval_wrap(irb, scope, ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult), lval, result_loc); | ||
| 6054 | case BinOpTypeMergeErrorSets: | ||
| 6055 | return ir_lval_wrap(irb, scope, ir_gen_merge_err_sets(irb, scope, node), lval, result_loc); | ||
| 6056 | case BinOpTypeUnwrapOptional: | ||
| 6057 | return ir_gen_orelse(irb, scope, node, lval, result_loc); | ||
| 6058 | case BinOpTypeErrorUnion: | ||
| 6059 | return ir_lval_wrap(irb, scope, ir_gen_error_union(irb, scope, node), lval, result_loc); | ||
| 6060 | } | ||
| 6061 | zig_unreachable(); | ||
| 6062 | } | ||
| 6063 | |||
| 6064 | static IrInstSrc *ir_gen_int_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 6065 | assert(node->type == NodeTypeIntLiteral); | ||
| 6066 | |||
| 6067 | return ir_build_const_bigint(irb, scope, node, node->data.int_literal.bigint); | ||
| 6068 | } | ||
| 6069 | |||
| 6070 | static IrInstSrc *ir_gen_float_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 6071 | assert(node->type == NodeTypeFloatLiteral); | ||
| 6072 | |||
| 6073 | if (node->data.float_literal.overflow) { | ||
| 6074 | add_node_error(irb->codegen, node, buf_sprintf("float literal out of range of any type")); | ||
| 6075 | return irb->codegen->invalid_inst_src; | ||
| 6076 | } | ||
| 6077 | |||
| 6078 | return ir_build_const_bigfloat(irb, scope, node, node->data.float_literal.bigfloat); | ||
| 6079 | } | ||
| 6080 | |||
| 6081 | static IrInstSrc *ir_gen_char_lit(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 6082 | assert(node->type == NodeTypeCharLiteral); | ||
| 6083 | |||
| 6084 | return ir_build_const_uint(irb, scope, node, node->data.char_literal.value); | ||
| 6085 | } | ||
| 6086 | |||
| 6087 | static IrInstSrc *ir_gen_null_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 6088 | assert(node->type == NodeTypeNullLiteral); | ||
| 6089 | |||
| 6090 | return ir_build_const_null(irb, scope, node); | ||
| 6091 | } | ||
| 6092 | |||
| 6093 | static void populate_invalid_variable_in_scope(CodeGen *g, Scope *scope, AstNode *node, Buf *var_name) { | ||
| 6094 | ScopeDecls *scope_decls = nullptr; | ||
| 6095 | while (scope != nullptr) { | ||
| 6096 | if (scope->id == ScopeIdDecls) { | ||
| 6097 | scope_decls = reinterpret_cast<ScopeDecls *>(scope); | ||
| 6098 | } | ||
| 6099 | scope = scope->parent; | ||
| 6100 | } | ||
| 6101 | TldVar *tld_var = heap::c_allocator.create<TldVar>(); | ||
| 6102 | init_tld(&tld_var->base, TldIdVar, var_name, VisibModPub, node, &scope_decls->base); | ||
| 6103 | tld_var->base.resolution = TldResolutionInvalid; | ||
| 6104 | tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false, | ||
| 6105 | g->invalid_inst_gen->value, &tld_var->base, g->builtin_types.entry_invalid); | ||
| 6106 | scope_decls->decl_table.put(var_name, &tld_var->base); | ||
| 6107 | } | ||
| 6108 | |||
| 6109 | static IrInstSrc *ir_gen_symbol(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { | ||
| 6110 | Error err; | ||
| 6111 | assert(node->type == NodeTypeSymbol); | ||
| 6112 | |||
| 6113 | Buf *variable_name = node->data.symbol_expr.symbol; | ||
| 6114 | |||
| 6115 | if (buf_eql_str(variable_name, "_")) { | ||
| 6116 | if (lval == LValAssign) { | ||
| 6117 | IrInstSrcConst *const_instruction = ir_build_instruction<IrInstSrcConst>(irb, scope, node); | ||
| 6118 | const_instruction->value = irb->codegen->pass1_arena->create<ZigValue>(); | ||
| 6119 | const_instruction->value->type = get_pointer_to_type(irb->codegen, | ||
| 6120 | irb->codegen->builtin_types.entry_void, false); | ||
| 6121 | const_instruction->value->special = ConstValSpecialStatic; | ||
| 6122 | const_instruction->value->data.x_ptr.special = ConstPtrSpecialDiscard; | ||
| 6123 | return &const_instruction->base; | ||
| 6124 | } else { | ||
| 6125 | add_node_error(irb->codegen, node, buf_sprintf("`_` may only be used to assign things to")); | ||
| 6126 | return irb->codegen->invalid_inst_src; | ||
| 6127 | } | ||
| 6128 | } | ||
| 6129 | |||
| 6130 | ZigType *primitive_type; | ||
| 6131 | if ((err = get_primitive_type(irb->codegen, variable_name, &primitive_type))) { | ||
| 6132 | if (err == ErrorOverflow) { | ||
| 6133 | add_node_error(irb->codegen, node, | ||
| 6134 | buf_sprintf("primitive integer type '%s' exceeds maximum bit width of 65535", | ||
| 6135 | buf_ptr(variable_name))); | ||
| 6136 | return irb->codegen->invalid_inst_src; | ||
| 6137 | } | ||
| 6138 | assert(err == ErrorPrimitiveTypeNotFound); | ||
| 6139 | } else { | ||
| 6140 | IrInstSrc *value = ir_build_const_type(irb, scope, node, primitive_type); | ||
| 6141 | if (lval == LValPtr || lval == LValAssign) { | ||
| 6142 | return ir_build_ref_src(irb, scope, node, value); | ||
| 6143 | } else { | ||
| 6144 | return ir_expr_wrap(irb, scope, value, result_loc); | ||
| 6145 | } | ||
| 6146 | } | ||
| 6147 | |||
| 6148 | ScopeFnDef *crossed_fndef_scope; | ||
| 6149 | ZigVar *var = find_variable(irb->codegen, scope, variable_name, &crossed_fndef_scope); | ||
| 6150 | if (var) { | ||
| 6151 | IrInstSrc *var_ptr = ir_build_var_ptr_x(irb, scope, node, var, crossed_fndef_scope); | ||
| 6152 | if (lval == LValPtr || lval == LValAssign) { | ||
| 6153 | return var_ptr; | ||
| 6154 | } else { | ||
| 6155 | return ir_expr_wrap(irb, scope, ir_build_load_ptr(irb, scope, node, var_ptr), result_loc); | ||
| 6156 | } | ||
| 6157 | } | ||
| 6158 | |||
| 6159 | Tld *tld = find_decl(irb->codegen, scope, variable_name); | ||
| 6160 | if (tld) { | ||
| 6161 | IrInstSrc *decl_ref = ir_build_decl_ref(irb, scope, node, tld, lval); | ||
| 6162 | if (lval == LValPtr || lval == LValAssign) { | ||
| 6163 | return decl_ref; | ||
| 6164 | } else { | ||
| 6165 | return ir_expr_wrap(irb, scope, decl_ref, result_loc); | ||
| 6166 | } | ||
| 6167 | } | ||
| 6168 | |||
| 6169 | if (get_container_scope(node->owner)->any_imports_failed) { | ||
| 6170 | // skip the error message since we had a failing import in this file | ||
| 6171 | // if an import breaks we don't need redundant undeclared identifier errors | ||
| 6172 | return irb->codegen->invalid_inst_src; | ||
| 6173 | } | ||
| 6174 | |||
| 6175 | return ir_build_undeclared_identifier(irb, scope, node, variable_name); | ||
| 6176 | } | ||
| 6177 | |||
| 6178 | static IrInstSrc *ir_gen_array_access(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, | ||
| 6179 | ResultLoc *result_loc) | ||
| 6180 | { | ||
| 6181 | assert(node->type == NodeTypeArrayAccessExpr); | ||
| 6182 | |||
| 6183 | AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr; | ||
| 6184 | IrInstSrc *array_ref_instruction = ir_gen_node_extra(irb, array_ref_node, scope, LValPtr, nullptr); | ||
| 6185 | if (array_ref_instruction == irb->codegen->invalid_inst_src) | ||
| 6186 | return array_ref_instruction; | ||
| 6187 | |||
| 6188 | // Create an usize-typed result location to hold the subscript value, this | ||
| 6189 | // makes it possible for the compiler to infer the subscript expression type | ||
| 6190 | // if needed | ||
| 6191 | IrInstSrc *usize_type_inst = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize); | ||
| 6192 | ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, usize_type_inst, no_result_loc()); | ||
| 6193 | |||
| 6194 | AstNode *subscript_node = node->data.array_access_expr.subscript; | ||
| 6195 | IrInstSrc *subscript_value = ir_gen_node_extra(irb, subscript_node, scope, LValNone, &result_loc_cast->base); | ||
| 6196 | if (subscript_value == irb->codegen->invalid_inst_src) | ||
| 6197 | return irb->codegen->invalid_inst_src; | ||
| 6198 | |||
| 6199 | IrInstSrc *subscript_instruction = ir_build_implicit_cast(irb, scope, subscript_node, subscript_value, result_loc_cast); | ||
| 6200 | |||
| 6201 | IrInstSrc *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction, | ||
| 6202 | subscript_instruction, true, PtrLenSingle, nullptr); | ||
| 6203 | if (lval == LValPtr || lval == LValAssign) | ||
| 6204 | return ptr_instruction; | ||
| 6205 | |||
| 6206 | IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); | ||
| 6207 | return ir_expr_wrap(irb, scope, load_ptr, result_loc); | ||
| 6208 | } | ||
| 6209 | |||
| 6210 | static IrInstSrc *ir_gen_field_access(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 6211 | assert(node->type == NodeTypeFieldAccessExpr); | ||
| 6212 | |||
| 6213 | AstNode *container_ref_node = node->data.field_access_expr.struct_expr; | ||
| 6214 | Buf *field_name = node->data.field_access_expr.field_name; | ||
| 6215 | |||
| 6216 | IrInstSrc *container_ref_instruction = ir_gen_node_extra(irb, container_ref_node, scope, LValPtr, nullptr); | ||
| 6217 | if (container_ref_instruction == irb->codegen->invalid_inst_src) | ||
| 6218 | return container_ref_instruction; | ||
| 6219 | |||
| 6220 | return ir_build_field_ptr(irb, scope, node, container_ref_instruction, field_name, false); | ||
| 6221 | } | ||
| 6222 | |||
| 6223 | static IrInstSrc *ir_gen_overflow_op(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrOverflowOp op) { | ||
| 6224 | assert(node->type == NodeTypeFnCallExpr); | ||
| 6225 | |||
| 6226 | AstNode *type_node = node->data.fn_call_expr.params.at(0); | ||
| 6227 | AstNode *op1_node = node->data.fn_call_expr.params.at(1); | ||
| 6228 | AstNode *op2_node = node->data.fn_call_expr.params.at(2); | ||
| 6229 | AstNode *result_ptr_node = node->data.fn_call_expr.params.at(3); | ||
| 6230 | |||
| 6231 | |||
| 6232 | IrInstSrc *type_value = ir_gen_node(irb, type_node, scope); | ||
| 6233 | if (type_value == irb->codegen->invalid_inst_src) | ||
| 6234 | return irb->codegen->invalid_inst_src; | ||
| 6235 | |||
| 6236 | IrInstSrc *op1 = ir_gen_node(irb, op1_node, scope); | ||
| 6237 | if (op1 == irb->codegen->invalid_inst_src) | ||
| 6238 | return irb->codegen->invalid_inst_src; | ||
| 6239 | |||
| 6240 | IrInstSrc *op2 = ir_gen_node(irb, op2_node, scope); | ||
| 6241 | if (op2 == irb->codegen->invalid_inst_src) | ||
| 6242 | return irb->codegen->invalid_inst_src; | ||
| 6243 | |||
| 6244 | IrInstSrc *result_ptr = ir_gen_node(irb, result_ptr_node, scope); | ||
| 6245 | if (result_ptr == irb->codegen->invalid_inst_src) | ||
| 6246 | return irb->codegen->invalid_inst_src; | ||
| 6247 | |||
| 6248 | return ir_build_overflow_op_src(irb, scope, node, op, type_value, op1, op2, result_ptr); | ||
| 6249 | } | ||
| 6250 | |||
| 6251 | static IrInstSrc *ir_gen_mul_add(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 6252 | assert(node->type == NodeTypeFnCallExpr); | ||
| 6253 | |||
| 6254 | AstNode *type_node = node->data.fn_call_expr.params.at(0); | ||
| 6255 | AstNode *op1_node = node->data.fn_call_expr.params.at(1); | ||
| 6256 | AstNode *op2_node = node->data.fn_call_expr.params.at(2); | ||
| 6257 | AstNode *op3_node = node->data.fn_call_expr.params.at(3); | ||
| 6258 | |||
| 6259 | IrInstSrc *type_value = ir_gen_node(irb, type_node, scope); | ||
| 6260 | if (type_value == irb->codegen->invalid_inst_src) | ||
| 6261 | return irb->codegen->invalid_inst_src; | ||
| 6262 | |||
| 6263 | IrInstSrc *op1 = ir_gen_node(irb, op1_node, scope); | ||
| 6264 | if (op1 == irb->codegen->invalid_inst_src) | ||
| 6265 | return irb->codegen->invalid_inst_src; | ||
| 6266 | |||
| 6267 | IrInstSrc *op2 = ir_gen_node(irb, op2_node, scope); | ||
| 6268 | if (op2 == irb->codegen->invalid_inst_src) | ||
| 6269 | return irb->codegen->invalid_inst_src; | ||
| 6270 | |||
| 6271 | IrInstSrc *op3 = ir_gen_node(irb, op3_node, scope); | ||
| 6272 | if (op3 == irb->codegen->invalid_inst_src) | ||
| 6273 | return irb->codegen->invalid_inst_src; | ||
| 6274 | |||
| 6275 | return ir_build_mul_add_src(irb, scope, node, type_value, op1, op2, op3); | ||
| 6276 | } | ||
| 6277 | |||
| 6278 | static IrInstSrc *ir_gen_this(IrBuilderSrc *irb, Scope *orig_scope, AstNode *node) { | ||
| 6279 | for (Scope *it_scope = orig_scope; it_scope != nullptr; it_scope = it_scope->parent) { | ||
| 6280 | if (it_scope->id == ScopeIdDecls) { | ||
| 6281 | ScopeDecls *decls_scope = (ScopeDecls *)it_scope; | ||
| 6282 | ZigType *container_type = decls_scope->container_type; | ||
| 6283 | if (container_type != nullptr) { | ||
| 6284 | return ir_build_const_type(irb, orig_scope, node, container_type); | ||
| 6285 | } else { | ||
| 6286 | return ir_build_const_import(irb, orig_scope, node, decls_scope->import); | ||
| 6287 | } | ||
| 6288 | } | ||
| 6289 | } | ||
| 6290 | zig_unreachable(); | ||
| 6291 | } | ||
| 6292 | |||
| 6293 | static IrInstSrc *ir_gen_async_call(IrBuilderSrc *irb, Scope *scope, AstNode *await_node, AstNode *call_node, | ||
| 6294 | LVal lval, ResultLoc *result_loc) | ||
| 6295 | { | ||
| 6296 | if (call_node->data.fn_call_expr.params.length != 4) { | ||
| 6297 | add_node_error(irb->codegen, call_node, | ||
| 6298 | buf_sprintf("expected 4 arguments, found %" ZIG_PRI_usize, | ||
| 6299 | call_node->data.fn_call_expr.params.length)); | ||
| 6300 | return irb->codegen->invalid_inst_src; | ||
| 6301 | } | ||
| 6302 | |||
| 6303 | AstNode *bytes_node = call_node->data.fn_call_expr.params.at(0); | ||
| 6304 | IrInstSrc *bytes = ir_gen_node(irb, bytes_node, scope); | ||
| 6305 | if (bytes == irb->codegen->invalid_inst_src) | ||
| 6306 | return bytes; | ||
| 6307 | |||
| 6308 | AstNode *ret_ptr_node = call_node->data.fn_call_expr.params.at(1); | ||
| 6309 | IrInstSrc *ret_ptr = ir_gen_node(irb, ret_ptr_node, scope); | ||
| 6310 | if (ret_ptr == irb->codegen->invalid_inst_src) | ||
| 6311 | return ret_ptr; | ||
| 6312 | |||
| 6313 | AstNode *fn_ref_node = call_node->data.fn_call_expr.params.at(2); | ||
| 6314 | IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); | ||
| 6315 | if (fn_ref == irb->codegen->invalid_inst_src) | ||
| 6316 | return fn_ref; | ||
| 6317 | |||
| 6318 | CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone; | ||
| 6319 | bool is_async_call_builtin = true; | ||
| 6320 | AstNode *args_node = call_node->data.fn_call_expr.params.at(3); | ||
| 6321 | if (args_node->type == NodeTypeContainerInitExpr) { | ||
| 6322 | if (args_node->data.container_init_expr.kind == ContainerInitKindArray || | ||
| 6323 | args_node->data.container_init_expr.entries.length == 0) | ||
| 6324 | { | ||
| 6325 | size_t arg_count = args_node->data.container_init_expr.entries.length; | ||
| 6326 | IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(arg_count); | ||
| 6327 | for (size_t i = 0; i < arg_count; i += 1) { | ||
| 6328 | AstNode *arg_node = args_node->data.container_init_expr.entries.at(i); | ||
| 6329 | IrInstSrc *arg = ir_gen_node(irb, arg_node, scope); | ||
| 6330 | if (arg == irb->codegen->invalid_inst_src) | ||
| 6331 | return arg; | ||
| 6332 | args[i] = arg; | ||
| 6333 | } | ||
| 6334 | |||
| 6335 | IrInstSrc *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args, | ||
| 6336 | ret_ptr, modifier, is_async_call_builtin, bytes, result_loc); | ||
| 6337 | return ir_lval_wrap(irb, scope, call, lval, result_loc); | ||
| 6338 | } else { | ||
| 6339 | exec_add_error_node(irb->codegen, irb->exec, args_node, | ||
| 6340 | buf_sprintf("TODO: @asyncCall with anon struct literal")); | ||
| 6341 | return irb->codegen->invalid_inst_src; | ||
| 6342 | } | ||
| 6343 | } | ||
| 6344 | IrInstSrc *args = ir_gen_node(irb, args_node, scope); | ||
| 6345 | if (args == irb->codegen->invalid_inst_src) | ||
| 6346 | return args; | ||
| 6347 | |||
| 6348 | IrInstSrc *call = ir_build_async_call_extra(irb, scope, call_node, modifier, fn_ref, ret_ptr, bytes, args, result_loc); | ||
| 6349 | return ir_lval_wrap(irb, scope, call, lval, result_loc); | ||
| 6350 | } | ||
| 6351 | |||
| 6352 | static IrInstSrc *ir_gen_fn_call_with_args(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 6353 | AstNode *fn_ref_node, CallModifier modifier, IrInstSrc *options, | ||
| 6354 | AstNode **args_ptr, size_t args_len, LVal lval, ResultLoc *result_loc) | ||
| 6355 | { | ||
| 6356 | IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); | ||
| 6357 | if (fn_ref == irb->codegen->invalid_inst_src) | ||
| 6358 | return fn_ref; | ||
| 6359 | |||
| 6360 | IrInstSrc *fn_type = ir_build_typeof_1(irb, scope, source_node, fn_ref); | ||
| 6361 | |||
| 6362 | IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(args_len); | ||
| 6363 | for (size_t i = 0; i < args_len; i += 1) { | ||
| 6364 | AstNode *arg_node = args_ptr[i]; | ||
| 6365 | |||
| 6366 | IrInstSrc *arg_index = ir_build_const_usize(irb, scope, arg_node, i); | ||
| 6367 | IrInstSrc *arg_type = ir_build_arg_type(irb, scope, source_node, fn_type, arg_index, true); | ||
| 6368 | ResultLoc *no_result = no_result_loc(); | ||
| 6369 | ir_build_reset_result(irb, scope, source_node, no_result); | ||
| 6370 | ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, arg_type, no_result); | ||
| 6371 | |||
| 6372 | IrInstSrc *arg = ir_gen_node_extra(irb, arg_node, scope, LValNone, &result_loc_cast->base); | ||
| 6373 | if (arg == irb->codegen->invalid_inst_src) | ||
| 6374 | return arg; | ||
| 6375 | |||
| 6376 | args[i] = ir_build_implicit_cast(irb, scope, arg_node, arg, result_loc_cast); | ||
| 6377 | } | ||
| 6378 | |||
| 6379 | IrInstSrc *fn_call; | ||
| 6380 | if (options != nullptr) { | ||
| 6381 | fn_call = ir_build_call_args(irb, scope, source_node, options, fn_ref, args, args_len, result_loc); | ||
| 6382 | } else { | ||
| 6383 | fn_call = ir_build_call_src(irb, scope, source_node, nullptr, fn_ref, args_len, args, nullptr, | ||
| 6384 | modifier, false, nullptr, result_loc); | ||
| 6385 | } | ||
| 6386 | return ir_lval_wrap(irb, scope, fn_call, lval, result_loc); | ||
| 6387 | } | ||
| 6388 | |||
| 6389 | static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, | ||
| 6390 | ResultLoc *result_loc) | ||
| 6391 | { | ||
| 6392 | assert(node->type == NodeTypeFnCallExpr); | ||
| 6393 | |||
| 6394 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; | ||
| 6395 | Buf *name = fn_ref_expr->data.symbol_expr.symbol; | ||
| 6396 | auto entry = irb->codegen->builtin_fn_table.maybe_get(name); | ||
| 6397 | |||
| 6398 | if (!entry) { | ||
| 6399 | add_node_error(irb->codegen, node, | ||
| 6400 | buf_sprintf("invalid builtin function: '%s'", buf_ptr(name))); | ||
| 6401 | return irb->codegen->invalid_inst_src; | ||
| 6402 | } | ||
| 6403 | |||
| 6404 | BuiltinFnEntry *builtin_fn = entry->value; | ||
| 6405 | size_t actual_param_count = node->data.fn_call_expr.params.length; | ||
| 6406 | |||
| 6407 | if (builtin_fn->param_count != SIZE_MAX && builtin_fn->param_count != actual_param_count) { | ||
| 6408 | add_node_error(irb->codegen, node, | ||
| 6409 | buf_sprintf("expected %" ZIG_PRI_usize " argument(s), found %" ZIG_PRI_usize, | ||
| 6410 | builtin_fn->param_count, actual_param_count)); | ||
| 6411 | return irb->codegen->invalid_inst_src; | ||
| 6412 | } | ||
| 6413 | |||
| 6414 | switch (builtin_fn->id) { | ||
| 6415 | case BuiltinFnIdInvalid: | ||
| 6416 | zig_unreachable(); | ||
| 6417 | case BuiltinFnIdTypeof: | ||
| 6418 | { | ||
| 6419 | Scope *sub_scope = create_typeof_scope(irb->codegen, node, scope); | ||
| 6420 | |||
| 6421 | size_t arg_count = node->data.fn_call_expr.params.length; | ||
| 6422 | |||
| 6423 | IrInstSrc *type_of; | ||
| 6424 | |||
| 6425 | if (arg_count == 0) { | ||
| 6426 | add_node_error(irb->codegen, node, | ||
| 6427 | buf_sprintf("expected at least 1 argument, found 0")); | ||
| 6428 | return irb->codegen->invalid_inst_src; | ||
| 6429 | } else if (arg_count == 1) { | ||
| 6430 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6431 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, sub_scope); | ||
| 6432 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6433 | return arg0_value; | ||
| 6434 | |||
| 6435 | type_of = ir_build_typeof_1(irb, scope, node, arg0_value); | ||
| 6436 | } else { | ||
| 6437 | IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(arg_count); | ||
| 6438 | for (size_t i = 0; i < arg_count; i += 1) { | ||
| 6439 | AstNode *arg_node = node->data.fn_call_expr.params.at(i); | ||
| 6440 | IrInstSrc *arg = ir_gen_node(irb, arg_node, sub_scope); | ||
| 6441 | if (arg == irb->codegen->invalid_inst_src) | ||
| 6442 | return irb->codegen->invalid_inst_src; | ||
| 6443 | args[i] = arg; | ||
| 6444 | } | ||
| 6445 | |||
| 6446 | type_of = ir_build_typeof_n(irb, scope, node, args, arg_count); | ||
| 6447 | } | ||
| 6448 | return ir_lval_wrap(irb, scope, type_of, lval, result_loc); | ||
| 6449 | } | ||
| 6450 | case BuiltinFnIdSetCold: | ||
| 6451 | { | ||
| 6452 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6453 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6454 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6455 | return arg0_value; | ||
| 6456 | |||
| 6457 | IrInstSrc *set_cold = ir_build_set_cold(irb, scope, node, arg0_value); | ||
| 6458 | return ir_lval_wrap(irb, scope, set_cold, lval, result_loc); | ||
| 6459 | } | ||
| 6460 | case BuiltinFnIdSetRuntimeSafety: | ||
| 6461 | { | ||
| 6462 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6463 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6464 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6465 | return arg0_value; | ||
| 6466 | |||
| 6467 | IrInstSrc *set_safety = ir_build_set_runtime_safety(irb, scope, node, arg0_value); | ||
| 6468 | return ir_lval_wrap(irb, scope, set_safety, lval, result_loc); | ||
| 6469 | } | ||
| 6470 | case BuiltinFnIdSetFloatMode: | ||
| 6471 | { | ||
| 6472 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6473 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6474 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6475 | return arg0_value; | ||
| 6476 | |||
| 6477 | IrInstSrc *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value); | ||
| 6478 | return ir_lval_wrap(irb, scope, set_float_mode, lval, result_loc); | ||
| 6479 | } | ||
| 6480 | case BuiltinFnIdSizeof: | ||
| 6481 | case BuiltinFnIdBitSizeof: | ||
| 6482 | { | ||
| 6483 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6484 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6485 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6486 | return arg0_value; | ||
| 6487 | |||
| 6488 | IrInstSrc *size_of = ir_build_size_of(irb, scope, node, arg0_value, builtin_fn->id == BuiltinFnIdBitSizeof); | ||
| 6489 | return ir_lval_wrap(irb, scope, size_of, lval, result_loc); | ||
| 6490 | } | ||
| 6491 | case BuiltinFnIdImport: | ||
| 6492 | { | ||
| 6493 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6494 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6495 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6496 | return arg0_value; | ||
| 6497 | |||
| 6498 | IrInstSrc *import = ir_build_import(irb, scope, node, arg0_value); | ||
| 6499 | return ir_lval_wrap(irb, scope, import, lval, result_loc); | ||
| 6500 | } | ||
| 6501 | case BuiltinFnIdCImport: | ||
| 6502 | { | ||
| 6503 | IrInstSrc *c_import = ir_build_c_import(irb, scope, node); | ||
| 6504 | return ir_lval_wrap(irb, scope, c_import, lval, result_loc); | ||
| 6505 | } | ||
| 6506 | case BuiltinFnIdCInclude: | ||
| 6507 | { | ||
| 6508 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6509 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6510 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6511 | return arg0_value; | ||
| 6512 | |||
| 6513 | if (!exec_c_import_buf(irb->exec)) { | ||
| 6514 | add_node_error(irb->codegen, node, buf_sprintf("C include valid only inside C import block")); | ||
| 6515 | return irb->codegen->invalid_inst_src; | ||
| 6516 | } | ||
| 6517 | |||
| 6518 | IrInstSrc *c_include = ir_build_c_include(irb, scope, node, arg0_value); | ||
| 6519 | return ir_lval_wrap(irb, scope, c_include, lval, result_loc); | ||
| 6520 | } | ||
| 6521 | case BuiltinFnIdCDefine: | ||
| 6522 | { | ||
| 6523 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6524 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6525 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6526 | return arg0_value; | ||
| 6527 | |||
| 6528 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6529 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6530 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6531 | return arg1_value; | ||
| 6532 | |||
| 6533 | if (!exec_c_import_buf(irb->exec)) { | ||
| 6534 | add_node_error(irb->codegen, node, buf_sprintf("C define valid only inside C import block")); | ||
| 6535 | return irb->codegen->invalid_inst_src; | ||
| 6536 | } | ||
| 6537 | |||
| 6538 | IrInstSrc *c_define = ir_build_c_define(irb, scope, node, arg0_value, arg1_value); | ||
| 6539 | return ir_lval_wrap(irb, scope, c_define, lval, result_loc); | ||
| 6540 | } | ||
| 6541 | case BuiltinFnIdCUndef: | ||
| 6542 | { | ||
| 6543 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6544 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6545 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6546 | return arg0_value; | ||
| 6547 | |||
| 6548 | if (!exec_c_import_buf(irb->exec)) { | ||
| 6549 | add_node_error(irb->codegen, node, buf_sprintf("C undef valid only inside C import block")); | ||
| 6550 | return irb->codegen->invalid_inst_src; | ||
| 6551 | } | ||
| 6552 | |||
| 6553 | IrInstSrc *c_undef = ir_build_c_undef(irb, scope, node, arg0_value); | ||
| 6554 | return ir_lval_wrap(irb, scope, c_undef, lval, result_loc); | ||
| 6555 | } | ||
| 6556 | case BuiltinFnIdCompileErr: | ||
| 6557 | { | ||
| 6558 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6559 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6560 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6561 | return arg0_value; | ||
| 6562 | |||
| 6563 | IrInstSrc *compile_err = ir_build_compile_err(irb, scope, node, arg0_value); | ||
| 6564 | return ir_lval_wrap(irb, scope, compile_err, lval, result_loc); | ||
| 6565 | } | ||
| 6566 | case BuiltinFnIdCompileLog: | ||
| 6567 | { | ||
| 6568 | IrInstSrc **args = heap::c_allocator.allocate<IrInstSrc*>(actual_param_count); | ||
| 6569 | |||
| 6570 | for (size_t i = 0; i < actual_param_count; i += 1) { | ||
| 6571 | AstNode *arg_node = node->data.fn_call_expr.params.at(i); | ||
| 6572 | args[i] = ir_gen_node(irb, arg_node, scope); | ||
| 6573 | if (args[i] == irb->codegen->invalid_inst_src) | ||
| 6574 | return irb->codegen->invalid_inst_src; | ||
| 6575 | } | ||
| 6576 | |||
| 6577 | IrInstSrc *compile_log = ir_build_compile_log(irb, scope, node, actual_param_count, args); | ||
| 6578 | return ir_lval_wrap(irb, scope, compile_log, lval, result_loc); | ||
| 6579 | } | ||
| 6580 | case BuiltinFnIdErrName: | ||
| 6581 | { | ||
| 6582 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6583 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6584 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6585 | return arg0_value; | ||
| 6586 | |||
| 6587 | IrInstSrc *err_name = ir_build_err_name(irb, scope, node, arg0_value); | ||
| 6588 | return ir_lval_wrap(irb, scope, err_name, lval, result_loc); | ||
| 6589 | } | ||
| 6590 | case BuiltinFnIdEmbedFile: | ||
| 6591 | { | ||
| 6592 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6593 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6594 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6595 | return arg0_value; | ||
| 6596 | |||
| 6597 | IrInstSrc *embed_file = ir_build_embed_file(irb, scope, node, arg0_value); | ||
| 6598 | return ir_lval_wrap(irb, scope, embed_file, lval, result_loc); | ||
| 6599 | } | ||
| 6600 | case BuiltinFnIdCmpxchgWeak: | ||
| 6601 | case BuiltinFnIdCmpxchgStrong: | ||
| 6602 | { | ||
| 6603 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6604 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6605 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6606 | return arg0_value; | ||
| 6607 | |||
| 6608 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6609 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6610 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6611 | return arg1_value; | ||
| 6612 | |||
| 6613 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 6614 | IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); | ||
| 6615 | if (arg2_value == irb->codegen->invalid_inst_src) | ||
| 6616 | return arg2_value; | ||
| 6617 | |||
| 6618 | AstNode *arg3_node = node->data.fn_call_expr.params.at(3); | ||
| 6619 | IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); | ||
| 6620 | if (arg3_value == irb->codegen->invalid_inst_src) | ||
| 6621 | return arg3_value; | ||
| 6622 | |||
| 6623 | AstNode *arg4_node = node->data.fn_call_expr.params.at(4); | ||
| 6624 | IrInstSrc *arg4_value = ir_gen_node(irb, arg4_node, scope); | ||
| 6625 | if (arg4_value == irb->codegen->invalid_inst_src) | ||
| 6626 | return arg4_value; | ||
| 6627 | |||
| 6628 | AstNode *arg5_node = node->data.fn_call_expr.params.at(5); | ||
| 6629 | IrInstSrc *arg5_value = ir_gen_node(irb, arg5_node, scope); | ||
| 6630 | if (arg5_value == irb->codegen->invalid_inst_src) | ||
| 6631 | return arg5_value; | ||
| 6632 | |||
| 6633 | IrInstSrc *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value, | ||
| 6634 | arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak), | ||
| 6635 | result_loc); | ||
| 6636 | return ir_lval_wrap(irb, scope, cmpxchg, lval, result_loc); | ||
| 6637 | } | ||
| 6638 | case BuiltinFnIdFence: | ||
| 6639 | { | ||
| 6640 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6641 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6642 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6643 | return arg0_value; | ||
| 6644 | |||
| 6645 | IrInstSrc *fence = ir_build_fence(irb, scope, node, arg0_value); | ||
| 6646 | return ir_lval_wrap(irb, scope, fence, lval, result_loc); | ||
| 6647 | } | ||
| 6648 | case BuiltinFnIdReduce: | ||
| 6649 | { | ||
| 6650 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6651 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6652 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6653 | return arg0_value; | ||
| 6654 | |||
| 6655 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6656 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6657 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6658 | return arg1_value; | ||
| 6659 | |||
| 6660 | IrInstSrc *reduce = ir_build_reduce(irb, scope, node, arg0_value, arg1_value); | ||
| 6661 | return ir_lval_wrap(irb, scope, reduce, lval, result_loc); | ||
| 6662 | } | ||
| 6663 | case BuiltinFnIdDivExact: | ||
| 6664 | { | ||
| 6665 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6666 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6667 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6668 | return arg0_value; | ||
| 6669 | |||
| 6670 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6671 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6672 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6673 | return arg1_value; | ||
| 6674 | |||
| 6675 | IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivExact, arg0_value, arg1_value, true); | ||
| 6676 | return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); | ||
| 6677 | } | ||
| 6678 | case BuiltinFnIdDivTrunc: | ||
| 6679 | { | ||
| 6680 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6681 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6682 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6683 | return arg0_value; | ||
| 6684 | |||
| 6685 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6686 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6687 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6688 | return arg1_value; | ||
| 6689 | |||
| 6690 | IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivTrunc, arg0_value, arg1_value, true); | ||
| 6691 | return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); | ||
| 6692 | } | ||
| 6693 | case BuiltinFnIdDivFloor: | ||
| 6694 | { | ||
| 6695 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6696 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6697 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6698 | return arg0_value; | ||
| 6699 | |||
| 6700 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6701 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6702 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6703 | return arg1_value; | ||
| 6704 | |||
| 6705 | IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpDivFloor, arg0_value, arg1_value, true); | ||
| 6706 | return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); | ||
| 6707 | } | ||
| 6708 | case BuiltinFnIdRem: | ||
| 6709 | { | ||
| 6710 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6711 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6712 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6713 | return arg0_value; | ||
| 6714 | |||
| 6715 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6716 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6717 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6718 | return arg1_value; | ||
| 6719 | |||
| 6720 | IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemRem, arg0_value, arg1_value, true); | ||
| 6721 | return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); | ||
| 6722 | } | ||
| 6723 | case BuiltinFnIdMod: | ||
| 6724 | { | ||
| 6725 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6726 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6727 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6728 | return arg0_value; | ||
| 6729 | |||
| 6730 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6731 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6732 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6733 | return arg1_value; | ||
| 6734 | |||
| 6735 | IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpRemMod, arg0_value, arg1_value, true); | ||
| 6736 | return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); | ||
| 6737 | } | ||
| 6738 | case BuiltinFnIdSqrt: | ||
| 6739 | case BuiltinFnIdSin: | ||
| 6740 | case BuiltinFnIdCos: | ||
| 6741 | case BuiltinFnIdExp: | ||
| 6742 | case BuiltinFnIdExp2: | ||
| 6743 | case BuiltinFnIdLog: | ||
| 6744 | case BuiltinFnIdLog2: | ||
| 6745 | case BuiltinFnIdLog10: | ||
| 6746 | case BuiltinFnIdFabs: | ||
| 6747 | case BuiltinFnIdFloor: | ||
| 6748 | case BuiltinFnIdCeil: | ||
| 6749 | case BuiltinFnIdTrunc: | ||
| 6750 | case BuiltinFnIdNearbyInt: | ||
| 6751 | case BuiltinFnIdRound: | ||
| 6752 | { | ||
| 6753 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6754 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6755 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6756 | return arg0_value; | ||
| 6757 | |||
| 6758 | IrInstSrc *inst = ir_build_float_op_src(irb, scope, node, arg0_value, builtin_fn->id); | ||
| 6759 | return ir_lval_wrap(irb, scope, inst, lval, result_loc); | ||
| 6760 | } | ||
| 6761 | case BuiltinFnIdTruncate: | ||
| 6762 | { | ||
| 6763 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6764 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6765 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6766 | return arg0_value; | ||
| 6767 | |||
| 6768 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6769 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6770 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6771 | return arg1_value; | ||
| 6772 | |||
| 6773 | IrInstSrc *truncate = ir_build_truncate(irb, scope, node, arg0_value, arg1_value); | ||
| 6774 | return ir_lval_wrap(irb, scope, truncate, lval, result_loc); | ||
| 6775 | } | ||
| 6776 | case BuiltinFnIdIntCast: | ||
| 6777 | { | ||
| 6778 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6779 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6780 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6781 | return arg0_value; | ||
| 6782 | |||
| 6783 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6784 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6785 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6786 | return arg1_value; | ||
| 6787 | |||
| 6788 | IrInstSrc *result = ir_build_int_cast(irb, scope, node, arg0_value, arg1_value); | ||
| 6789 | return ir_lval_wrap(irb, scope, result, lval, result_loc); | ||
| 6790 | } | ||
| 6791 | case BuiltinFnIdFloatCast: | ||
| 6792 | { | ||
| 6793 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6794 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6795 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6796 | return arg0_value; | ||
| 6797 | |||
| 6798 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6799 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6800 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6801 | return arg1_value; | ||
| 6802 | |||
| 6803 | IrInstSrc *result = ir_build_float_cast(irb, scope, node, arg0_value, arg1_value); | ||
| 6804 | return ir_lval_wrap(irb, scope, result, lval, result_loc); | ||
| 6805 | } | ||
| 6806 | case BuiltinFnIdErrSetCast: | ||
| 6807 | { | ||
| 6808 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6809 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6810 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6811 | return arg0_value; | ||
| 6812 | |||
| 6813 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6814 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6815 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6816 | return arg1_value; | ||
| 6817 | |||
| 6818 | IrInstSrc *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value); | ||
| 6819 | return ir_lval_wrap(irb, scope, result, lval, result_loc); | ||
| 6820 | } | ||
| 6821 | case BuiltinFnIdIntToFloat: | ||
| 6822 | { | ||
| 6823 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6824 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6825 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6826 | return arg0_value; | ||
| 6827 | |||
| 6828 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6829 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6830 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6831 | return arg1_value; | ||
| 6832 | |||
| 6833 | IrInstSrc *result = ir_build_int_to_float(irb, scope, node, arg0_value, arg1_value); | ||
| 6834 | return ir_lval_wrap(irb, scope, result, lval, result_loc); | ||
| 6835 | } | ||
| 6836 | case BuiltinFnIdFloatToInt: | ||
| 6837 | { | ||
| 6838 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6839 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6840 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6841 | return arg0_value; | ||
| 6842 | |||
| 6843 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6844 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6845 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6846 | return arg1_value; | ||
| 6847 | |||
| 6848 | IrInstSrc *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value); | ||
| 6849 | return ir_lval_wrap(irb, scope, result, lval, result_loc); | ||
| 6850 | } | ||
| 6851 | case BuiltinFnIdErrToInt: | ||
| 6852 | { | ||
| 6853 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6854 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6855 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6856 | return arg0_value; | ||
| 6857 | |||
| 6858 | IrInstSrc *result = ir_build_err_to_int_src(irb, scope, node, arg0_value); | ||
| 6859 | return ir_lval_wrap(irb, scope, result, lval, result_loc); | ||
| 6860 | } | ||
| 6861 | case BuiltinFnIdIntToErr: | ||
| 6862 | { | ||
| 6863 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6864 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6865 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6866 | return arg0_value; | ||
| 6867 | |||
| 6868 | IrInstSrc *result = ir_build_int_to_err_src(irb, scope, node, arg0_value); | ||
| 6869 | return ir_lval_wrap(irb, scope, result, lval, result_loc); | ||
| 6870 | } | ||
| 6871 | case BuiltinFnIdBoolToInt: | ||
| 6872 | { | ||
| 6873 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6874 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6875 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6876 | return arg0_value; | ||
| 6877 | |||
| 6878 | IrInstSrc *result = ir_build_bool_to_int(irb, scope, node, arg0_value); | ||
| 6879 | return ir_lval_wrap(irb, scope, result, lval, result_loc); | ||
| 6880 | } | ||
| 6881 | case BuiltinFnIdVectorType: | ||
| 6882 | { | ||
| 6883 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6884 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6885 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6886 | return arg0_value; | ||
| 6887 | |||
| 6888 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6889 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6890 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6891 | return arg1_value; | ||
| 6892 | |||
| 6893 | IrInstSrc *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value); | ||
| 6894 | return ir_lval_wrap(irb, scope, vector_type, lval, result_loc); | ||
| 6895 | } | ||
| 6896 | case BuiltinFnIdShuffle: | ||
| 6897 | { | ||
| 6898 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6899 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6900 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6901 | return arg0_value; | ||
| 6902 | |||
| 6903 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6904 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6905 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6906 | return arg1_value; | ||
| 6907 | |||
| 6908 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 6909 | IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); | ||
| 6910 | if (arg2_value == irb->codegen->invalid_inst_src) | ||
| 6911 | return arg2_value; | ||
| 6912 | |||
| 6913 | AstNode *arg3_node = node->data.fn_call_expr.params.at(3); | ||
| 6914 | IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); | ||
| 6915 | if (arg3_value == irb->codegen->invalid_inst_src) | ||
| 6916 | return arg3_value; | ||
| 6917 | |||
| 6918 | IrInstSrc *shuffle_vector = ir_build_shuffle_vector(irb, scope, node, | ||
| 6919 | arg0_value, arg1_value, arg2_value, arg3_value); | ||
| 6920 | return ir_lval_wrap(irb, scope, shuffle_vector, lval, result_loc); | ||
| 6921 | } | ||
| 6922 | case BuiltinFnIdSplat: | ||
| 6923 | { | ||
| 6924 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6925 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6926 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6927 | return arg0_value; | ||
| 6928 | |||
| 6929 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6930 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6931 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6932 | return arg1_value; | ||
| 6933 | |||
| 6934 | IrInstSrc *splat = ir_build_splat_src(irb, scope, node, | ||
| 6935 | arg0_value, arg1_value); | ||
| 6936 | return ir_lval_wrap(irb, scope, splat, lval, result_loc); | ||
| 6937 | } | ||
| 6938 | case BuiltinFnIdMemcpy: | ||
| 6939 | { | ||
| 6940 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6941 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6942 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6943 | return arg0_value; | ||
| 6944 | |||
| 6945 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6946 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6947 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6948 | return arg1_value; | ||
| 6949 | |||
| 6950 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 6951 | IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); | ||
| 6952 | if (arg2_value == irb->codegen->invalid_inst_src) | ||
| 6953 | return arg2_value; | ||
| 6954 | |||
| 6955 | IrInstSrc *ir_memcpy = ir_build_memcpy_src(irb, scope, node, arg0_value, arg1_value, arg2_value); | ||
| 6956 | return ir_lval_wrap(irb, scope, ir_memcpy, lval, result_loc); | ||
| 6957 | } | ||
| 6958 | case BuiltinFnIdMemset: | ||
| 6959 | { | ||
| 6960 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6961 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6962 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6963 | return arg0_value; | ||
| 6964 | |||
| 6965 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6966 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6967 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6968 | return arg1_value; | ||
| 6969 | |||
| 6970 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 6971 | IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); | ||
| 6972 | if (arg2_value == irb->codegen->invalid_inst_src) | ||
| 6973 | return arg2_value; | ||
| 6974 | |||
| 6975 | IrInstSrc *ir_memset = ir_build_memset_src(irb, scope, node, arg0_value, arg1_value, arg2_value); | ||
| 6976 | return ir_lval_wrap(irb, scope, ir_memset, lval, result_loc); | ||
| 6977 | } | ||
| 6978 | case BuiltinFnIdWasmMemorySize: | ||
| 6979 | { | ||
| 6980 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6981 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6982 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6983 | return arg0_value; | ||
| 6984 | |||
| 6985 | IrInstSrc *ir_wasm_memory_size = ir_build_wasm_memory_size_src(irb, scope, node, arg0_value); | ||
| 6986 | return ir_lval_wrap(irb, scope, ir_wasm_memory_size, lval, result_loc); | ||
| 6987 | } | ||
| 6988 | case BuiltinFnIdWasmMemoryGrow: | ||
| 6989 | { | ||
| 6990 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 6991 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 6992 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 6993 | return arg0_value; | ||
| 6994 | |||
| 6995 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 6996 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 6997 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 6998 | return arg1_value; | ||
| 6999 | |||
| 7000 | IrInstSrc *ir_wasm_memory_grow = ir_build_wasm_memory_grow_src(irb, scope, node, arg0_value, arg1_value); | ||
| 7001 | return ir_lval_wrap(irb, scope, ir_wasm_memory_grow, lval, result_loc); | ||
| 7002 | } | ||
| 7003 | case BuiltinFnIdField: | ||
| 7004 | { | ||
| 7005 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7006 | IrInstSrc *arg0_value = ir_gen_node_extra(irb, arg0_node, scope, LValPtr, nullptr); | ||
| 7007 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7008 | return arg0_value; | ||
| 7009 | |||
| 7010 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7011 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7012 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7013 | return arg1_value; | ||
| 7014 | |||
| 7015 | IrInstSrc *ptr_instruction = ir_build_field_ptr_instruction(irb, scope, node, | ||
| 7016 | arg0_value, arg1_value, false); | ||
| 7017 | |||
| 7018 | if (lval == LValPtr || lval == LValAssign) | ||
| 7019 | return ptr_instruction; | ||
| 7020 | |||
| 7021 | IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); | ||
| 7022 | return ir_expr_wrap(irb, scope, load_ptr, result_loc); | ||
| 7023 | } | ||
| 7024 | case BuiltinFnIdHasField: | ||
| 7025 | { | ||
| 7026 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7027 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7028 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7029 | return arg0_value; | ||
| 7030 | |||
| 7031 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7032 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7033 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7034 | return arg1_value; | ||
| 7035 | |||
| 7036 | IrInstSrc *type_info = ir_build_has_field(irb, scope, node, arg0_value, arg1_value); | ||
| 7037 | return ir_lval_wrap(irb, scope, type_info, lval, result_loc); | ||
| 7038 | } | ||
| 7039 | case BuiltinFnIdTypeInfo: | ||
| 7040 | { | ||
| 7041 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7042 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7043 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7044 | return arg0_value; | ||
| 7045 | |||
| 7046 | IrInstSrc *type_info = ir_build_type_info(irb, scope, node, arg0_value); | ||
| 7047 | return ir_lval_wrap(irb, scope, type_info, lval, result_loc); | ||
| 7048 | } | ||
| 7049 | case BuiltinFnIdType: | ||
| 7050 | { | ||
| 7051 | AstNode *arg_node = node->data.fn_call_expr.params.at(0); | ||
| 7052 | IrInstSrc *arg = ir_gen_node(irb, arg_node, scope); | ||
| 7053 | if (arg == irb->codegen->invalid_inst_src) | ||
| 7054 | return arg; | ||
| 7055 | |||
| 7056 | IrInstSrc *type = ir_build_type(irb, scope, node, arg); | ||
| 7057 | return ir_lval_wrap(irb, scope, type, lval, result_loc); | ||
| 7058 | } | ||
| 7059 | case BuiltinFnIdBreakpoint: | ||
| 7060 | return ir_lval_wrap(irb, scope, ir_build_breakpoint(irb, scope, node), lval, result_loc); | ||
| 7061 | case BuiltinFnIdReturnAddress: | ||
| 7062 | return ir_lval_wrap(irb, scope, ir_build_return_address_src(irb, scope, node), lval, result_loc); | ||
| 7063 | case BuiltinFnIdFrameAddress: | ||
| 7064 | return ir_lval_wrap(irb, scope, ir_build_frame_address_src(irb, scope, node), lval, result_loc); | ||
| 7065 | case BuiltinFnIdFrameHandle: | ||
| 7066 | if (!irb->exec->fn_entry) { | ||
| 7067 | add_node_error(irb->codegen, node, buf_sprintf("@frame() called outside of function definition")); | ||
| 7068 | return irb->codegen->invalid_inst_src; | ||
| 7069 | } | ||
| 7070 | return ir_lval_wrap(irb, scope, ir_build_handle_src(irb, scope, node), lval, result_loc); | ||
| 7071 | case BuiltinFnIdFrameType: { | ||
| 7072 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7073 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7074 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7075 | return arg0_value; | ||
| 7076 | |||
| 7077 | IrInstSrc *frame_type = ir_build_frame_type(irb, scope, node, arg0_value); | ||
| 7078 | return ir_lval_wrap(irb, scope, frame_type, lval, result_loc); | ||
| 7079 | } | ||
| 7080 | case BuiltinFnIdFrameSize: { | ||
| 7081 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7082 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7083 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7084 | return arg0_value; | ||
| 7085 | |||
| 7086 | IrInstSrc *frame_size = ir_build_frame_size_src(irb, scope, node, arg0_value); | ||
| 7087 | return ir_lval_wrap(irb, scope, frame_size, lval, result_loc); | ||
| 7088 | } | ||
| 7089 | case BuiltinFnIdAlignOf: | ||
| 7090 | { | ||
| 7091 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7092 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7093 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7094 | return arg0_value; | ||
| 7095 | |||
| 7096 | IrInstSrc *align_of = ir_build_align_of(irb, scope, node, arg0_value); | ||
| 7097 | return ir_lval_wrap(irb, scope, align_of, lval, result_loc); | ||
| 7098 | } | ||
| 7099 | case BuiltinFnIdAddWithOverflow: | ||
| 7100 | return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd), lval, result_loc); | ||
| 7101 | case BuiltinFnIdSubWithOverflow: | ||
| 7102 | return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpSub), lval, result_loc); | ||
| 7103 | case BuiltinFnIdMulWithOverflow: | ||
| 7104 | return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpMul), lval, result_loc); | ||
| 7105 | case BuiltinFnIdShlWithOverflow: | ||
| 7106 | return ir_lval_wrap(irb, scope, ir_gen_overflow_op(irb, scope, node, IrOverflowOpShl), lval, result_loc); | ||
| 7107 | case BuiltinFnIdMulAdd: | ||
| 7108 | return ir_lval_wrap(irb, scope, ir_gen_mul_add(irb, scope, node), lval, result_loc); | ||
| 7109 | case BuiltinFnIdTypeName: | ||
| 7110 | { | ||
| 7111 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7112 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7113 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7114 | return arg0_value; | ||
| 7115 | |||
| 7116 | IrInstSrc *type_name = ir_build_type_name(irb, scope, node, arg0_value); | ||
| 7117 | return ir_lval_wrap(irb, scope, type_name, lval, result_loc); | ||
| 7118 | } | ||
| 7119 | case BuiltinFnIdPanic: | ||
| 7120 | { | ||
| 7121 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7122 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7123 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7124 | return arg0_value; | ||
| 7125 | |||
| 7126 | IrInstSrc *panic = ir_build_panic_src(irb, scope, node, arg0_value); | ||
| 7127 | return ir_lval_wrap(irb, scope, panic, lval, result_loc); | ||
| 7128 | } | ||
| 7129 | case BuiltinFnIdPtrCast: | ||
| 7130 | { | ||
| 7131 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7132 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7133 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7134 | return arg0_value; | ||
| 7135 | |||
| 7136 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7137 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7138 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7139 | return arg1_value; | ||
| 7140 | |||
| 7141 | IrInstSrc *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true); | ||
| 7142 | return ir_lval_wrap(irb, scope, ptr_cast, lval, result_loc); | ||
| 7143 | } | ||
| 7144 | case BuiltinFnIdBitCast: | ||
| 7145 | { | ||
| 7146 | AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); | ||
| 7147 | IrInstSrc *dest_type = ir_gen_node(irb, dest_type_node, scope); | ||
| 7148 | if (dest_type == irb->codegen->invalid_inst_src) | ||
| 7149 | return dest_type; | ||
| 7150 | |||
| 7151 | ResultLocBitCast *result_loc_bit_cast = heap::c_allocator.create<ResultLocBitCast>(); | ||
| 7152 | result_loc_bit_cast->base.id = ResultLocIdBitCast; | ||
| 7153 | result_loc_bit_cast->base.source_instruction = dest_type; | ||
| 7154 | result_loc_bit_cast->base.allow_write_through_const = result_loc->allow_write_through_const; | ||
| 7155 | ir_ref_instruction(dest_type, irb->current_basic_block); | ||
| 7156 | result_loc_bit_cast->parent = result_loc; | ||
| 7157 | |||
| 7158 | ir_build_reset_result(irb, scope, node, &result_loc_bit_cast->base); | ||
| 7159 | |||
| 7160 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7161 | IrInstSrc *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone, | ||
| 7162 | &result_loc_bit_cast->base); | ||
| 7163 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7164 | return arg1_value; | ||
| 7165 | |||
| 7166 | IrInstSrc *bitcast = ir_build_bit_cast_src(irb, scope, arg1_node, arg1_value, result_loc_bit_cast); | ||
| 7167 | return ir_lval_wrap(irb, scope, bitcast, lval, result_loc); | ||
| 7168 | } | ||
| 7169 | case BuiltinFnIdAs: | ||
| 7170 | { | ||
| 7171 | AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); | ||
| 7172 | IrInstSrc *dest_type = ir_gen_node(irb, dest_type_node, scope); | ||
| 7173 | if (dest_type == irb->codegen->invalid_inst_src) | ||
| 7174 | return dest_type; | ||
| 7175 | |||
| 7176 | ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, dest_type, result_loc); | ||
| 7177 | |||
| 7178 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7179 | IrInstSrc *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone, | ||
| 7180 | &result_loc_cast->base); | ||
| 7181 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7182 | return arg1_value; | ||
| 7183 | |||
| 7184 | IrInstSrc *result = ir_build_implicit_cast(irb, scope, node, arg1_value, result_loc_cast); | ||
| 7185 | return ir_lval_wrap(irb, scope, result, lval, result_loc); | ||
| 7186 | } | ||
| 7187 | case BuiltinFnIdIntToPtr: | ||
| 7188 | { | ||
| 7189 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7190 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7191 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7192 | return arg0_value; | ||
| 7193 | |||
| 7194 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7195 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7196 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7197 | return arg1_value; | ||
| 7198 | |||
| 7199 | IrInstSrc *int_to_ptr = ir_build_int_to_ptr_src(irb, scope, node, arg0_value, arg1_value); | ||
| 7200 | return ir_lval_wrap(irb, scope, int_to_ptr, lval, result_loc); | ||
| 7201 | } | ||
| 7202 | case BuiltinFnIdPtrToInt: | ||
| 7203 | { | ||
| 7204 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7205 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7206 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7207 | return arg0_value; | ||
| 7208 | |||
| 7209 | IrInstSrc *ptr_to_int = ir_build_ptr_to_int_src(irb, scope, node, arg0_value); | ||
| 7210 | return ir_lval_wrap(irb, scope, ptr_to_int, lval, result_loc); | ||
| 7211 | } | ||
| 7212 | case BuiltinFnIdTagName: | ||
| 7213 | { | ||
| 7214 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7215 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7216 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7217 | return arg0_value; | ||
| 7218 | |||
| 7219 | IrInstSrc *tag_name = ir_build_tag_name_src(irb, scope, node, arg0_value); | ||
| 7220 | return ir_lval_wrap(irb, scope, tag_name, lval, result_loc); | ||
| 7221 | } | ||
| 7222 | case BuiltinFnIdFieldParentPtr: | ||
| 7223 | { | ||
| 7224 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7225 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7226 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7227 | return arg0_value; | ||
| 7228 | |||
| 7229 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7230 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7231 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7232 | return arg1_value; | ||
| 7233 | |||
| 7234 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 7235 | IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); | ||
| 7236 | if (arg2_value == irb->codegen->invalid_inst_src) | ||
| 7237 | return arg2_value; | ||
| 7238 | |||
| 7239 | IrInstSrc *field_parent_ptr = ir_build_field_parent_ptr_src(irb, scope, node, | ||
| 7240 | arg0_value, arg1_value, arg2_value); | ||
| 7241 | return ir_lval_wrap(irb, scope, field_parent_ptr, lval, result_loc); | ||
| 7242 | } | ||
| 7243 | case BuiltinFnIdByteOffsetOf: | ||
| 7244 | { | ||
| 7245 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7246 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7247 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7248 | return arg0_value; | ||
| 7249 | |||
| 7250 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7251 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7252 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7253 | return arg1_value; | ||
| 7254 | |||
| 7255 | IrInstSrc *offset_of = ir_build_byte_offset_of(irb, scope, node, arg0_value, arg1_value); | ||
| 7256 | return ir_lval_wrap(irb, scope, offset_of, lval, result_loc); | ||
| 7257 | } | ||
| 7258 | case BuiltinFnIdBitOffsetOf: | ||
| 7259 | { | ||
| 7260 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7261 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7262 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7263 | return arg0_value; | ||
| 7264 | |||
| 7265 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7266 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7267 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7268 | return arg1_value; | ||
| 7269 | |||
| 7270 | IrInstSrc *offset_of = ir_build_bit_offset_of(irb, scope, node, arg0_value, arg1_value); | ||
| 7271 | return ir_lval_wrap(irb, scope, offset_of, lval, result_loc); | ||
| 7272 | } | ||
| 7273 | case BuiltinFnIdCall: { | ||
| 7274 | // Cast the options parameter to the options type | ||
| 7275 | ZigType *options_type = get_builtin_type(irb->codegen, "CallOptions"); | ||
| 7276 | IrInstSrc *options_type_inst = ir_build_const_type(irb, scope, node, options_type); | ||
| 7277 | ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc()); | ||
| 7278 | |||
| 7279 | AstNode *options_node = node->data.fn_call_expr.params.at(0); | ||
| 7280 | IrInstSrc *options_inner = ir_gen_node_extra(irb, options_node, scope, | ||
| 7281 | LValNone, &result_loc_cast->base); | ||
| 7282 | if (options_inner == irb->codegen->invalid_inst_src) | ||
| 7283 | return options_inner; | ||
| 7284 | IrInstSrc *options = ir_build_implicit_cast(irb, scope, options_node, options_inner, result_loc_cast); | ||
| 7285 | |||
| 7286 | AstNode *fn_ref_node = node->data.fn_call_expr.params.at(1); | ||
| 7287 | AstNode *args_node = node->data.fn_call_expr.params.at(2); | ||
| 7288 | if (args_node->type == NodeTypeContainerInitExpr) { | ||
| 7289 | if (args_node->data.container_init_expr.kind == ContainerInitKindArray || | ||
| 7290 | args_node->data.container_init_expr.entries.length == 0) | ||
| 7291 | { | ||
| 7292 | return ir_gen_fn_call_with_args(irb, scope, node, | ||
| 7293 | fn_ref_node, CallModifierNone, options, | ||
| 7294 | args_node->data.container_init_expr.entries.items, | ||
| 7295 | args_node->data.container_init_expr.entries.length, | ||
| 7296 | lval, result_loc); | ||
| 7297 | } else { | ||
| 7298 | exec_add_error_node(irb->codegen, irb->exec, args_node, | ||
| 7299 | buf_sprintf("TODO: @call with anon struct literal")); | ||
| 7300 | return irb->codegen->invalid_inst_src; | ||
| 7301 | } | ||
| 7302 | } else { | ||
| 7303 | IrInstSrc *fn_ref = ir_gen_node(irb, fn_ref_node, scope); | ||
| 7304 | if (fn_ref == irb->codegen->invalid_inst_src) | ||
| 7305 | return fn_ref; | ||
| 7306 | |||
| 7307 | IrInstSrc *args = ir_gen_node(irb, args_node, scope); | ||
| 7308 | if (args == irb->codegen->invalid_inst_src) | ||
| 7309 | return args; | ||
| 7310 | |||
| 7311 | IrInstSrc *call = ir_build_call_extra(irb, scope, node, options, fn_ref, args, result_loc); | ||
| 7312 | return ir_lval_wrap(irb, scope, call, lval, result_loc); | ||
| 7313 | } | ||
| 7314 | } | ||
| 7315 | case BuiltinFnIdAsyncCall: | ||
| 7316 | return ir_gen_async_call(irb, scope, nullptr, node, lval, result_loc); | ||
| 7317 | case BuiltinFnIdShlExact: | ||
| 7318 | { | ||
| 7319 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7320 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7321 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7322 | return arg0_value; | ||
| 7323 | |||
| 7324 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7325 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7326 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7327 | return arg1_value; | ||
| 7328 | |||
| 7329 | IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftLeftExact, arg0_value, arg1_value, true); | ||
| 7330 | return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); | ||
| 7331 | } | ||
| 7332 | case BuiltinFnIdShrExact: | ||
| 7333 | { | ||
| 7334 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7335 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7336 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7337 | return arg0_value; | ||
| 7338 | |||
| 7339 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7340 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7341 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7342 | return arg1_value; | ||
| 7343 | |||
| 7344 | IrInstSrc *bin_op = ir_build_bin_op(irb, scope, node, IrBinOpBitShiftRightExact, arg0_value, arg1_value, true); | ||
| 7345 | return ir_lval_wrap(irb, scope, bin_op, lval, result_loc); | ||
| 7346 | } | ||
| 7347 | case BuiltinFnIdSetEvalBranchQuota: | ||
| 7348 | { | ||
| 7349 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7350 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7351 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7352 | return arg0_value; | ||
| 7353 | |||
| 7354 | IrInstSrc *set_eval_branch_quota = ir_build_set_eval_branch_quota(irb, scope, node, arg0_value); | ||
| 7355 | return ir_lval_wrap(irb, scope, set_eval_branch_quota, lval, result_loc); | ||
| 7356 | } | ||
| 7357 | case BuiltinFnIdAlignCast: | ||
| 7358 | { | ||
| 7359 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7360 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7361 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7362 | return arg0_value; | ||
| 7363 | |||
| 7364 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7365 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7366 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7367 | return arg1_value; | ||
| 7368 | |||
| 7369 | IrInstSrc *align_cast = ir_build_align_cast_src(irb, scope, node, arg0_value, arg1_value); | ||
| 7370 | return ir_lval_wrap(irb, scope, align_cast, lval, result_loc); | ||
| 7371 | } | ||
| 7372 | case BuiltinFnIdThis: | ||
| 7373 | { | ||
| 7374 | IrInstSrc *this_inst = ir_gen_this(irb, scope, node); | ||
| 7375 | return ir_lval_wrap(irb, scope, this_inst, lval, result_loc); | ||
| 7376 | } | ||
| 7377 | case BuiltinFnIdSetAlignStack: | ||
| 7378 | { | ||
| 7379 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7380 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7381 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7382 | return arg0_value; | ||
| 7383 | |||
| 7384 | IrInstSrc *set_align_stack = ir_build_set_align_stack(irb, scope, node, arg0_value); | ||
| 7385 | return ir_lval_wrap(irb, scope, set_align_stack, lval, result_loc); | ||
| 7386 | } | ||
| 7387 | case BuiltinFnIdExport: | ||
| 7388 | { | ||
| 7389 | // Cast the options parameter to the options type | ||
| 7390 | ZigType *options_type = get_builtin_type(irb->codegen, "ExportOptions"); | ||
| 7391 | IrInstSrc *options_type_inst = ir_build_const_type(irb, scope, node, options_type); | ||
| 7392 | ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc()); | ||
| 7393 | |||
| 7394 | AstNode *target_node = node->data.fn_call_expr.params.at(0); | ||
| 7395 | IrInstSrc *target_value = ir_gen_node(irb, target_node, scope); | ||
| 7396 | if (target_value == irb->codegen->invalid_inst_src) | ||
| 7397 | return target_value; | ||
| 7398 | |||
| 7399 | AstNode *options_node = node->data.fn_call_expr.params.at(1); | ||
| 7400 | IrInstSrc *options_value = ir_gen_node_extra(irb, options_node, | ||
| 7401 | scope, LValNone, &result_loc_cast->base); | ||
| 7402 | if (options_value == irb->codegen->invalid_inst_src) | ||
| 7403 | return options_value; | ||
| 7404 | |||
| 7405 | IrInstSrc *casted_options_value = ir_build_implicit_cast( | ||
| 7406 | irb, scope, options_node, options_value, result_loc_cast); | ||
| 7407 | |||
| 7408 | IrInstSrc *ir_export = ir_build_export(irb, scope, node, target_value, casted_options_value); | ||
| 7409 | return ir_lval_wrap(irb, scope, ir_export, lval, result_loc); | ||
| 7410 | } | ||
| 7411 | case BuiltinFnIdExtern: | ||
| 7412 | { | ||
| 7413 | // Cast the options parameter to the options type | ||
| 7414 | ZigType *options_type = get_builtin_type(irb->codegen, "ExternOptions"); | ||
| 7415 | IrInstSrc *options_type_inst = ir_build_const_type(irb, scope, node, options_type); | ||
| 7416 | ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc()); | ||
| 7417 | |||
| 7418 | AstNode *type_node = node->data.fn_call_expr.params.at(0); | ||
| 7419 | IrInstSrc *type_value = ir_gen_node(irb, type_node, scope); | ||
| 7420 | if (type_value == irb->codegen->invalid_inst_src) | ||
| 7421 | return type_value; | ||
| 7422 | |||
| 7423 | AstNode *options_node = node->data.fn_call_expr.params.at(1); | ||
| 7424 | IrInstSrc *options_value = ir_gen_node_extra(irb, options_node, | ||
| 7425 | scope, LValNone, &result_loc_cast->base); | ||
| 7426 | if (options_value == irb->codegen->invalid_inst_src) | ||
| 7427 | return options_value; | ||
| 7428 | |||
| 7429 | IrInstSrc *casted_options_value = ir_build_implicit_cast( | ||
| 7430 | irb, scope, options_node, options_value, result_loc_cast); | ||
| 7431 | |||
| 7432 | IrInstSrc *ir_extern = ir_build_extern(irb, scope, node, type_value, casted_options_value); | ||
| 7433 | return ir_lval_wrap(irb, scope, ir_extern, lval, result_loc); | ||
| 7434 | } | ||
| 7435 | case BuiltinFnIdErrorReturnTrace: | ||
| 7436 | { | ||
| 7437 | IrInstSrc *error_return_trace = ir_build_error_return_trace_src(irb, scope, node, | ||
| 7438 | IrInstErrorReturnTraceNull); | ||
| 7439 | return ir_lval_wrap(irb, scope, error_return_trace, lval, result_loc); | ||
| 7440 | } | ||
| 7441 | case BuiltinFnIdAtomicRmw: | ||
| 7442 | { | ||
| 7443 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7444 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7445 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7446 | return arg0_value; | ||
| 7447 | |||
| 7448 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7449 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7450 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7451 | return arg1_value; | ||
| 7452 | |||
| 7453 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 7454 | IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); | ||
| 7455 | if (arg2_value == irb->codegen->invalid_inst_src) | ||
| 7456 | return arg2_value; | ||
| 7457 | |||
| 7458 | AstNode *arg3_node = node->data.fn_call_expr.params.at(3); | ||
| 7459 | IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); | ||
| 7460 | if (arg3_value == irb->codegen->invalid_inst_src) | ||
| 7461 | return arg3_value; | ||
| 7462 | |||
| 7463 | AstNode *arg4_node = node->data.fn_call_expr.params.at(4); | ||
| 7464 | IrInstSrc *arg4_value = ir_gen_node(irb, arg4_node, scope); | ||
| 7465 | if (arg4_value == irb->codegen->invalid_inst_src) | ||
| 7466 | return arg4_value; | ||
| 7467 | |||
| 7468 | IrInstSrc *inst = ir_build_atomic_rmw_src(irb, scope, node, | ||
| 7469 | arg0_value, arg1_value, arg2_value, arg3_value, arg4_value); | ||
| 7470 | return ir_lval_wrap(irb, scope, inst, lval, result_loc); | ||
| 7471 | } | ||
| 7472 | case BuiltinFnIdAtomicLoad: | ||
| 7473 | { | ||
| 7474 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7475 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7476 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7477 | return arg0_value; | ||
| 7478 | |||
| 7479 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7480 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7481 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7482 | return arg1_value; | ||
| 7483 | |||
| 7484 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 7485 | IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); | ||
| 7486 | if (arg2_value == irb->codegen->invalid_inst_src) | ||
| 7487 | return arg2_value; | ||
| 7488 | |||
| 7489 | IrInstSrc *inst = ir_build_atomic_load_src(irb, scope, node, arg0_value, arg1_value, arg2_value); | ||
| 7490 | return ir_lval_wrap(irb, scope, inst, lval, result_loc); | ||
| 7491 | } | ||
| 7492 | case BuiltinFnIdAtomicStore: | ||
| 7493 | { | ||
| 7494 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7495 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7496 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7497 | return arg0_value; | ||
| 7498 | |||
| 7499 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7500 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7501 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7502 | return arg1_value; | ||
| 7503 | |||
| 7504 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | ||
| 7505 | IrInstSrc *arg2_value = ir_gen_node(irb, arg2_node, scope); | ||
| 7506 | if (arg2_value == irb->codegen->invalid_inst_src) | ||
| 7507 | return arg2_value; | ||
| 7508 | |||
| 7509 | AstNode *arg3_node = node->data.fn_call_expr.params.at(3); | ||
| 7510 | IrInstSrc *arg3_value = ir_gen_node(irb, arg3_node, scope); | ||
| 7511 | if (arg3_value == irb->codegen->invalid_inst_src) | ||
| 7512 | return arg3_value; | ||
| 7513 | |||
| 7514 | IrInstSrc *inst = ir_build_atomic_store_src(irb, scope, node, arg0_value, arg1_value, | ||
| 7515 | arg2_value, arg3_value); | ||
| 7516 | return ir_lval_wrap(irb, scope, inst, lval, result_loc); | ||
| 7517 | } | ||
| 7518 | case BuiltinFnIdIntToEnum: | ||
| 7519 | { | ||
| 7520 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7521 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7522 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7523 | return arg0_value; | ||
| 7524 | |||
| 7525 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7526 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7527 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7528 | return arg1_value; | ||
| 7529 | |||
| 7530 | IrInstSrc *result = ir_build_int_to_enum_src(irb, scope, node, arg0_value, arg1_value); | ||
| 7531 | return ir_lval_wrap(irb, scope, result, lval, result_loc); | ||
| 7532 | } | ||
| 7533 | case BuiltinFnIdEnumToInt: | ||
| 7534 | { | ||
| 7535 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7536 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7537 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7538 | return arg0_value; | ||
| 7539 | |||
| 7540 | IrInstSrc *result = ir_build_enum_to_int(irb, scope, node, arg0_value); | ||
| 7541 | return ir_lval_wrap(irb, scope, result, lval, result_loc); | ||
| 7542 | } | ||
| 7543 | case BuiltinFnIdCtz: | ||
| 7544 | case BuiltinFnIdPopCount: | ||
| 7545 | case BuiltinFnIdClz: | ||
| 7546 | case BuiltinFnIdBswap: | ||
| 7547 | case BuiltinFnIdBitReverse: | ||
| 7548 | { | ||
| 7549 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7550 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7551 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7552 | return arg0_value; | ||
| 7553 | |||
| 7554 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7555 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7556 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7557 | return arg1_value; | ||
| 7558 | |||
| 7559 | IrInstSrc *result; | ||
| 7560 | switch (builtin_fn->id) { | ||
| 7561 | case BuiltinFnIdCtz: | ||
| 7562 | result = ir_build_ctz(irb, scope, node, arg0_value, arg1_value); | ||
| 7563 | break; | ||
| 7564 | case BuiltinFnIdPopCount: | ||
| 7565 | result = ir_build_pop_count(irb, scope, node, arg0_value, arg1_value); | ||
| 7566 | break; | ||
| 7567 | case BuiltinFnIdClz: | ||
| 7568 | result = ir_build_clz(irb, scope, node, arg0_value, arg1_value); | ||
| 7569 | break; | ||
| 7570 | case BuiltinFnIdBswap: | ||
| 7571 | result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value); | ||
| 7572 | break; | ||
| 7573 | case BuiltinFnIdBitReverse: | ||
| 7574 | result = ir_build_bit_reverse(irb, scope, node, arg0_value, arg1_value); | ||
| 7575 | break; | ||
| 7576 | default: | ||
| 7577 | zig_unreachable(); | ||
| 7578 | } | ||
| 7579 | return ir_lval_wrap(irb, scope, result, lval, result_loc); | ||
| 7580 | } | ||
| 7581 | case BuiltinFnIdHasDecl: | ||
| 7582 | { | ||
| 7583 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | ||
| 7584 | IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); | ||
| 7585 | if (arg0_value == irb->codegen->invalid_inst_src) | ||
| 7586 | return arg0_value; | ||
| 7587 | |||
| 7588 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | ||
| 7589 | IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); | ||
| 7590 | if (arg1_value == irb->codegen->invalid_inst_src) | ||
| 7591 | return arg1_value; | ||
| 7592 | |||
| 7593 | IrInstSrc *has_decl = ir_build_has_decl(irb, scope, node, arg0_value, arg1_value); | ||
| 7594 | return ir_lval_wrap(irb, scope, has_decl, lval, result_loc); | ||
| 7595 | } | ||
| 7596 | case BuiltinFnIdUnionInit: | ||
| 7597 | { | ||
| 7598 | AstNode *union_type_node = node->data.fn_call_expr.params.at(0); | ||
| 7599 | IrInstSrc *union_type_inst = ir_gen_node(irb, union_type_node, scope); | ||
| 7600 | if (union_type_inst == irb->codegen->invalid_inst_src) | ||
| 7601 | return union_type_inst; | ||
| 7602 | |||
| 7603 | AstNode *name_node = node->data.fn_call_expr.params.at(1); | ||
| 7604 | IrInstSrc *name_inst = ir_gen_node(irb, name_node, scope); | ||
| 7605 | if (name_inst == irb->codegen->invalid_inst_src) | ||
| 7606 | return name_inst; | ||
| 7607 | |||
| 7608 | AstNode *init_node = node->data.fn_call_expr.params.at(2); | ||
| 7609 | |||
| 7610 | return ir_gen_union_init_expr(irb, scope, node, union_type_inst, name_inst, init_node, | ||
| 7611 | lval, result_loc); | ||
| 7612 | } | ||
| 7613 | case BuiltinFnIdSrc: | ||
| 7614 | { | ||
| 7615 | IrInstSrc *src_inst = ir_build_src(irb, scope, node); | ||
| 7616 | return ir_lval_wrap(irb, scope, src_inst, lval, result_loc); | ||
| 7617 | } | ||
| 7618 | } | ||
| 7619 | zig_unreachable(); | ||
| 7620 | } | ||
| 7621 | |||
| 7622 | static ScopeNoSuspend *get_scope_nosuspend(Scope *scope) { | ||
| 7623 | while (scope) { | ||
| 7624 | if (scope->id == ScopeIdNoSuspend) | ||
| 7625 | return (ScopeNoSuspend *)scope; | ||
| 7626 | if (scope->id == ScopeIdFnDef) | ||
| 7627 | return nullptr; | ||
| 7628 | |||
| 7629 | scope = scope->parent; | ||
| 7630 | } | ||
| 7631 | return nullptr; | ||
| 7632 | } | ||
| 7633 | |||
| 7634 | static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, | ||
| 7635 | ResultLoc *result_loc) | ||
| 7636 | { | ||
| 7637 | assert(node->type == NodeTypeFnCallExpr); | ||
| 7638 | |||
| 7639 | if (node->data.fn_call_expr.modifier == CallModifierBuiltin) | ||
| 7640 | return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc); | ||
| 7641 | |||
| 7642 | bool is_nosuspend = get_scope_nosuspend(scope) != nullptr; | ||
| 7643 | CallModifier modifier = node->data.fn_call_expr.modifier; | ||
| 7644 | if (is_nosuspend && modifier != CallModifierAsync) { | ||
| 7645 | modifier = CallModifierNoSuspend; | ||
| 7646 | } | ||
| 7647 | |||
| 7648 | AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; | ||
| 7649 | return ir_gen_fn_call_with_args(irb, scope, node, fn_ref_node, modifier, | ||
| 7650 | nullptr, node->data.fn_call_expr.params.items, node->data.fn_call_expr.params.length, lval, result_loc); | ||
| 7651 | } | ||
| 7652 | |||
| 7653 | static IrInstSrc *ir_gen_if_bool_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, | ||
| 7654 | ResultLoc *result_loc) | ||
| 7655 | { | ||
| 7656 | assert(node->type == NodeTypeIfBoolExpr); | ||
| 7657 | |||
| 7658 | IrInstSrc *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope); | ||
| 7659 | if (condition == irb->codegen->invalid_inst_src) | ||
| 7660 | return irb->codegen->invalid_inst_src; | ||
| 7661 | |||
| 7662 | IrInstSrc *is_comptime; | ||
| 7663 | if (ir_should_inline(irb->exec, scope)) { | ||
| 7664 | is_comptime = ir_build_const_bool(irb, scope, node, true); | ||
| 7665 | } else { | ||
| 7666 | is_comptime = ir_build_test_comptime(irb, scope, node, condition); | ||
| 7667 | } | ||
| 7668 | |||
| 7669 | AstNode *then_node = node->data.if_bool_expr.then_block; | ||
| 7670 | AstNode *else_node = node->data.if_bool_expr.else_node; | ||
| 7671 | |||
| 7672 | IrBasicBlockSrc *then_block = ir_create_basic_block(irb, scope, "Then"); | ||
| 7673 | IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "Else"); | ||
| 7674 | IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "EndIf"); | ||
| 7675 | |||
| 7676 | IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, condition, | ||
| 7677 | then_block, else_block, is_comptime); | ||
| 7678 | ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, | ||
| 7679 | result_loc, is_comptime); | ||
| 7680 | |||
| 7681 | ir_set_cursor_at_end_and_append_block(irb, then_block); | ||
| 7682 | |||
| 7683 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); | ||
| 7684 | IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, subexpr_scope, lval, | ||
| 7685 | &peer_parent->peers.at(0)->base); | ||
| 7686 | if (then_expr_result == irb->codegen->invalid_inst_src) | ||
| 7687 | return irb->codegen->invalid_inst_src; | ||
| 7688 | IrBasicBlockSrc *after_then_block = irb->current_basic_block; | ||
| 7689 | if (!instr_is_unreachable(then_expr_result)) | ||
| 7690 | ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); | ||
| 7691 | |||
| 7692 | ir_set_cursor_at_end_and_append_block(irb, else_block); | ||
| 7693 | IrInstSrc *else_expr_result; | ||
| 7694 | if (else_node) { | ||
| 7695 | else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); | ||
| 7696 | if (else_expr_result == irb->codegen->invalid_inst_src) | ||
| 7697 | return irb->codegen->invalid_inst_src; | ||
| 7698 | } else { | ||
| 7699 | else_expr_result = ir_build_const_void(irb, scope, node); | ||
| 7700 | ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); | ||
| 7701 | } | ||
| 7702 | IrBasicBlockSrc *after_else_block = irb->current_basic_block; | ||
| 7703 | if (!instr_is_unreachable(else_expr_result)) | ||
| 7704 | ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); | ||
| 7705 | |||
| 7706 | ir_set_cursor_at_end_and_append_block(irb, endif_block); | ||
| 7707 | IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2); | ||
| 7708 | incoming_values[0] = then_expr_result; | ||
| 7709 | incoming_values[1] = else_expr_result; | ||
| 7710 | IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate<IrBasicBlockSrc *>(2); | ||
| 7711 | incoming_blocks[0] = after_then_block; | ||
| 7712 | incoming_blocks[1] = after_else_block; | ||
| 7713 | |||
| 7714 | IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); | ||
| 7715 | return ir_expr_wrap(irb, scope, phi, result_loc); | ||
| 7716 | } | ||
| 7717 | |||
| 7718 | static IrInstSrc *ir_gen_prefix_op_id_lval(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) { | ||
| 7719 | assert(node->type == NodeTypePrefixOpExpr); | ||
| 7720 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | ||
| 7721 | |||
| 7722 | IrInstSrc *value = ir_gen_node_extra(irb, expr_node, scope, lval, nullptr); | ||
| 7723 | if (value == irb->codegen->invalid_inst_src) | ||
| 7724 | return value; | ||
| 7725 | |||
| 7726 | return ir_build_un_op(irb, scope, node, op_id, value); | ||
| 7727 | } | ||
| 7728 | |||
| 7729 | static IrInstSrc *ir_gen_prefix_op_id(IrBuilderSrc *irb, Scope *scope, AstNode *node, IrUnOp op_id) { | ||
| 7730 | return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValNone); | ||
| 7731 | } | ||
| 7732 | |||
| 7733 | static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc) { | ||
| 7734 | if (inst == irb->codegen->invalid_inst_src) return inst; | ||
| 7735 | ir_build_end_expr(irb, scope, inst->base.source_node, inst, result_loc); | ||
| 7736 | return inst; | ||
| 7737 | } | ||
| 7738 | |||
| 7739 | static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, | ||
| 7740 | ResultLoc *result_loc) | ||
| 7741 | { | ||
| 7742 | // This logic must be kept in sync with | ||
| 7743 | // [STMT_EXPR_TEST_THING] <--- (search this token) | ||
| 7744 | if (value == irb->codegen->invalid_inst_src || | ||
| 7745 | instr_is_unreachable(value) || | ||
| 7746 | value->base.source_node->type == NodeTypeDefer || | ||
| 7747 | value->id == IrInstSrcIdDeclVar) | ||
| 7748 | { | ||
| 7749 | return value; | ||
| 7750 | } | ||
| 7751 | |||
| 7752 | assert(lval != LValAssign); | ||
| 7753 | if (lval == LValPtr) { | ||
| 7754 | // We needed a pointer to a value, but we got a value. So we create | ||
| 7755 | // an instruction which just makes a pointer of it. | ||
| 7756 | return ir_build_ref_src(irb, scope, value->base.source_node, value); | ||
| 7757 | } else if (result_loc != nullptr) { | ||
| 7758 | return ir_expr_wrap(irb, scope, value, result_loc); | ||
| 7759 | } else { | ||
| 7760 | return value; | ||
| 7761 | } | ||
| 7762 | |||
| 7763 | } | ||
| 7764 | |||
| 7765 | static PtrLen star_token_to_ptr_len(TokenId token_id) { | ||
| 7766 | switch (token_id) { | ||
| 7767 | case TokenIdStar: | ||
| 7768 | case TokenIdStarStar: | ||
| 7769 | return PtrLenSingle; | ||
| 7770 | case TokenIdLBracket: | ||
| 7771 | return PtrLenUnknown; | ||
| 7772 | case TokenIdSymbol: | ||
| 7773 | return PtrLenC; | ||
| 7774 | default: | ||
| 7775 | zig_unreachable(); | ||
| 7776 | } | ||
| 7777 | } | ||
| 7778 | |||
| 7779 | static IrInstSrc *ir_gen_pointer_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 7780 | assert(node->type == NodeTypePointerType); | ||
| 7781 | |||
| 7782 | PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id); | ||
| 7783 | |||
| 7784 | bool is_const = node->data.pointer_type.is_const; | ||
| 7785 | bool is_volatile = node->data.pointer_type.is_volatile; | ||
| 7786 | bool is_allow_zero = node->data.pointer_type.allow_zero_token != nullptr; | ||
| 7787 | AstNode *sentinel_expr = node->data.pointer_type.sentinel; | ||
| 7788 | AstNode *expr_node = node->data.pointer_type.op_expr; | ||
| 7789 | AstNode *align_expr = node->data.pointer_type.align_expr; | ||
| 7790 | |||
| 7791 | IrInstSrc *sentinel; | ||
| 7792 | if (sentinel_expr != nullptr) { | ||
| 7793 | sentinel = ir_gen_node(irb, sentinel_expr, scope); | ||
| 7794 | if (sentinel == irb->codegen->invalid_inst_src) | ||
| 7795 | return sentinel; | ||
| 7796 | } else { | ||
| 7797 | sentinel = nullptr; | ||
| 7798 | } | ||
| 7799 | |||
| 7800 | IrInstSrc *align_value; | ||
| 7801 | if (align_expr != nullptr) { | ||
| 7802 | align_value = ir_gen_node(irb, align_expr, scope); | ||
| 7803 | if (align_value == irb->codegen->invalid_inst_src) | ||
| 7804 | return align_value; | ||
| 7805 | } else { | ||
| 7806 | align_value = nullptr; | ||
| 7807 | } | ||
| 7808 | |||
| 7809 | IrInstSrc *child_type = ir_gen_node(irb, expr_node, scope); | ||
| 7810 | if (child_type == irb->codegen->invalid_inst_src) | ||
| 7811 | return child_type; | ||
| 7812 | |||
| 7813 | uint32_t bit_offset_start = 0; | ||
| 7814 | if (node->data.pointer_type.bit_offset_start != nullptr) { | ||
| 7815 | if (!bigint_fits_in_bits(node->data.pointer_type.bit_offset_start, 32, false)) { | ||
| 7816 | Buf *val_buf = buf_alloc(); | ||
| 7817 | bigint_append_buf(val_buf, node->data.pointer_type.bit_offset_start, 10); | ||
| 7818 | exec_add_error_node(irb->codegen, irb->exec, node, | ||
| 7819 | buf_sprintf("value %s too large for u32 bit offset", buf_ptr(val_buf))); | ||
| 7820 | return irb->codegen->invalid_inst_src; | ||
| 7821 | } | ||
| 7822 | bit_offset_start = bigint_as_u32(node->data.pointer_type.bit_offset_start); | ||
| 7823 | } | ||
| 7824 | |||
| 7825 | uint32_t host_int_bytes = 0; | ||
| 7826 | if (node->data.pointer_type.host_int_bytes != nullptr) { | ||
| 7827 | if (!bigint_fits_in_bits(node->data.pointer_type.host_int_bytes, 32, false)) { | ||
| 7828 | Buf *val_buf = buf_alloc(); | ||
| 7829 | bigint_append_buf(val_buf, node->data.pointer_type.host_int_bytes, 10); | ||
| 7830 | exec_add_error_node(irb->codegen, irb->exec, node, | ||
| 7831 | buf_sprintf("value %s too large for u32 byte count", buf_ptr(val_buf))); | ||
| 7832 | return irb->codegen->invalid_inst_src; | ||
| 7833 | } | ||
| 7834 | host_int_bytes = bigint_as_u32(node->data.pointer_type.host_int_bytes); | ||
| 7835 | } | ||
| 7836 | |||
| 7837 | if (host_int_bytes != 0 && bit_offset_start >= host_int_bytes * 8) { | ||
| 7838 | exec_add_error_node(irb->codegen, irb->exec, node, | ||
| 7839 | buf_sprintf("bit offset starts after end of host integer")); | ||
| 7840 | return irb->codegen->invalid_inst_src; | ||
| 7841 | } | ||
| 7842 | |||
| 7843 | return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile, | ||
| 7844 | ptr_len, sentinel, align_value, bit_offset_start, host_int_bytes, is_allow_zero); | ||
| 7845 | } | ||
| 7846 | |||
| 7847 | static IrInstSrc *ir_gen_catch_unreachable(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 7848 | AstNode *expr_node, LVal lval, ResultLoc *result_loc) | ||
| 7849 | { | ||
| 7850 | IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); | ||
| 7851 | if (err_union_ptr == irb->codegen->invalid_inst_src) | ||
| 7852 | return irb->codegen->invalid_inst_src; | ||
| 7853 | |||
| 7854 | IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, scope, source_node, err_union_ptr, true, false); | ||
| 7855 | if (payload_ptr == irb->codegen->invalid_inst_src) | ||
| 7856 | return irb->codegen->invalid_inst_src; | ||
| 7857 | |||
| 7858 | if (lval == LValPtr) | ||
| 7859 | return payload_ptr; | ||
| 7860 | |||
| 7861 | IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, source_node, payload_ptr); | ||
| 7862 | return ir_expr_wrap(irb, scope, load_ptr, result_loc); | ||
| 7863 | } | ||
| 7864 | |||
| 7865 | static IrInstSrc *ir_gen_bool_not(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 7866 | assert(node->type == NodeTypePrefixOpExpr); | ||
| 7867 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | ||
| 7868 | |||
| 7869 | IrInstSrc *value = ir_gen_node(irb, expr_node, scope); | ||
| 7870 | if (value == irb->codegen->invalid_inst_src) | ||
| 7871 | return irb->codegen->invalid_inst_src; | ||
| 7872 | |||
| 7873 | return ir_build_bool_not(irb, scope, node, value); | ||
| 7874 | } | ||
| 7875 | |||
| 7876 | static IrInstSrc *ir_gen_prefix_op_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, | ||
| 7877 | ResultLoc *result_loc) | ||
| 7878 | { | ||
| 7879 | assert(node->type == NodeTypePrefixOpExpr); | ||
| 7880 | |||
| 7881 | PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op; | ||
| 7882 | |||
| 7883 | switch (prefix_op) { | ||
| 7884 | case PrefixOpInvalid: | ||
| 7885 | zig_unreachable(); | ||
| 7886 | case PrefixOpBoolNot: | ||
| 7887 | return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval, result_loc); | ||
| 7888 | case PrefixOpBinNot: | ||
| 7889 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot), lval, result_loc); | ||
| 7890 | case PrefixOpNegation: | ||
| 7891 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval, result_loc); | ||
| 7892 | case PrefixOpNegationWrap: | ||
| 7893 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval, result_loc); | ||
| 7894 | case PrefixOpOptional: | ||
| 7895 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpOptional), lval, result_loc); | ||
| 7896 | case PrefixOpAddrOf: { | ||
| 7897 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | ||
| 7898 | return ir_lval_wrap(irb, scope, ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr), lval, result_loc); | ||
| 7899 | } | ||
| 7900 | } | ||
| 7901 | zig_unreachable(); | ||
| 7902 | } | ||
| 7903 | |||
| 7904 | static IrInstSrc *ir_gen_union_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | ||
| 7905 | IrInstSrc *union_type, IrInstSrc *field_name, AstNode *expr_node, | ||
| 7906 | LVal lval, ResultLoc *parent_result_loc) | ||
| 7907 | { | ||
| 7908 | IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, source_node, parent_result_loc, union_type); | ||
| 7909 | IrInstSrc *field_ptr = ir_build_field_ptr_instruction(irb, scope, source_node, container_ptr, | ||
| 7910 | field_name, true); | ||
| 7911 | |||
| 7912 | ResultLocInstruction *result_loc_inst = heap::c_allocator.create<ResultLocInstruction>(); | ||
| 7913 | result_loc_inst->base.id = ResultLocIdInstruction; | ||
| 7914 | result_loc_inst->base.source_instruction = field_ptr; | ||
| 7915 | ir_ref_instruction(field_ptr, irb->current_basic_block); | ||
| 7916 | ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); | ||
| 7917 | |||
| 7918 | IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, | ||
| 7919 | &result_loc_inst->base); | ||
| 7920 | if (expr_value == irb->codegen->invalid_inst_src) | ||
| 7921 | return expr_value; | ||
| 7922 | |||
| 7923 | IrInstSrc *init_union = ir_build_union_init_named_field(irb, scope, source_node, union_type, | ||
| 7924 | field_name, field_ptr, container_ptr); | ||
| 7925 | |||
| 7926 | return ir_lval_wrap(irb, scope, init_union, lval, parent_result_loc); | ||
| 7927 | } | ||
| 7928 | |||
| 7929 | static IrInstSrc *ir_gen_container_init_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, | ||
| 7930 | ResultLoc *parent_result_loc) | ||
| 7931 | { | ||
| 7932 | assert(node->type == NodeTypeContainerInitExpr); | ||
| 7933 | |||
| 7934 | AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr; | ||
| 7935 | ContainerInitKind kind = container_init_expr->kind; | ||
| 7936 | |||
| 7937 | ResultLocCast *result_loc_cast = nullptr; | ||
| 7938 | ResultLoc *child_result_loc; | ||
| 7939 | AstNode *init_array_type_source_node; | ||
| 7940 | if (container_init_expr->type != nullptr) { | ||
| 7941 | IrInstSrc *container_type; | ||
| 7942 | if (container_init_expr->type->type == NodeTypeInferredArrayType) { | ||
| 7943 | if (kind == ContainerInitKindStruct) { | ||
| 7944 | add_node_error(irb->codegen, container_init_expr->type, | ||
| 7945 | buf_sprintf("initializing array with struct syntax")); | ||
| 7946 | return irb->codegen->invalid_inst_src; | ||
| 7947 | } | ||
| 7948 | IrInstSrc *sentinel; | ||
| 7949 | if (container_init_expr->type->data.inferred_array_type.sentinel != nullptr) { | ||
| 7950 | sentinel = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.sentinel, scope); | ||
| 7951 | if (sentinel == irb->codegen->invalid_inst_src) | ||
| 7952 | return sentinel; | ||
| 7953 | } else { | ||
| 7954 | sentinel = nullptr; | ||
| 7955 | } | ||
| 7956 | |||
| 7957 | IrInstSrc *elem_type = ir_gen_node(irb, | ||
| 7958 | container_init_expr->type->data.inferred_array_type.child_type, scope); | ||
| 7959 | if (elem_type == irb->codegen->invalid_inst_src) | ||
| 7960 | return elem_type; | ||
| 7961 | size_t item_count = container_init_expr->entries.length; | ||
| 7962 | IrInstSrc *item_count_inst = ir_build_const_usize(irb, scope, node, item_count); | ||
| 7963 | container_type = ir_build_array_type(irb, scope, node, item_count_inst, sentinel, elem_type); | ||
| 7964 | } else { | ||
| 7965 | container_type = ir_gen_node(irb, container_init_expr->type, scope); | ||
| 7966 | if (container_type == irb->codegen->invalid_inst_src) | ||
| 7967 | return container_type; | ||
| 7968 | } | ||
| 7969 | |||
| 7970 | result_loc_cast = ir_build_cast_result_loc(irb, container_type, parent_result_loc); | ||
| 7971 | child_result_loc = &result_loc_cast->base; | ||
| 7972 | init_array_type_source_node = container_type->base.source_node; | ||
| 7973 | } else { | ||
| 7974 | child_result_loc = parent_result_loc; | ||
| 7975 | if (parent_result_loc->source_instruction != nullptr) { | ||
| 7976 | init_array_type_source_node = parent_result_loc->source_instruction->base.source_node; | ||
| 7977 | } else { | ||
| 7978 | init_array_type_source_node = node; | ||
| 7979 | } | ||
| 7980 | } | ||
| 7981 | |||
| 7982 | switch (kind) { | ||
| 7983 | case ContainerInitKindStruct: { | ||
| 7984 | IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, | ||
| 7985 | nullptr); | ||
| 7986 | |||
| 7987 | size_t field_count = container_init_expr->entries.length; | ||
| 7988 | IrInstSrcContainerInitFieldsField *fields = heap::c_allocator.allocate<IrInstSrcContainerInitFieldsField>(field_count); | ||
| 7989 | for (size_t i = 0; i < field_count; i += 1) { | ||
| 7990 | AstNode *entry_node = container_init_expr->entries.at(i); | ||
| 7991 | assert(entry_node->type == NodeTypeStructValueField); | ||
| 7992 | |||
| 7993 | Buf *name = entry_node->data.struct_val_field.name; | ||
| 7994 | AstNode *expr_node = entry_node->data.struct_val_field.expr; | ||
| 7995 | |||
| 7996 | IrInstSrc *field_ptr = ir_build_field_ptr(irb, scope, entry_node, container_ptr, name, true); | ||
| 7997 | ResultLocInstruction *result_loc_inst = heap::c_allocator.create<ResultLocInstruction>(); | ||
| 7998 | result_loc_inst->base.id = ResultLocIdInstruction; | ||
| 7999 | result_loc_inst->base.source_instruction = field_ptr; | ||
| 8000 | result_loc_inst->base.allow_write_through_const = true; | ||
| 8001 | ir_ref_instruction(field_ptr, irb->current_basic_block); | ||
| 8002 | ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); | ||
| 8003 | |||
| 8004 | IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, | ||
| 8005 | &result_loc_inst->base); | ||
| 8006 | if (expr_value == irb->codegen->invalid_inst_src) | ||
| 8007 | return expr_value; | ||
| 8008 | |||
| 8009 | fields[i].name = name; | ||
| 8010 | fields[i].source_node = entry_node; | ||
| 8011 | fields[i].result_loc = field_ptr; | ||
| 8012 | } | ||
| 8013 | IrInstSrc *result = ir_build_container_init_fields(irb, scope, node, field_count, | ||
| 8014 | fields, container_ptr); | ||
| 8015 | |||
| 8016 | if (result_loc_cast != nullptr) { | ||
| 8017 | result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast); | ||
| 8018 | } | ||
| 8019 | return ir_lval_wrap(irb, scope, result, lval, parent_result_loc); | ||
| 8020 | } | ||
| 8021 | case ContainerInitKindArray: { | ||
| 8022 | size_t item_count = container_init_expr->entries.length; | ||
| 8023 | |||
| 8024 | IrInstSrc *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, | ||
| 8025 | nullptr); | ||
| 8026 | |||
| 8027 | IrInstSrc **result_locs = heap::c_allocator.allocate<IrInstSrc *>(item_count); | ||
| 8028 | for (size_t i = 0; i < item_count; i += 1) { | ||
| 8029 | AstNode *expr_node = container_init_expr->entries.at(i); | ||
| 8030 | |||
| 8031 | IrInstSrc *elem_index = ir_build_const_usize(irb, scope, expr_node, i); | ||
| 8032 | IrInstSrc *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, | ||
| 8033 | elem_index, false, PtrLenSingle, init_array_type_source_node); | ||
| 8034 | ResultLocInstruction *result_loc_inst = heap::c_allocator.create<ResultLocInstruction>(); | ||
| 8035 | result_loc_inst->base.id = ResultLocIdInstruction; | ||
| 8036 | result_loc_inst->base.source_instruction = elem_ptr; | ||
| 8037 | result_loc_inst->base.allow_write_through_const = true; | ||
| 8038 | ir_ref_instruction(elem_ptr, irb->current_basic_block); | ||
| 8039 | ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); | ||
| 8040 | |||
| 8041 | IrInstSrc *expr_value = ir_gen_node_extra(irb, expr_node, scope, LValNone, | ||
| 8042 | &result_loc_inst->base); | ||
| 8043 | if (expr_value == irb->codegen->invalid_inst_src) | ||
| 8044 | return expr_value; | ||
| 8045 | |||
| 8046 | result_locs[i] = elem_ptr; | ||
| 8047 | } | ||
| 8048 | IrInstSrc *result = ir_build_container_init_list(irb, scope, node, item_count, | ||
| 8049 | result_locs, container_ptr, init_array_type_source_node); | ||
| 8050 | if (result_loc_cast != nullptr) { | ||
| 8051 | result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast); | ||
| 8052 | } | ||
| 8053 | return ir_lval_wrap(irb, scope, result, lval, parent_result_loc); | ||
| 8054 | } | ||
| 8055 | } | ||
| 8056 | zig_unreachable(); | ||
| 8057 | } | ||
| 8058 | |||
| 8059 | static ResultLocVar *ir_build_var_result_loc(IrBuilderSrc *irb, IrInstSrc *alloca, ZigVar *var) { | ||
| 8060 | ResultLocVar *result_loc_var = heap::c_allocator.create<ResultLocVar>(); | ||
| 8061 | result_loc_var->base.id = ResultLocIdVar; | ||
| 8062 | result_loc_var->base.source_instruction = alloca; | ||
| 8063 | result_loc_var->base.allow_write_through_const = true; | ||
| 8064 | result_loc_var->var = var; | ||
| 8065 | |||
| 8066 | ir_build_reset_result(irb, alloca->base.scope, alloca->base.source_node, &result_loc_var->base); | ||
| 8067 | |||
| 8068 | return result_loc_var; | ||
| 8069 | } | ||
| 8070 | |||
| 8071 | static ResultLocCast *ir_build_cast_result_loc(IrBuilderSrc *irb, IrInstSrc *dest_type, | ||
| 8072 | ResultLoc *parent_result_loc) | ||
| 8073 | { | ||
| 8074 | ResultLocCast *result_loc_cast = heap::c_allocator.create<ResultLocCast>(); | ||
| 8075 | result_loc_cast->base.id = ResultLocIdCast; | ||
| 8076 | result_loc_cast->base.source_instruction = dest_type; | ||
| 8077 | result_loc_cast->base.allow_write_through_const = parent_result_loc->allow_write_through_const; | ||
| 8078 | ir_ref_instruction(dest_type, irb->current_basic_block); | ||
| 8079 | result_loc_cast->parent = parent_result_loc; | ||
| 8080 | |||
| 8081 | ir_build_reset_result(irb, dest_type->base.scope, dest_type->base.source_node, &result_loc_cast->base); | ||
| 8082 | |||
| 8083 | return result_loc_cast; | ||
| 8084 | } | ||
| 8085 | |||
| 8086 | static void build_decl_var_and_init(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var, | ||
| 8087 | IrInstSrc *init, const char *name_hint, IrInstSrc *is_comptime) | ||
| 8088 | { | ||
| 8089 | IrInstSrc *alloca = ir_build_alloca_src(irb, scope, source_node, nullptr, name_hint, is_comptime); | ||
| 8090 | ResultLocVar *var_result_loc = ir_build_var_result_loc(irb, alloca, var); | ||
| 8091 | ir_build_end_expr(irb, scope, source_node, init, &var_result_loc->base); | ||
| 8092 | ir_build_var_decl_src(irb, scope, source_node, var, nullptr, alloca); | ||
| 8093 | } | ||
| 8094 | |||
| 8095 | static IrInstSrc *ir_gen_var_decl(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 8096 | assert(node->type == NodeTypeVariableDeclaration); | ||
| 8097 | |||
| 8098 | AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration; | ||
| 8099 | |||
| 8100 | if (buf_eql_str(variable_declaration->symbol, "_")) { | ||
| 8101 | add_node_error(irb->codegen, node, buf_sprintf("`_` is not a declarable symbol")); | ||
| 8102 | return irb->codegen->invalid_inst_src; | ||
| 8103 | } | ||
| 8104 | |||
| 8105 | // Used for the type expr and the align expr | ||
| 8106 | Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); | ||
| 8107 | |||
| 8108 | IrInstSrc *type_instruction; | ||
| 8109 | if (variable_declaration->type != nullptr) { | ||
| 8110 | type_instruction = ir_gen_node(irb, variable_declaration->type, comptime_scope); | ||
| 8111 | if (type_instruction == irb->codegen->invalid_inst_src) | ||
| 8112 | return type_instruction; | ||
| 8113 | } else { | ||
| 8114 | type_instruction = nullptr; | ||
| 8115 | } | ||
| 8116 | |||
| 8117 | bool is_shadowable = false; | ||
| 8118 | bool is_const = variable_declaration->is_const; | ||
| 8119 | bool is_extern = variable_declaration->is_extern; | ||
| 8120 | |||
| 8121 | bool is_comptime_scalar = ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime; | ||
| 8122 | IrInstSrc *is_comptime = ir_build_const_bool(irb, scope, node, is_comptime_scalar); | ||
| 8123 | ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol, | ||
| 8124 | is_const, is_const, is_shadowable, is_comptime); | ||
| 8125 | // we detect IrInstSrcDeclVar in gen_block to make sure the next node | ||
| 8126 | // is inside var->child_scope | ||
| 8127 | |||
| 8128 | if (!is_extern && !variable_declaration->expr) { | ||
| 8129 | var->var_type = irb->codegen->builtin_types.entry_invalid; | ||
| 8130 | add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized")); | ||
| 8131 | return irb->codegen->invalid_inst_src; | ||
| 8132 | } | ||
| 8133 | |||
| 8134 | IrInstSrc *align_value = nullptr; | ||
| 8135 | if (variable_declaration->align_expr != nullptr) { | ||
| 8136 | align_value = ir_gen_node(irb, variable_declaration->align_expr, comptime_scope); | ||
| 8137 | if (align_value == irb->codegen->invalid_inst_src) | ||
| 8138 | return align_value; | ||
| 8139 | } | ||
| 8140 | |||
| 8141 | if (variable_declaration->section_expr != nullptr) { | ||
| 8142 | add_node_error(irb->codegen, variable_declaration->section_expr, | ||
| 8143 | buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol))); | ||
| 8144 | } | ||
| 8145 | |||
| 8146 | // Parser should ensure that this never happens | ||
| 8147 | assert(variable_declaration->threadlocal_tok == nullptr); | ||
| 8148 | |||
| 8149 | IrInstSrc *alloca = ir_build_alloca_src(irb, scope, node, align_value, | ||
| 8150 | buf_ptr(variable_declaration->symbol), is_comptime); | ||
| 8151 | |||
| 8152 | // Create a result location for the initialization expression. | ||
| 8153 | ResultLocVar *result_loc_var = ir_build_var_result_loc(irb, alloca, var); | ||
| 8154 | ResultLoc *init_result_loc; | ||
| 8155 | ResultLocCast *result_loc_cast; | ||
| 8156 | if (type_instruction != nullptr) { | ||
| 8157 | result_loc_cast = ir_build_cast_result_loc(irb, type_instruction, &result_loc_var->base); | ||
| 8158 | init_result_loc = &result_loc_cast->base; | ||
| 8159 | } else { | ||
| 8160 | result_loc_cast = nullptr; | ||
| 8161 | init_result_loc = &result_loc_var->base; | ||
| 8162 | } | ||
| 8163 | |||
| 8164 | Scope *init_scope = is_comptime_scalar ? | ||
| 8165 | create_comptime_scope(irb->codegen, variable_declaration->expr, scope) : scope; | ||
| 8166 | |||
| 8167 | // Temporarily set the name of the IrExecutableSrc to the VariableDeclaration | ||
| 8168 | // so that the struct or enum from the init expression inherits the name. | ||
| 8169 | Buf *old_exec_name = irb->exec->name; | ||
| 8170 | irb->exec->name = variable_declaration->symbol; | ||
| 8171 | IrInstSrc *init_value = ir_gen_node_extra(irb, variable_declaration->expr, init_scope, | ||
| 8172 | LValNone, init_result_loc); | ||
| 8173 | irb->exec->name = old_exec_name; | ||
| 8174 | |||
| 8175 | if (init_value == irb->codegen->invalid_inst_src) | ||
| 8176 | return irb->codegen->invalid_inst_src; | ||
| 8177 | |||
| 8178 | if (result_loc_cast != nullptr) { | ||
| 8179 | IrInstSrc *implicit_cast = ir_build_implicit_cast(irb, scope, init_value->base.source_node, | ||
| 8180 | init_value, result_loc_cast); | ||
| 8181 | ir_build_end_expr(irb, scope, node, implicit_cast, &result_loc_var->base); | ||
| 8182 | } | ||
| 8183 | |||
| 8184 | return ir_build_var_decl_src(irb, scope, node, var, align_value, alloca); | ||
| 8185 | } | ||
| 8186 | |||
| 8187 | static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, | ||
| 8188 | ResultLoc *result_loc) | ||
| 8189 | { | ||
| 8190 | assert(node->type == NodeTypeWhileExpr); | ||
| 8191 | |||
| 8192 | AstNode *continue_expr_node = node->data.while_expr.continue_expr; | ||
| 8193 | AstNode *else_node = node->data.while_expr.else_node; | ||
| 8194 | |||
| 8195 | IrBasicBlockSrc *cond_block = ir_create_basic_block(irb, scope, "WhileCond"); | ||
| 8196 | IrBasicBlockSrc *body_block = ir_create_basic_block(irb, scope, "WhileBody"); | ||
| 8197 | IrBasicBlockSrc *continue_block = continue_expr_node ? | ||
| 8198 | ir_create_basic_block(irb, scope, "WhileContinue") : cond_block; | ||
| 8199 | IrBasicBlockSrc *end_block = ir_create_basic_block(irb, scope, "WhileEnd"); | ||
| 8200 | IrBasicBlockSrc *else_block = else_node ? | ||
| 8201 | ir_create_basic_block(irb, scope, "WhileElse") : end_block; | ||
| 8202 | |||
| 8203 | IrInstSrc *is_comptime = ir_build_const_bool(irb, scope, node, | ||
| 8204 | ir_should_inline(irb->exec, scope) || node->data.while_expr.is_inline); | ||
| 8205 | ir_build_br(irb, scope, node, cond_block, is_comptime); | ||
| 8206 | |||
| 8207 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); | ||
| 8208 | Buf *var_symbol = node->data.while_expr.var_symbol; | ||
| 8209 | Buf *err_symbol = node->data.while_expr.err_symbol; | ||
| 8210 | if (err_symbol != nullptr) { | ||
| 8211 | ir_set_cursor_at_end_and_append_block(irb, cond_block); | ||
| 8212 | |||
| 8213 | Scope *payload_scope; | ||
| 8214 | AstNode *symbol_node = node; // TODO make more accurate | ||
| 8215 | ZigVar *payload_var; | ||
| 8216 | if (var_symbol) { | ||
| 8217 | // TODO make it an error to write to payload variable | ||
| 8218 | payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol, | ||
| 8219 | true, false, false, is_comptime); | ||
| 8220 | payload_scope = payload_var->child_scope; | ||
| 8221 | } else { | ||
| 8222 | payload_scope = subexpr_scope; | ||
| 8223 | } | ||
| 8224 | ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, payload_scope); | ||
| 8225 | IrInstSrc *err_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, | ||
| 8226 | LValPtr, nullptr); | ||
| 8227 | if (err_val_ptr == irb->codegen->invalid_inst_src) | ||
| 8228 | return err_val_ptr; | ||
| 8229 | IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node->data.while_expr.condition, err_val_ptr, | ||
| 8230 | true, false); | ||
| 8231 | IrBasicBlockSrc *after_cond_block = irb->current_basic_block; | ||
| 8232 | IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); | ||
| 8233 | IrInstSrc *cond_br_inst; | ||
| 8234 | if (!instr_is_unreachable(is_err)) { | ||
| 8235 | cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_err, | ||
| 8236 | else_block, body_block, is_comptime); | ||
| 8237 | cond_br_inst->is_gen = true; | ||
| 8238 | } else { | ||
| 8239 | // for the purposes of the source instruction to ir_build_result_peers | ||
| 8240 | cond_br_inst = irb->current_basic_block->instruction_list.last(); | ||
| 8241 | } | ||
| 8242 | |||
| 8243 | ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, | ||
| 8244 | is_comptime); | ||
| 8245 | |||
| 8246 | ir_set_cursor_at_end_and_append_block(irb, body_block); | ||
| 8247 | if (var_symbol) { | ||
| 8248 | IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, &spill_scope->base, symbol_node, | ||
| 8249 | err_val_ptr, false, false); | ||
| 8250 | IrInstSrc *var_value = node->data.while_expr.var_is_ptr ? | ||
| 8251 | payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, symbol_node, payload_ptr); | ||
| 8252 | build_decl_var_and_init(irb, payload_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); | ||
| 8253 | } | ||
| 8254 | |||
| 8255 | ZigList<IrInstSrc *> incoming_values = {0}; | ||
| 8256 | ZigList<IrBasicBlockSrc *> incoming_blocks = {0}; | ||
| 8257 | |||
| 8258 | if (is_duplicate_label(irb->codegen, payload_scope, node, node->data.while_expr.name)) | ||
| 8259 | return irb->codegen->invalid_inst_src; | ||
| 8260 | |||
| 8261 | ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, payload_scope); | ||
| 8262 | loop_scope->break_block = end_block; | ||
| 8263 | loop_scope->continue_block = continue_block; | ||
| 8264 | loop_scope->is_comptime = is_comptime; | ||
| 8265 | loop_scope->incoming_blocks = &incoming_blocks; | ||
| 8266 | loop_scope->incoming_values = &incoming_values; | ||
| 8267 | loop_scope->lval = lval; | ||
| 8268 | loop_scope->peer_parent = peer_parent; | ||
| 8269 | loop_scope->spill_scope = spill_scope; | ||
| 8270 | |||
| 8271 | // Note the body block of the loop is not the place that lval and result_loc are used - | ||
| 8272 | // it's actually in break statements, handled similarly to return statements. | ||
| 8273 | // That is why we set those values in loop_scope above and not in this ir_gen_node call. | ||
| 8274 | IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); | ||
| 8275 | if (body_result == irb->codegen->invalid_inst_src) | ||
| 8276 | return body_result; | ||
| 8277 | |||
| 8278 | if (loop_scope->name != nullptr && loop_scope->name_used == false) { | ||
| 8279 | add_node_error(irb->codegen, node, buf_sprintf("unused while label")); | ||
| 8280 | } | ||
| 8281 | |||
| 8282 | if (!instr_is_unreachable(body_result)) { | ||
| 8283 | ir_mark_gen(ir_build_check_statement_is_void(irb, payload_scope, node->data.while_expr.body, body_result)); | ||
| 8284 | ir_mark_gen(ir_build_br(irb, payload_scope, node, continue_block, is_comptime)); | ||
| 8285 | } | ||
| 8286 | |||
| 8287 | if (continue_expr_node) { | ||
| 8288 | ir_set_cursor_at_end_and_append_block(irb, continue_block); | ||
| 8289 | IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, payload_scope); | ||
| 8290 | if (expr_result == irb->codegen->invalid_inst_src) | ||
| 8291 | return expr_result; | ||
| 8292 | if (!instr_is_unreachable(expr_result)) { | ||
| 8293 | ir_mark_gen(ir_build_check_statement_is_void(irb, payload_scope, continue_expr_node, expr_result)); | ||
| 8294 | ir_mark_gen(ir_build_br(irb, payload_scope, node, cond_block, is_comptime)); | ||
| 8295 | } | ||
| 8296 | } | ||
| 8297 | |||
| 8298 | ir_set_cursor_at_end_and_append_block(irb, else_block); | ||
| 8299 | assert(else_node != nullptr); | ||
| 8300 | |||
| 8301 | // TODO make it an error to write to error variable | ||
| 8302 | AstNode *err_symbol_node = else_node; // TODO make more accurate | ||
| 8303 | ZigVar *err_var = ir_create_var(irb, err_symbol_node, scope, err_symbol, | ||
| 8304 | true, false, false, is_comptime); | ||
| 8305 | Scope *err_scope = err_var->child_scope; | ||
| 8306 | IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, err_scope, err_symbol_node, err_val_ptr); | ||
| 8307 | IrInstSrc *err_value = ir_build_load_ptr(irb, err_scope, err_symbol_node, err_ptr); | ||
| 8308 | build_decl_var_and_init(irb, err_scope, err_symbol_node, err_var, err_value, buf_ptr(err_symbol), is_comptime); | ||
| 8309 | |||
| 8310 | if (peer_parent->peers.length != 0) { | ||
| 8311 | peer_parent->peers.last()->next_bb = else_block; | ||
| 8312 | } | ||
| 8313 | ResultLocPeer *peer_result = create_peer_result(peer_parent); | ||
| 8314 | peer_parent->peers.append(peer_result); | ||
| 8315 | IrInstSrc *else_result = ir_gen_node_extra(irb, else_node, err_scope, lval, &peer_result->base); | ||
| 8316 | if (else_result == irb->codegen->invalid_inst_src) | ||
| 8317 | return else_result; | ||
| 8318 | if (!instr_is_unreachable(else_result)) | ||
| 8319 | ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); | ||
| 8320 | IrBasicBlockSrc *after_else_block = irb->current_basic_block; | ||
| 8321 | ir_set_cursor_at_end_and_append_block(irb, end_block); | ||
| 8322 | if (else_result) { | ||
| 8323 | incoming_blocks.append(after_else_block); | ||
| 8324 | incoming_values.append(else_result); | ||
| 8325 | } else { | ||
| 8326 | incoming_blocks.append(after_cond_block); | ||
| 8327 | incoming_values.append(void_else_result); | ||
| 8328 | } | ||
| 8329 | if (peer_parent->peers.length != 0) { | ||
| 8330 | peer_parent->peers.last()->next_bb = end_block; | ||
| 8331 | } | ||
| 8332 | |||
| 8333 | IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, | ||
| 8334 | incoming_blocks.items, incoming_values.items, peer_parent); | ||
| 8335 | return ir_expr_wrap(irb, scope, phi, result_loc); | ||
| 8336 | } else if (var_symbol != nullptr) { | ||
| 8337 | ir_set_cursor_at_end_and_append_block(irb, cond_block); | ||
| 8338 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); | ||
| 8339 | // TODO make it an error to write to payload variable | ||
| 8340 | AstNode *symbol_node = node; // TODO make more accurate | ||
| 8341 | |||
| 8342 | ZigVar *payload_var = ir_create_var(irb, symbol_node, subexpr_scope, var_symbol, | ||
| 8343 | true, false, false, is_comptime); | ||
| 8344 | Scope *child_scope = payload_var->child_scope; | ||
| 8345 | ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, child_scope); | ||
| 8346 | IrInstSrc *maybe_val_ptr = ir_gen_node_extra(irb, node->data.while_expr.condition, subexpr_scope, | ||
| 8347 | LValPtr, nullptr); | ||
| 8348 | if (maybe_val_ptr == irb->codegen->invalid_inst_src) | ||
| 8349 | return maybe_val_ptr; | ||
| 8350 | IrInstSrc *maybe_val = ir_build_load_ptr(irb, scope, node->data.while_expr.condition, maybe_val_ptr); | ||
| 8351 | IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, scope, node->data.while_expr.condition, maybe_val); | ||
| 8352 | IrBasicBlockSrc *after_cond_block = irb->current_basic_block; | ||
| 8353 | IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); | ||
| 8354 | IrInstSrc *cond_br_inst; | ||
| 8355 | if (!instr_is_unreachable(is_non_null)) { | ||
| 8356 | cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, is_non_null, | ||
| 8357 | body_block, else_block, is_comptime); | ||
| 8358 | cond_br_inst->is_gen = true; | ||
| 8359 | } else { | ||
| 8360 | // for the purposes of the source instruction to ir_build_result_peers | ||
| 8361 | cond_br_inst = irb->current_basic_block->instruction_list.last(); | ||
| 8362 | } | ||
| 8363 | |||
| 8364 | ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, | ||
| 8365 | is_comptime); | ||
| 8366 | |||
| 8367 | ir_set_cursor_at_end_and_append_block(irb, body_block); | ||
| 8368 | IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, &spill_scope->base, symbol_node, maybe_val_ptr, false); | ||
| 8369 | IrInstSrc *var_value = node->data.while_expr.var_is_ptr ? | ||
| 8370 | payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, symbol_node, payload_ptr); | ||
| 8371 | build_decl_var_and_init(irb, child_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime); | ||
| 8372 | |||
| 8373 | ZigList<IrInstSrc *> incoming_values = {0}; | ||
| 8374 | ZigList<IrBasicBlockSrc *> incoming_blocks = {0}; | ||
| 8375 | |||
| 8376 | if (is_duplicate_label(irb->codegen, child_scope, node, node->data.while_expr.name)) | ||
| 8377 | return irb->codegen->invalid_inst_src; | ||
| 8378 | |||
| 8379 | ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope); | ||
| 8380 | loop_scope->break_block = end_block; | ||
| 8381 | loop_scope->continue_block = continue_block; | ||
| 8382 | loop_scope->is_comptime = is_comptime; | ||
| 8383 | loop_scope->incoming_blocks = &incoming_blocks; | ||
| 8384 | loop_scope->incoming_values = &incoming_values; | ||
| 8385 | loop_scope->lval = lval; | ||
| 8386 | loop_scope->peer_parent = peer_parent; | ||
| 8387 | loop_scope->spill_scope = spill_scope; | ||
| 8388 | |||
| 8389 | // Note the body block of the loop is not the place that lval and result_loc are used - | ||
| 8390 | // it's actually in break statements, handled similarly to return statements. | ||
| 8391 | // That is why we set those values in loop_scope above and not in this ir_gen_node call. | ||
| 8392 | IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); | ||
| 8393 | if (body_result == irb->codegen->invalid_inst_src) | ||
| 8394 | return body_result; | ||
| 8395 | |||
| 8396 | if (loop_scope->name != nullptr && loop_scope->name_used == false) { | ||
| 8397 | add_node_error(irb->codegen, node, buf_sprintf("unused while label")); | ||
| 8398 | } | ||
| 8399 | |||
| 8400 | if (!instr_is_unreachable(body_result)) { | ||
| 8401 | ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.while_expr.body, body_result)); | ||
| 8402 | ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime)); | ||
| 8403 | } | ||
| 8404 | |||
| 8405 | if (continue_expr_node) { | ||
| 8406 | ir_set_cursor_at_end_and_append_block(irb, continue_block); | ||
| 8407 | IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, child_scope); | ||
| 8408 | if (expr_result == irb->codegen->invalid_inst_src) | ||
| 8409 | return expr_result; | ||
| 8410 | if (!instr_is_unreachable(expr_result)) { | ||
| 8411 | ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, continue_expr_node, expr_result)); | ||
| 8412 | ir_mark_gen(ir_build_br(irb, child_scope, node, cond_block, is_comptime)); | ||
| 8413 | } | ||
| 8414 | } | ||
| 8415 | |||
| 8416 | IrInstSrc *else_result = nullptr; | ||
| 8417 | if (else_node) { | ||
| 8418 | ir_set_cursor_at_end_and_append_block(irb, else_block); | ||
| 8419 | |||
| 8420 | if (peer_parent->peers.length != 0) { | ||
| 8421 | peer_parent->peers.last()->next_bb = else_block; | ||
| 8422 | } | ||
| 8423 | ResultLocPeer *peer_result = create_peer_result(peer_parent); | ||
| 8424 | peer_parent->peers.append(peer_result); | ||
| 8425 | else_result = ir_gen_node_extra(irb, else_node, scope, lval, &peer_result->base); | ||
| 8426 | if (else_result == irb->codegen->invalid_inst_src) | ||
| 8427 | return else_result; | ||
| 8428 | if (!instr_is_unreachable(else_result)) | ||
| 8429 | ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); | ||
| 8430 | } | ||
| 8431 | IrBasicBlockSrc *after_else_block = irb->current_basic_block; | ||
| 8432 | ir_set_cursor_at_end_and_append_block(irb, end_block); | ||
| 8433 | if (else_result) { | ||
| 8434 | incoming_blocks.append(after_else_block); | ||
| 8435 | incoming_values.append(else_result); | ||
| 8436 | } else { | ||
| 8437 | incoming_blocks.append(after_cond_block); | ||
| 8438 | incoming_values.append(void_else_result); | ||
| 8439 | } | ||
| 8440 | if (peer_parent->peers.length != 0) { | ||
| 8441 | peer_parent->peers.last()->next_bb = end_block; | ||
| 8442 | } | ||
| 8443 | |||
| 8444 | IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, | ||
| 8445 | incoming_blocks.items, incoming_values.items, peer_parent); | ||
| 8446 | return ir_expr_wrap(irb, scope, phi, result_loc); | ||
| 8447 | } else { | ||
| 8448 | ir_set_cursor_at_end_and_append_block(irb, cond_block); | ||
| 8449 | IrInstSrc *cond_val = ir_gen_node(irb, node->data.while_expr.condition, scope); | ||
| 8450 | if (cond_val == irb->codegen->invalid_inst_src) | ||
| 8451 | return cond_val; | ||
| 8452 | IrBasicBlockSrc *after_cond_block = irb->current_basic_block; | ||
| 8453 | IrInstSrc *void_else_result = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, scope, node)); | ||
| 8454 | IrInstSrc *cond_br_inst; | ||
| 8455 | if (!instr_is_unreachable(cond_val)) { | ||
| 8456 | cond_br_inst = ir_build_cond_br(irb, scope, node->data.while_expr.condition, cond_val, | ||
| 8457 | body_block, else_block, is_comptime); | ||
| 8458 | cond_br_inst->is_gen = true; | ||
| 8459 | } else { | ||
| 8460 | // for the purposes of the source instruction to ir_build_result_peers | ||
| 8461 | cond_br_inst = irb->current_basic_block->instruction_list.last(); | ||
| 8462 | } | ||
| 8463 | |||
| 8464 | ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, | ||
| 8465 | is_comptime); | ||
| 8466 | ir_set_cursor_at_end_and_append_block(irb, body_block); | ||
| 8467 | |||
| 8468 | ZigList<IrInstSrc *> incoming_values = {0}; | ||
| 8469 | ZigList<IrBasicBlockSrc *> incoming_blocks = {0}; | ||
| 8470 | |||
| 8471 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); | ||
| 8472 | |||
| 8473 | if (is_duplicate_label(irb->codegen, subexpr_scope, node, node->data.while_expr.name)) | ||
| 8474 | return irb->codegen->invalid_inst_src; | ||
| 8475 | |||
| 8476 | ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, subexpr_scope); | ||
| 8477 | loop_scope->break_block = end_block; | ||
| 8478 | loop_scope->continue_block = continue_block; | ||
| 8479 | loop_scope->is_comptime = is_comptime; | ||
| 8480 | loop_scope->incoming_blocks = &incoming_blocks; | ||
| 8481 | loop_scope->incoming_values = &incoming_values; | ||
| 8482 | loop_scope->lval = lval; | ||
| 8483 | loop_scope->peer_parent = peer_parent; | ||
| 8484 | |||
| 8485 | // Note the body block of the loop is not the place that lval and result_loc are used - | ||
| 8486 | // it's actually in break statements, handled similarly to return statements. | ||
| 8487 | // That is why we set those values in loop_scope above and not in this ir_gen_node call. | ||
| 8488 | IrInstSrc *body_result = ir_gen_node(irb, node->data.while_expr.body, &loop_scope->base); | ||
| 8489 | if (body_result == irb->codegen->invalid_inst_src) | ||
| 8490 | return body_result; | ||
| 8491 | |||
| 8492 | if (loop_scope->name != nullptr && loop_scope->name_used == false) { | ||
| 8493 | add_node_error(irb->codegen, node, buf_sprintf("unused while label")); | ||
| 8494 | } | ||
| 8495 | |||
| 8496 | if (!instr_is_unreachable(body_result)) { | ||
| 8497 | ir_mark_gen(ir_build_check_statement_is_void(irb, scope, node->data.while_expr.body, body_result)); | ||
| 8498 | ir_mark_gen(ir_build_br(irb, scope, node, continue_block, is_comptime)); | ||
| 8499 | } | ||
| 8500 | |||
| 8501 | if (continue_expr_node) { | ||
| 8502 | ir_set_cursor_at_end_and_append_block(irb, continue_block); | ||
| 8503 | IrInstSrc *expr_result = ir_gen_node(irb, continue_expr_node, subexpr_scope); | ||
| 8504 | if (expr_result == irb->codegen->invalid_inst_src) | ||
| 8505 | return expr_result; | ||
| 8506 | if (!instr_is_unreachable(expr_result)) { | ||
| 8507 | ir_mark_gen(ir_build_check_statement_is_void(irb, scope, continue_expr_node, expr_result)); | ||
| 8508 | ir_mark_gen(ir_build_br(irb, scope, node, cond_block, is_comptime)); | ||
| 8509 | } | ||
| 8510 | } | ||
| 8511 | |||
| 8512 | IrInstSrc *else_result = nullptr; | ||
| 8513 | if (else_node) { | ||
| 8514 | ir_set_cursor_at_end_and_append_block(irb, else_block); | ||
| 8515 | |||
| 8516 | if (peer_parent->peers.length != 0) { | ||
| 8517 | peer_parent->peers.last()->next_bb = else_block; | ||
| 8518 | } | ||
| 8519 | ResultLocPeer *peer_result = create_peer_result(peer_parent); | ||
| 8520 | peer_parent->peers.append(peer_result); | ||
| 8521 | |||
| 8522 | else_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_result->base); | ||
| 8523 | if (else_result == irb->codegen->invalid_inst_src) | ||
| 8524 | return else_result; | ||
| 8525 | if (!instr_is_unreachable(else_result)) | ||
| 8526 | ir_mark_gen(ir_build_br(irb, scope, node, end_block, is_comptime)); | ||
| 8527 | } | ||
| 8528 | IrBasicBlockSrc *after_else_block = irb->current_basic_block; | ||
| 8529 | ir_set_cursor_at_end_and_append_block(irb, end_block); | ||
| 8530 | if (else_result) { | ||
| 8531 | incoming_blocks.append(after_else_block); | ||
| 8532 | incoming_values.append(else_result); | ||
| 8533 | } else { | ||
| 8534 | incoming_blocks.append(after_cond_block); | ||
| 8535 | incoming_values.append(void_else_result); | ||
| 8536 | } | ||
| 8537 | if (peer_parent->peers.length != 0) { | ||
| 8538 | peer_parent->peers.last()->next_bb = end_block; | ||
| 8539 | } | ||
| 8540 | |||
| 8541 | IrInstSrc *phi = ir_build_phi(irb, scope, node, incoming_blocks.length, | ||
| 8542 | incoming_blocks.items, incoming_values.items, peer_parent); | ||
| 8543 | return ir_expr_wrap(irb, scope, phi, result_loc); | ||
| 8544 | } | ||
| 8545 | } | ||
| 8546 | |||
| 8547 | static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, | ||
| 8548 | ResultLoc *result_loc) | ||
| 8549 | { | ||
| 8550 | assert(node->type == NodeTypeForExpr); | ||
| 8551 | |||
| 8552 | AstNode *array_node = node->data.for_expr.array_expr; | ||
| 8553 | AstNode *elem_node = node->data.for_expr.elem_node; | ||
| 8554 | AstNode *index_node = node->data.for_expr.index_node; | ||
| 8555 | AstNode *body_node = node->data.for_expr.body; | ||
| 8556 | AstNode *else_node = node->data.for_expr.else_node; | ||
| 8557 | |||
| 8558 | if (!elem_node) { | ||
| 8559 | add_node_error(irb->codegen, node, buf_sprintf("for loop expression missing element parameter")); | ||
| 8560 | return irb->codegen->invalid_inst_src; | ||
| 8561 | } | ||
| 8562 | assert(elem_node->type == NodeTypeSymbol); | ||
| 8563 | |||
| 8564 | ScopeExpr *spill_scope = create_expr_scope(irb->codegen, node, parent_scope); | ||
| 8565 | |||
| 8566 | IrInstSrc *array_val_ptr = ir_gen_node_extra(irb, array_node, &spill_scope->base, LValPtr, nullptr); | ||
| 8567 | if (array_val_ptr == irb->codegen->invalid_inst_src) | ||
| 8568 | return array_val_ptr; | ||
| 8569 | |||
| 8570 | IrInstSrc *is_comptime = ir_build_const_bool(irb, parent_scope, node, | ||
| 8571 | ir_should_inline(irb->exec, parent_scope) || node->data.for_expr.is_inline); | ||
| 8572 | |||
| 8573 | AstNode *index_var_source_node; | ||
| 8574 | ZigVar *index_var; | ||
| 8575 | const char *index_var_name; | ||
| 8576 | if (index_node) { | ||
| 8577 | index_var_source_node = index_node; | ||
| 8578 | Buf *index_var_name_buf = index_node->data.symbol_expr.symbol; | ||
| 8579 | index_var = ir_create_var(irb, index_node, parent_scope, index_var_name_buf, true, false, false, is_comptime); | ||
| 8580 | index_var_name = buf_ptr(index_var_name_buf); | ||
| 8581 | } else { | ||
| 8582 | index_var_source_node = node; | ||
| 8583 | index_var = ir_create_var(irb, node, parent_scope, nullptr, true, false, true, is_comptime); | ||
| 8584 | index_var_name = "i"; | ||
| 8585 | } | ||
| 8586 | |||
| 8587 | IrInstSrc *zero = ir_build_const_usize(irb, parent_scope, node, 0); | ||
| 8588 | build_decl_var_and_init(irb, parent_scope, index_var_source_node, index_var, zero, index_var_name, is_comptime); | ||
| 8589 | parent_scope = index_var->child_scope; | ||
| 8590 | |||
| 8591 | IrInstSrc *one = ir_build_const_usize(irb, parent_scope, node, 1); | ||
| 8592 | IrInstSrc *index_ptr = ir_build_var_ptr(irb, parent_scope, node, index_var); | ||
| 8593 | |||
| 8594 | |||
| 8595 | IrBasicBlockSrc *cond_block = ir_create_basic_block(irb, parent_scope, "ForCond"); | ||
| 8596 | IrBasicBlockSrc *body_block = ir_create_basic_block(irb, parent_scope, "ForBody"); | ||
| 8597 | IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "ForEnd"); | ||
| 8598 | IrBasicBlockSrc *else_block = else_node ? ir_create_basic_block(irb, parent_scope, "ForElse") : end_block; | ||
| 8599 | IrBasicBlockSrc *continue_block = ir_create_basic_block(irb, parent_scope, "ForContinue"); | ||
| 8600 | |||
| 8601 | Buf *len_field_name = buf_create_from_str("len"); | ||
| 8602 | IrInstSrc *len_ref = ir_build_field_ptr(irb, parent_scope, node, array_val_ptr, len_field_name, false); | ||
| 8603 | IrInstSrc *len_val = ir_build_load_ptr(irb, &spill_scope->base, node, len_ref); | ||
| 8604 | ir_build_br(irb, parent_scope, node, cond_block, is_comptime); | ||
| 8605 | |||
| 8606 | ir_set_cursor_at_end_and_append_block(irb, cond_block); | ||
| 8607 | IrInstSrc *index_val = ir_build_load_ptr(irb, &spill_scope->base, node, index_ptr); | ||
| 8608 | IrInstSrc *cond = ir_build_bin_op(irb, parent_scope, node, IrBinOpCmpLessThan, index_val, len_val, false); | ||
| 8609 | IrBasicBlockSrc *after_cond_block = irb->current_basic_block; | ||
| 8610 | IrInstSrc *void_else_value = else_node ? nullptr : ir_mark_gen(ir_build_const_void(irb, parent_scope, node)); | ||
| 8611 | IrInstSrc *cond_br_inst = ir_mark_gen(ir_build_cond_br(irb, parent_scope, node, cond, | ||
| 8612 | body_block, else_block, is_comptime)); | ||
| 8613 | |||
| 8614 | ResultLocPeerParent *peer_parent = ir_build_result_peers(irb, cond_br_inst, end_block, result_loc, is_comptime); | ||
| 8615 | |||
| 8616 | ir_set_cursor_at_end_and_append_block(irb, body_block); | ||
| 8617 | IrInstSrc *elem_ptr = ir_build_elem_ptr(irb, &spill_scope->base, node, array_val_ptr, index_val, | ||
| 8618 | false, PtrLenSingle, nullptr); | ||
| 8619 | // TODO make it an error to write to element variable or i variable. | ||
| 8620 | Buf *elem_var_name = elem_node->data.symbol_expr.symbol; | ||
| 8621 | ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime); | ||
| 8622 | Scope *child_scope = elem_var->child_scope; | ||
| 8623 | |||
| 8624 | IrInstSrc *elem_value = node->data.for_expr.elem_is_ptr ? | ||
| 8625 | elem_ptr : ir_build_load_ptr(irb, &spill_scope->base, elem_node, elem_ptr); | ||
| 8626 | build_decl_var_and_init(irb, parent_scope, elem_node, elem_var, elem_value, buf_ptr(elem_var_name), is_comptime); | ||
| 8627 | |||
| 8628 | if (is_duplicate_label(irb->codegen, child_scope, node, node->data.for_expr.name)) | ||
| 8629 | return irb->codegen->invalid_inst_src; | ||
| 8630 | |||
| 8631 | ZigList<IrInstSrc *> incoming_values = {0}; | ||
| 8632 | ZigList<IrBasicBlockSrc *> incoming_blocks = {0}; | ||
| 8633 | ScopeLoop *loop_scope = create_loop_scope(irb->codegen, node, child_scope); | ||
| 8634 | loop_scope->break_block = end_block; | ||
| 8635 | loop_scope->continue_block = continue_block; | ||
| 8636 | loop_scope->is_comptime = is_comptime; | ||
| 8637 | loop_scope->incoming_blocks = &incoming_blocks; | ||
| 8638 | loop_scope->incoming_values = &incoming_values; | ||
| 8639 | loop_scope->lval = LValNone; | ||
| 8640 | loop_scope->peer_parent = peer_parent; | ||
| 8641 | loop_scope->spill_scope = spill_scope; | ||
| 8642 | |||
| 8643 | // Note the body block of the loop is not the place that lval and result_loc are used - | ||
| 8644 | // it's actually in break statements, handled similarly to return statements. | ||
| 8645 | // That is why we set those values in loop_scope above and not in this ir_gen_node call. | ||
| 8646 | IrInstSrc *body_result = ir_gen_node(irb, body_node, &loop_scope->base); | ||
| 8647 | if (body_result == irb->codegen->invalid_inst_src) | ||
| 8648 | return irb->codegen->invalid_inst_src; | ||
| 8649 | |||
| 8650 | if (loop_scope->name != nullptr && loop_scope->name_used == false) { | ||
| 8651 | add_node_error(irb->codegen, node, buf_sprintf("unused for label")); | ||
| 8652 | } | ||
| 8653 | |||
| 8654 | if (!instr_is_unreachable(body_result)) { | ||
| 8655 | ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.for_expr.body, body_result)); | ||
| 8656 | ir_mark_gen(ir_build_br(irb, child_scope, node, continue_block, is_comptime)); | ||
| 8657 | } | ||
| 8658 | |||
| 8659 | ir_set_cursor_at_end_and_append_block(irb, continue_block); | ||
| 8660 | IrInstSrc *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false); | ||
| 8661 | ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val)->allow_write_through_const = true; | ||
| 8662 | ir_build_br(irb, child_scope, node, cond_block, is_comptime); | ||
| 8663 | |||
| 8664 | IrInstSrc *else_result = nullptr; | ||
| 8665 | if (else_node) { | ||
| 8666 | ir_set_cursor_at_end_and_append_block(irb, else_block); | ||
| 8667 | |||
| 8668 | if (peer_parent->peers.length != 0) { | ||
| 8669 | peer_parent->peers.last()->next_bb = else_block; | ||
| 8670 | } | ||
| 8671 | ResultLocPeer *peer_result = create_peer_result(peer_parent); | ||
| 8672 | peer_parent->peers.append(peer_result); | ||
| 8673 | else_result = ir_gen_node_extra(irb, else_node, parent_scope, LValNone, &peer_result->base); | ||
| 8674 | if (else_result == irb->codegen->invalid_inst_src) | ||
| 8675 | return else_result; | ||
| 8676 | if (!instr_is_unreachable(else_result)) | ||
| 8677 | ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); | ||
| 8678 | } | ||
| 8679 | IrBasicBlockSrc *after_else_block = irb->current_basic_block; | ||
| 8680 | ir_set_cursor_at_end_and_append_block(irb, end_block); | ||
| 8681 | |||
| 8682 | if (else_result) { | ||
| 8683 | incoming_blocks.append(after_else_block); | ||
| 8684 | incoming_values.append(else_result); | ||
| 8685 | } else { | ||
| 8686 | incoming_blocks.append(after_cond_block); | ||
| 8687 | incoming_values.append(void_else_value); | ||
| 8688 | } | ||
| 8689 | if (peer_parent->peers.length != 0) { | ||
| 8690 | peer_parent->peers.last()->next_bb = end_block; | ||
| 8691 | } | ||
| 8692 | |||
| 8693 | IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, incoming_blocks.length, | ||
| 8694 | incoming_blocks.items, incoming_values.items, peer_parent); | ||
| 8695 | return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); | ||
| 8696 | } | ||
| 8697 | |||
| 8698 | static IrInstSrc *ir_gen_bool_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 8699 | assert(node->type == NodeTypeBoolLiteral); | ||
| 8700 | return ir_build_const_bool(irb, scope, node, node->data.bool_literal.value); | ||
| 8701 | } | ||
| 8702 | |||
| 8703 | static IrInstSrc *ir_gen_enum_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 8704 | assert(node->type == NodeTypeEnumLiteral); | ||
| 8705 | Buf *name = &node->data.enum_literal.identifier->data.str_lit.str; | ||
| 8706 | return ir_build_const_enum_literal(irb, scope, node, name); | ||
| 8707 | } | ||
| 8708 | |||
| 8709 | static IrInstSrc *ir_gen_string_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 8710 | assert(node->type == NodeTypeStringLiteral); | ||
| 8711 | |||
| 8712 | return ir_build_const_str_lit(irb, scope, node, node->data.string_literal.buf); | ||
| 8713 | } | ||
| 8714 | |||
| 8715 | static IrInstSrc *ir_gen_array_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 8716 | assert(node->type == NodeTypeArrayType); | ||
| 8717 | |||
| 8718 | AstNode *size_node = node->data.array_type.size; | ||
| 8719 | AstNode *child_type_node = node->data.array_type.child_type; | ||
| 8720 | bool is_const = node->data.array_type.is_const; | ||
| 8721 | bool is_volatile = node->data.array_type.is_volatile; | ||
| 8722 | bool is_allow_zero = node->data.array_type.allow_zero_token != nullptr; | ||
| 8723 | AstNode *sentinel_expr = node->data.array_type.sentinel; | ||
| 8724 | AstNode *align_expr = node->data.array_type.align_expr; | ||
| 8725 | |||
| 8726 | Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); | ||
| 8727 | |||
| 8728 | IrInstSrc *sentinel; | ||
| 8729 | if (sentinel_expr != nullptr) { | ||
| 8730 | sentinel = ir_gen_node(irb, sentinel_expr, comptime_scope); | ||
| 8731 | if (sentinel == irb->codegen->invalid_inst_src) | ||
| 8732 | return sentinel; | ||
| 8733 | } else { | ||
| 8734 | sentinel = nullptr; | ||
| 8735 | } | ||
| 8736 | |||
| 8737 | if (size_node) { | ||
| 8738 | if (is_const) { | ||
| 8739 | add_node_error(irb->codegen, node, buf_create_from_str("const qualifier invalid on array type")); | ||
| 8740 | return irb->codegen->invalid_inst_src; | ||
| 8741 | } | ||
| 8742 | if (is_volatile) { | ||
| 8743 | add_node_error(irb->codegen, node, buf_create_from_str("volatile qualifier invalid on array type")); | ||
| 8744 | return irb->codegen->invalid_inst_src; | ||
| 8745 | } | ||
| 8746 | if (is_allow_zero) { | ||
| 8747 | add_node_error(irb->codegen, node, buf_create_from_str("allowzero qualifier invalid on array type")); | ||
| 8748 | return irb->codegen->invalid_inst_src; | ||
| 8749 | } | ||
| 8750 | if (align_expr != nullptr) { | ||
| 8751 | add_node_error(irb->codegen, node, buf_create_from_str("align qualifier invalid on array type")); | ||
| 8752 | return irb->codegen->invalid_inst_src; | ||
| 8753 | } | ||
| 8754 | |||
| 8755 | IrInstSrc *size_value = ir_gen_node(irb, size_node, comptime_scope); | ||
| 8756 | if (size_value == irb->codegen->invalid_inst_src) | ||
| 8757 | return size_value; | ||
| 8758 | |||
| 8759 | IrInstSrc *child_type = ir_gen_node(irb, child_type_node, comptime_scope); | ||
| 8760 | if (child_type == irb->codegen->invalid_inst_src) | ||
| 8761 | return child_type; | ||
| 8762 | |||
| 8763 | return ir_build_array_type(irb, scope, node, size_value, sentinel, child_type); | ||
| 8764 | } else { | ||
| 8765 | IrInstSrc *align_value; | ||
| 8766 | if (align_expr != nullptr) { | ||
| 8767 | align_value = ir_gen_node(irb, align_expr, comptime_scope); | ||
| 8768 | if (align_value == irb->codegen->invalid_inst_src) | ||
| 8769 | return align_value; | ||
| 8770 | } else { | ||
| 8771 | align_value = nullptr; | ||
| 8772 | } | ||
| 8773 | |||
| 8774 | IrInstSrc *child_type = ir_gen_node(irb, child_type_node, comptime_scope); | ||
| 8775 | if (child_type == irb->codegen->invalid_inst_src) | ||
| 8776 | return child_type; | ||
| 8777 | |||
| 8778 | return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, sentinel, | ||
| 8779 | align_value, is_allow_zero); | ||
| 8780 | } | ||
| 8781 | } | ||
| 8782 | |||
| 8783 | static IrInstSrc *ir_gen_anyframe_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 8784 | assert(node->type == NodeTypeAnyFrameType); | ||
| 8785 | |||
| 8786 | AstNode *payload_type_node = node->data.anyframe_type.payload_type; | ||
| 8787 | IrInstSrc *payload_type_value = nullptr; | ||
| 8788 | |||
| 8789 | if (payload_type_node != nullptr) { | ||
| 8790 | payload_type_value = ir_gen_node(irb, payload_type_node, scope); | ||
| 8791 | if (payload_type_value == irb->codegen->invalid_inst_src) | ||
| 8792 | return payload_type_value; | ||
| 8793 | |||
| 8794 | } | ||
| 8795 | |||
| 8796 | return ir_build_anyframe_type(irb, scope, node, payload_type_value); | ||
| 8797 | } | ||
| 8798 | |||
| 8799 | static IrInstSrc *ir_gen_undefined_literal(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 8800 | assert(node->type == NodeTypeUndefinedLiteral); | ||
| 8801 | return ir_build_const_undefined(irb, scope, node); | ||
| 8802 | } | ||
| 8803 | |||
| 8804 | static Error parse_asm_template(IrAnalyze *ira, AstNode *source_node, Buf *asm_template, | ||
| 8805 | ZigList<AsmToken> *tok_list) | ||
| 8806 | { | ||
| 8807 | // TODO Connect the errors in this function back up to the actual source location | ||
| 8808 | // rather than just the token. https://github.com/ziglang/zig/issues/2080 | ||
| 8809 | enum State { | ||
| 8810 | StateStart, | ||
| 8811 | StatePercent, | ||
| 8812 | StateTemplate, | ||
| 8813 | StateVar, | ||
| 8814 | }; | ||
| 8815 | |||
| 8816 | assert(tok_list->length == 0); | ||
| 8817 | |||
| 8818 | AsmToken *cur_tok = nullptr; | ||
| 8819 | |||
| 8820 | enum State state = StateStart; | ||
| 8821 | |||
| 8822 | for (size_t i = 0; i < buf_len(asm_template); i += 1) { | ||
| 8823 | uint8_t c = *((uint8_t*)buf_ptr(asm_template) + i); | ||
| 8824 | switch (state) { | ||
| 8825 | case StateStart: | ||
| 8826 | if (c == '%') { | ||
| 8827 | tok_list->add_one(); | ||
| 8828 | cur_tok = &tok_list->last(); | ||
| 8829 | cur_tok->id = AsmTokenIdPercent; | ||
| 8830 | cur_tok->start = i; | ||
| 8831 | state = StatePercent; | ||
| 8832 | } else { | ||
| 8833 | tok_list->add_one(); | ||
| 8834 | cur_tok = &tok_list->last(); | ||
| 8835 | cur_tok->id = AsmTokenIdTemplate; | ||
| 8836 | cur_tok->start = i; | ||
| 8837 | state = StateTemplate; | ||
| 8838 | } | ||
| 8839 | break; | ||
| 8840 | case StatePercent: | ||
| 8841 | if (c == '%') { | ||
| 8842 | cur_tok->end = i; | ||
| 8843 | state = StateStart; | ||
| 8844 | } else if (c == '[') { | ||
| 8845 | cur_tok->id = AsmTokenIdVar; | ||
| 8846 | state = StateVar; | ||
| 8847 | } else if (c == '=') { | ||
| 8848 | cur_tok->id = AsmTokenIdUniqueId; | ||
| 8849 | cur_tok->end = i; | ||
| 8850 | state = StateStart; | ||
| 8851 | } else { | ||
| 8852 | add_node_error(ira->codegen, source_node, | ||
| 8853 | buf_create_from_str("expected a '%' or '['")); | ||
| 8854 | return ErrorSemanticAnalyzeFail; | ||
| 8855 | } | ||
| 8856 | break; | ||
| 8857 | case StateTemplate: | ||
| 8858 | if (c == '%') { | ||
| 8859 | cur_tok->end = i; | ||
| 8860 | i -= 1; | ||
| 8861 | cur_tok = nullptr; | ||
| 8862 | state = StateStart; | ||
| 8863 | } | ||
| 8864 | break; | ||
| 8865 | case StateVar: | ||
| 8866 | if (c == ']') { | ||
| 8867 | cur_tok->end = i; | ||
| 8868 | state = StateStart; | ||
| 8869 | } else if ((c >= 'a' && c <= 'z') || | ||
| 8870 | (c >= '0' && c <= '9') || | ||
| 8871 | (c == '_')) | ||
| 8872 | { | ||
| 8873 | // do nothing | ||
| 8874 | } else { | ||
| 8875 | add_node_error(ira->codegen, source_node, | ||
| 8876 | buf_sprintf("invalid substitution character: '%c'", c)); | ||
| 8877 | return ErrorSemanticAnalyzeFail; | ||
| 8878 | } | ||
| 8879 | break; | ||
| 8880 | } | ||
| 8881 | } | ||
| 8882 | |||
| 8883 | switch (state) { | ||
| 8884 | case StateStart: | ||
| 8885 | break; | ||
| 8886 | case StatePercent: | ||
| 8887 | case StateVar: | ||
| 8888 | add_node_error(ira->codegen, source_node, buf_sprintf("unexpected end of assembly template")); | ||
| 8889 | return ErrorSemanticAnalyzeFail; | ||
| 8890 | case StateTemplate: | ||
| 8891 | cur_tok->end = buf_len(asm_template); | ||
| 8892 | break; | ||
| 8893 | } | ||
| 8894 | return ErrorNone; | ||
| 8895 | } | ||
| 8896 | |||
| 8897 | static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_template) { | ||
| 8898 | const char *ptr = buf_ptr(src_template) + tok->start + 2; | ||
| 8899 | size_t len = tok->end - tok->start - 2; | ||
| 8900 | size_t result = 0; | ||
| 8901 | for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1, result += 1) { | ||
| 8902 | AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); | ||
| 8903 | if (buf_eql_mem(asm_output->asm_symbolic_name, ptr, len)) { | ||
| 8904 | return result; | ||
| 8905 | } | ||
| 8906 | } | ||
| 8907 | for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1, result += 1) { | ||
| 8908 | AsmInput *asm_input = node->data.asm_expr.input_list.at(i); | ||
| 8909 | if (buf_eql_mem(asm_input->asm_symbolic_name, ptr, len)) { | ||
| 8910 | return result; | ||
| 8911 | } | ||
| 8912 | } | ||
| 8913 | return SIZE_MAX; | ||
| 8914 | } | ||
| 8915 | |||
| 8916 | static IrInstSrc *ir_gen_asm_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 8917 | assert(node->type == NodeTypeAsmExpr); | ||
| 8918 | AstNodeAsmExpr *asm_expr = &node->data.asm_expr; | ||
| 8919 | |||
| 8920 | IrInstSrc *asm_template = ir_gen_node(irb, asm_expr->asm_template, scope); | ||
| 8921 | if (asm_template == irb->codegen->invalid_inst_src) | ||
| 8922 | return irb->codegen->invalid_inst_src; | ||
| 8923 | |||
| 8924 | bool is_volatile = asm_expr->volatile_token != nullptr; | ||
| 8925 | bool in_fn_scope = (scope_fn_entry(scope) != nullptr); | ||
| 8926 | |||
| 8927 | if (!in_fn_scope) { | ||
| 8928 | if (is_volatile) { | ||
| 8929 | add_token_error(irb->codegen, node->owner, asm_expr->volatile_token, | ||
| 8930 | buf_sprintf("volatile is meaningless on global assembly")); | ||
| 8931 | return irb->codegen->invalid_inst_src; | ||
| 8932 | } | ||
| 8933 | |||
| 8934 | if (asm_expr->output_list.length != 0 || asm_expr->input_list.length != 0 || | ||
| 8935 | asm_expr->clobber_list.length != 0) | ||
| 8936 | { | ||
| 8937 | add_node_error(irb->codegen, node, | ||
| 8938 | buf_sprintf("global assembly cannot have inputs, outputs, or clobbers")); | ||
| 8939 | return irb->codegen->invalid_inst_src; | ||
| 8940 | } | ||
| 8941 | |||
| 8942 | return ir_build_asm_src(irb, scope, node, asm_template, nullptr, nullptr, | ||
| 8943 | nullptr, 0, is_volatile, true); | ||
| 8944 | } | ||
| 8945 | |||
| 8946 | IrInstSrc **input_list = heap::c_allocator.allocate<IrInstSrc *>(asm_expr->input_list.length); | ||
| 8947 | IrInstSrc **output_types = heap::c_allocator.allocate<IrInstSrc *>(asm_expr->output_list.length); | ||
| 8948 | ZigVar **output_vars = heap::c_allocator.allocate<ZigVar *>(asm_expr->output_list.length); | ||
| 8949 | size_t return_count = 0; | ||
| 8950 | if (!is_volatile && asm_expr->output_list.length == 0) { | ||
| 8951 | add_node_error(irb->codegen, node, | ||
| 8952 | buf_sprintf("assembly expression with no output must be marked volatile")); | ||
| 8953 | return irb->codegen->invalid_inst_src; | ||
| 8954 | } | ||
| 8955 | for (size_t i = 0; i < asm_expr->output_list.length; i += 1) { | ||
| 8956 | AsmOutput *asm_output = asm_expr->output_list.at(i); | ||
| 8957 | if (asm_output->return_type) { | ||
| 8958 | return_count += 1; | ||
| 8959 | |||
| 8960 | IrInstSrc *return_type = ir_gen_node(irb, asm_output->return_type, scope); | ||
| 8961 | if (return_type == irb->codegen->invalid_inst_src) | ||
| 8962 | return irb->codegen->invalid_inst_src; | ||
| 8963 | if (return_count > 1) { | ||
| 8964 | add_node_error(irb->codegen, node, | ||
| 8965 | buf_sprintf("inline assembly allows up to one output value")); | ||
| 8966 | return irb->codegen->invalid_inst_src; | ||
| 8967 | } | ||
| 8968 | output_types[i] = return_type; | ||
| 8969 | } else { | ||
| 8970 | Buf *variable_name = asm_output->variable_name; | ||
| 8971 | // TODO there is some duplication here with ir_gen_symbol. I need to do a full audit of how | ||
| 8972 | // inline assembly works. https://github.com/ziglang/zig/issues/215 | ||
| 8973 | ZigVar *var = find_variable(irb->codegen, scope, variable_name, nullptr); | ||
| 8974 | if (var) { | ||
| 8975 | output_vars[i] = var; | ||
| 8976 | } else { | ||
| 8977 | add_node_error(irb->codegen, node, | ||
| 8978 | buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); | ||
| 8979 | return irb->codegen->invalid_inst_src; | ||
| 8980 | } | ||
| 8981 | } | ||
| 8982 | |||
| 8983 | const char modifier = *buf_ptr(asm_output->constraint); | ||
| 8984 | if (modifier != '=') { | ||
| 8985 | add_node_error(irb->codegen, node, | ||
| 8986 | buf_sprintf("invalid modifier starting output constraint for '%s': '%c', only '=' is supported." | ||
| 8987 | " Compiler TODO: see https://github.com/ziglang/zig/issues/215", | ||
| 8988 | buf_ptr(asm_output->asm_symbolic_name), modifier)); | ||
| 8989 | return irb->codegen->invalid_inst_src; | ||
| 8990 | } | ||
| 8991 | } | ||
| 8992 | for (size_t i = 0; i < asm_expr->input_list.length; i += 1) { | ||
| 8993 | AsmInput *asm_input = asm_expr->input_list.at(i); | ||
| 8994 | IrInstSrc *input_value = ir_gen_node(irb, asm_input->expr, scope); | ||
| 8995 | if (input_value == irb->codegen->invalid_inst_src) | ||
| 8996 | return irb->codegen->invalid_inst_src; | ||
| 8997 | |||
| 8998 | input_list[i] = input_value; | ||
| 8999 | } | ||
| 9000 | |||
| 9001 | return ir_build_asm_src(irb, scope, node, asm_template, input_list, output_types, | ||
| 9002 | output_vars, return_count, is_volatile, false); | ||
| 9003 | } | ||
| 9004 | |||
| 9005 | static IrInstSrc *ir_gen_if_optional_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, | ||
| 9006 | ResultLoc *result_loc) | ||
| 9007 | { | ||
| 9008 | assert(node->type == NodeTypeIfOptional); | ||
| 9009 | |||
| 9010 | Buf *var_symbol = node->data.test_expr.var_symbol; | ||
| 9011 | AstNode *expr_node = node->data.test_expr.target_node; | ||
| 9012 | AstNode *then_node = node->data.test_expr.then_node; | ||
| 9013 | AstNode *else_node = node->data.test_expr.else_node; | ||
| 9014 | bool var_is_ptr = node->data.test_expr.var_is_ptr; | ||
| 9015 | |||
| 9016 | ScopeExpr *spill_scope = create_expr_scope(irb->codegen, expr_node, scope); | ||
| 9017 | spill_scope->spill_harder = true; | ||
| 9018 | |||
| 9019 | IrInstSrc *maybe_val_ptr = ir_gen_node_extra(irb, expr_node, &spill_scope->base, LValPtr, nullptr); | ||
| 9020 | if (maybe_val_ptr == irb->codegen->invalid_inst_src) | ||
| 9021 | return maybe_val_ptr; | ||
| 9022 | |||
| 9023 | IrInstSrc *maybe_val = ir_build_load_ptr(irb, scope, node, maybe_val_ptr); | ||
| 9024 | IrInstSrc *is_non_null = ir_build_test_non_null_src(irb, scope, node, maybe_val); | ||
| 9025 | |||
| 9026 | IrBasicBlockSrc *then_block = ir_create_basic_block(irb, scope, "OptionalThen"); | ||
| 9027 | IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "OptionalElse"); | ||
| 9028 | IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "OptionalEndIf"); | ||
| 9029 | |||
| 9030 | IrInstSrc *is_comptime; | ||
| 9031 | if (ir_should_inline(irb->exec, scope)) { | ||
| 9032 | is_comptime = ir_build_const_bool(irb, scope, node, true); | ||
| 9033 | } else { | ||
| 9034 | is_comptime = ir_build_test_comptime(irb, scope, node, is_non_null); | ||
| 9035 | } | ||
| 9036 | IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, is_non_null, | ||
| 9037 | then_block, else_block, is_comptime); | ||
| 9038 | |||
| 9039 | ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, | ||
| 9040 | result_loc, is_comptime); | ||
| 9041 | |||
| 9042 | ir_set_cursor_at_end_and_append_block(irb, then_block); | ||
| 9043 | |||
| 9044 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, &spill_scope->base, is_comptime); | ||
| 9045 | Scope *var_scope; | ||
| 9046 | if (var_symbol) { | ||
| 9047 | bool is_shadowable = false; | ||
| 9048 | bool is_const = true; | ||
| 9049 | ZigVar *var = ir_create_var(irb, node, subexpr_scope, | ||
| 9050 | var_symbol, is_const, is_const, is_shadowable, is_comptime); | ||
| 9051 | |||
| 9052 | IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false); | ||
| 9053 | IrInstSrc *var_value = var_is_ptr ? | ||
| 9054 | payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, node, payload_ptr); | ||
| 9055 | build_decl_var_and_init(irb, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), is_comptime); | ||
| 9056 | var_scope = var->child_scope; | ||
| 9057 | } else { | ||
| 9058 | var_scope = subexpr_scope; | ||
| 9059 | } | ||
| 9060 | IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval, | ||
| 9061 | &peer_parent->peers.at(0)->base); | ||
| 9062 | if (then_expr_result == irb->codegen->invalid_inst_src) | ||
| 9063 | return then_expr_result; | ||
| 9064 | IrBasicBlockSrc *after_then_block = irb->current_basic_block; | ||
| 9065 | if (!instr_is_unreachable(then_expr_result)) | ||
| 9066 | ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); | ||
| 9067 | |||
| 9068 | ir_set_cursor_at_end_and_append_block(irb, else_block); | ||
| 9069 | IrInstSrc *else_expr_result; | ||
| 9070 | if (else_node) { | ||
| 9071 | else_expr_result = ir_gen_node_extra(irb, else_node, subexpr_scope, lval, &peer_parent->peers.at(1)->base); | ||
| 9072 | if (else_expr_result == irb->codegen->invalid_inst_src) | ||
| 9073 | return else_expr_result; | ||
| 9074 | } else { | ||
| 9075 | else_expr_result = ir_build_const_void(irb, scope, node); | ||
| 9076 | ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); | ||
| 9077 | } | ||
| 9078 | IrBasicBlockSrc *after_else_block = irb->current_basic_block; | ||
| 9079 | if (!instr_is_unreachable(else_expr_result)) | ||
| 9080 | ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); | ||
| 9081 | |||
| 9082 | ir_set_cursor_at_end_and_append_block(irb, endif_block); | ||
| 9083 | IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2); | ||
| 9084 | incoming_values[0] = then_expr_result; | ||
| 9085 | incoming_values[1] = else_expr_result; | ||
| 9086 | IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate<IrBasicBlockSrc *>(2); | ||
| 9087 | incoming_blocks[0] = after_then_block; | ||
| 9088 | incoming_blocks[1] = after_else_block; | ||
| 9089 | |||
| 9090 | IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); | ||
| 9091 | return ir_expr_wrap(irb, scope, phi, result_loc); | ||
| 9092 | } | ||
| 9093 | |||
| 9094 | static IrInstSrc *ir_gen_if_err_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, | ||
| 9095 | ResultLoc *result_loc) | ||
| 9096 | { | ||
| 9097 | assert(node->type == NodeTypeIfErrorExpr); | ||
| 9098 | |||
| 9099 | AstNode *target_node = node->data.if_err_expr.target_node; | ||
| 9100 | AstNode *then_node = node->data.if_err_expr.then_node; | ||
| 9101 | AstNode *else_node = node->data.if_err_expr.else_node; | ||
| 9102 | bool var_is_ptr = node->data.if_err_expr.var_is_ptr; | ||
| 9103 | bool var_is_const = true; | ||
| 9104 | Buf *var_symbol = node->data.if_err_expr.var_symbol; | ||
| 9105 | Buf *err_symbol = node->data.if_err_expr.err_symbol; | ||
| 9106 | |||
| 9107 | IrInstSrc *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr); | ||
| 9108 | if (err_val_ptr == irb->codegen->invalid_inst_src) | ||
| 9109 | return err_val_ptr; | ||
| 9110 | |||
| 9111 | IrInstSrc *err_val = ir_build_load_ptr(irb, scope, node, err_val_ptr); | ||
| 9112 | IrInstSrc *is_err = ir_build_test_err_src(irb, scope, node, err_val_ptr, true, false); | ||
| 9113 | |||
| 9114 | IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, scope, "TryOk"); | ||
| 9115 | IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "TryElse"); | ||
| 9116 | IrBasicBlockSrc *endif_block = ir_create_basic_block(irb, scope, "TryEnd"); | ||
| 9117 | |||
| 9118 | bool force_comptime = ir_should_inline(irb->exec, scope); | ||
| 9119 | IrInstSrc *is_comptime = force_comptime ? ir_build_const_bool(irb, scope, node, true) : ir_build_test_comptime(irb, scope, node, is_err); | ||
| 9120 | IrInstSrc *cond_br_inst = ir_build_cond_br(irb, scope, node, is_err, else_block, ok_block, is_comptime); | ||
| 9121 | |||
| 9122 | ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, else_block, endif_block, | ||
| 9123 | result_loc, is_comptime); | ||
| 9124 | |||
| 9125 | ir_set_cursor_at_end_and_append_block(irb, ok_block); | ||
| 9126 | |||
| 9127 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); | ||
| 9128 | Scope *var_scope; | ||
| 9129 | if (var_symbol) { | ||
| 9130 | bool is_shadowable = false; | ||
| 9131 | IrInstSrc *var_is_comptime = force_comptime ? ir_build_const_bool(irb, subexpr_scope, node, true) : ir_build_test_comptime(irb, subexpr_scope, node, err_val); | ||
| 9132 | ZigVar *var = ir_create_var(irb, node, subexpr_scope, | ||
| 9133 | var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime); | ||
| 9134 | |||
| 9135 | IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, subexpr_scope, node, err_val_ptr, false, false); | ||
| 9136 | IrInstSrc *var_value = var_is_ptr ? | ||
| 9137 | payload_ptr : ir_build_load_ptr(irb, subexpr_scope, node, payload_ptr); | ||
| 9138 | build_decl_var_and_init(irb, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), var_is_comptime); | ||
| 9139 | var_scope = var->child_scope; | ||
| 9140 | } else { | ||
| 9141 | var_scope = subexpr_scope; | ||
| 9142 | } | ||
| 9143 | IrInstSrc *then_expr_result = ir_gen_node_extra(irb, then_node, var_scope, lval, | ||
| 9144 | &peer_parent->peers.at(0)->base); | ||
| 9145 | if (then_expr_result == irb->codegen->invalid_inst_src) | ||
| 9146 | return then_expr_result; | ||
| 9147 | IrBasicBlockSrc *after_then_block = irb->current_basic_block; | ||
| 9148 | if (!instr_is_unreachable(then_expr_result)) | ||
| 9149 | ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); | ||
| 9150 | |||
| 9151 | ir_set_cursor_at_end_and_append_block(irb, else_block); | ||
| 9152 | |||
| 9153 | IrInstSrc *else_expr_result; | ||
| 9154 | if (else_node) { | ||
| 9155 | Scope *err_var_scope; | ||
| 9156 | if (err_symbol) { | ||
| 9157 | bool is_shadowable = false; | ||
| 9158 | bool is_const = true; | ||
| 9159 | ZigVar *var = ir_create_var(irb, node, subexpr_scope, | ||
| 9160 | err_symbol, is_const, is_const, is_shadowable, is_comptime); | ||
| 9161 | |||
| 9162 | IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, subexpr_scope, node, err_val_ptr); | ||
| 9163 | IrInstSrc *err_value = ir_build_load_ptr(irb, subexpr_scope, node, err_ptr); | ||
| 9164 | build_decl_var_and_init(irb, subexpr_scope, node, var, err_value, buf_ptr(err_symbol), is_comptime); | ||
| 9165 | err_var_scope = var->child_scope; | ||
| 9166 | } else { | ||
| 9167 | err_var_scope = subexpr_scope; | ||
| 9168 | } | ||
| 9169 | else_expr_result = ir_gen_node_extra(irb, else_node, err_var_scope, lval, &peer_parent->peers.at(1)->base); | ||
| 9170 | if (else_expr_result == irb->codegen->invalid_inst_src) | ||
| 9171 | return else_expr_result; | ||
| 9172 | } else { | ||
| 9173 | else_expr_result = ir_build_const_void(irb, scope, node); | ||
| 9174 | ir_build_end_expr(irb, scope, node, else_expr_result, &peer_parent->peers.at(1)->base); | ||
| 9175 | } | ||
| 9176 | IrBasicBlockSrc *after_else_block = irb->current_basic_block; | ||
| 9177 | if (!instr_is_unreachable(else_expr_result)) | ||
| 9178 | ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); | ||
| 9179 | |||
| 9180 | ir_set_cursor_at_end_and_append_block(irb, endif_block); | ||
| 9181 | IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2); | ||
| 9182 | incoming_values[0] = then_expr_result; | ||
| 9183 | incoming_values[1] = else_expr_result; | ||
| 9184 | IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate<IrBasicBlockSrc *>(2); | ||
| 9185 | incoming_blocks[0] = after_then_block; | ||
| 9186 | incoming_blocks[1] = after_else_block; | ||
| 9187 | |||
| 9188 | IrInstSrc *phi = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values, peer_parent); | ||
| 9189 | return ir_expr_wrap(irb, scope, phi, result_loc); | ||
| 9190 | } | ||
| 9191 | |||
| 9192 | static bool ir_gen_switch_prong_expr(IrBuilderSrc *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node, | ||
| 9193 | IrBasicBlockSrc *end_block, IrInstSrc *is_comptime, IrInstSrc *var_is_comptime, | ||
| 9194 | IrInstSrc *target_value_ptr, IrInstSrc **prong_values, size_t prong_values_len, | ||
| 9195 | ZigList<IrBasicBlockSrc *> *incoming_blocks, ZigList<IrInstSrc *> *incoming_values, | ||
| 9196 | IrInstSrcSwitchElseVar **out_switch_else_var, LVal lval, ResultLoc *result_loc) | ||
| 9197 | { | ||
| 9198 | assert(switch_node->type == NodeTypeSwitchExpr); | ||
| 9199 | assert(prong_node->type == NodeTypeSwitchProng); | ||
| 9200 | |||
| 9201 | AstNode *expr_node = prong_node->data.switch_prong.expr; | ||
| 9202 | AstNode *var_symbol_node = prong_node->data.switch_prong.var_symbol; | ||
| 9203 | Scope *child_scope; | ||
| 9204 | if (var_symbol_node) { | ||
| 9205 | assert(var_symbol_node->type == NodeTypeSymbol); | ||
| 9206 | Buf *var_name = var_symbol_node->data.symbol_expr.symbol; | ||
| 9207 | bool var_is_ptr = prong_node->data.switch_prong.var_is_ptr; | ||
| 9208 | |||
| 9209 | bool is_shadowable = false; | ||
| 9210 | bool is_const = true; | ||
| 9211 | ZigVar *var = ir_create_var(irb, var_symbol_node, scope, | ||
| 9212 | var_name, is_const, is_const, is_shadowable, var_is_comptime); | ||
| 9213 | child_scope = var->child_scope; | ||
| 9214 | IrInstSrc *var_value; | ||
| 9215 | if (out_switch_else_var != nullptr) { | ||
| 9216 | IrInstSrcSwitchElseVar *switch_else_var = ir_build_switch_else_var(irb, scope, var_symbol_node, | ||
| 9217 | target_value_ptr); | ||
| 9218 | *out_switch_else_var = switch_else_var; | ||
| 9219 | IrInstSrc *payload_ptr = &switch_else_var->base; | ||
| 9220 | var_value = var_is_ptr ? | ||
| 9221 | payload_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, payload_ptr); | ||
| 9222 | } else if (prong_values != nullptr) { | ||
| 9223 | IrInstSrc *payload_ptr = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr, | ||
| 9224 | prong_values, prong_values_len); | ||
| 9225 | var_value = var_is_ptr ? | ||
| 9226 | payload_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, payload_ptr); | ||
| 9227 | } else { | ||
| 9228 | var_value = var_is_ptr ? | ||
| 9229 | target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr); | ||
| 9230 | } | ||
| 9231 | build_decl_var_and_init(irb, scope, var_symbol_node, var, var_value, buf_ptr(var_name), var_is_comptime); | ||
| 9232 | } else { | ||
| 9233 | child_scope = scope; | ||
| 9234 | } | ||
| 9235 | |||
| 9236 | IrInstSrc *expr_result = ir_gen_node_extra(irb, expr_node, child_scope, lval, result_loc); | ||
| 9237 | if (expr_result == irb->codegen->invalid_inst_src) | ||
| 9238 | return false; | ||
| 9239 | if (!instr_is_unreachable(expr_result)) | ||
| 9240 | ir_mark_gen(ir_build_br(irb, scope, switch_node, end_block, is_comptime)); | ||
| 9241 | incoming_blocks->append(irb->current_basic_block); | ||
| 9242 | incoming_values->append(expr_result); | ||
| 9243 | return true; | ||
| 9244 | } | ||
| 9245 | |||
| 9246 | static IrInstSrc *ir_gen_switch_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, | ||
| 9247 | ResultLoc *result_loc) | ||
| 9248 | { | ||
| 9249 | assert(node->type == NodeTypeSwitchExpr); | ||
| 9250 | |||
| 9251 | AstNode *target_node = node->data.switch_expr.expr; | ||
| 9252 | IrInstSrc *target_value_ptr = ir_gen_node_extra(irb, target_node, scope, LValPtr, nullptr); | ||
| 9253 | if (target_value_ptr == irb->codegen->invalid_inst_src) | ||
| 9254 | return target_value_ptr; | ||
| 9255 | IrInstSrc *target_value = ir_build_switch_target(irb, scope, node, target_value_ptr); | ||
| 9256 | |||
| 9257 | IrBasicBlockSrc *else_block = ir_create_basic_block(irb, scope, "SwitchElse"); | ||
| 9258 | IrBasicBlockSrc *end_block = ir_create_basic_block(irb, scope, "SwitchEnd"); | ||
| 9259 | |||
| 9260 | size_t prong_count = node->data.switch_expr.prongs.length; | ||
| 9261 | ZigList<IrInstSrcSwitchBrCase> cases = {0}; | ||
| 9262 | |||
| 9263 | IrInstSrc *is_comptime; | ||
| 9264 | IrInstSrc *var_is_comptime; | ||
| 9265 | if (ir_should_inline(irb->exec, scope)) { | ||
| 9266 | is_comptime = ir_build_const_bool(irb, scope, node, true); | ||
| 9267 | var_is_comptime = is_comptime; | ||
| 9268 | } else { | ||
| 9269 | is_comptime = ir_build_test_comptime(irb, scope, node, target_value); | ||
| 9270 | var_is_comptime = ir_build_test_comptime(irb, scope, node, target_value_ptr); | ||
| 9271 | } | ||
| 9272 | |||
| 9273 | ZigList<IrInstSrc *> incoming_values = {0}; | ||
| 9274 | ZigList<IrBasicBlockSrc *> incoming_blocks = {0}; | ||
| 9275 | ZigList<IrInstSrcCheckSwitchProngsRange> check_ranges = {0}; | ||
| 9276 | |||
| 9277 | IrInstSrcSwitchElseVar *switch_else_var = nullptr; | ||
| 9278 | |||
| 9279 | ResultLocPeerParent *peer_parent = heap::c_allocator.create<ResultLocPeerParent>(); | ||
| 9280 | peer_parent->base.id = ResultLocIdPeerParent; | ||
| 9281 | peer_parent->base.allow_write_through_const = result_loc->allow_write_through_const; | ||
| 9282 | peer_parent->end_bb = end_block; | ||
| 9283 | peer_parent->is_comptime = is_comptime; | ||
| 9284 | peer_parent->parent = result_loc; | ||
| 9285 | |||
| 9286 | ir_build_reset_result(irb, scope, node, &peer_parent->base); | ||
| 9287 | |||
| 9288 | // First do the else and the ranges | ||
| 9289 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); | ||
| 9290 | Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); | ||
| 9291 | AstNode *else_prong = nullptr; | ||
| 9292 | AstNode *underscore_prong = nullptr; | ||
| 9293 | for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { | ||
| 9294 | AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); | ||
| 9295 | size_t prong_item_count = prong_node->data.switch_prong.items.length; | ||
| 9296 | if (prong_node->data.switch_prong.any_items_are_range) { | ||
| 9297 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); | ||
| 9298 | |||
| 9299 | IrInstSrc *ok_bit = nullptr; | ||
| 9300 | AstNode *last_item_node = nullptr; | ||
| 9301 | for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { | ||
| 9302 | AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); | ||
| 9303 | last_item_node = item_node; | ||
| 9304 | if (item_node->type == NodeTypeSwitchRange) { | ||
| 9305 | AstNode *start_node = item_node->data.switch_range.start; | ||
| 9306 | AstNode *end_node = item_node->data.switch_range.end; | ||
| 9307 | |||
| 9308 | IrInstSrc *start_value = ir_gen_node(irb, start_node, comptime_scope); | ||
| 9309 | if (start_value == irb->codegen->invalid_inst_src) | ||
| 9310 | return irb->codegen->invalid_inst_src; | ||
| 9311 | |||
| 9312 | IrInstSrc *end_value = ir_gen_node(irb, end_node, comptime_scope); | ||
| 9313 | if (end_value == irb->codegen->invalid_inst_src) | ||
| 9314 | return irb->codegen->invalid_inst_src; | ||
| 9315 | |||
| 9316 | IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); | ||
| 9317 | check_range->start = start_value; | ||
| 9318 | check_range->end = end_value; | ||
| 9319 | |||
| 9320 | IrInstSrc *lower_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpGreaterOrEq, | ||
| 9321 | target_value, start_value, false); | ||
| 9322 | IrInstSrc *upper_range_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpLessOrEq, | ||
| 9323 | target_value, end_value, false); | ||
| 9324 | IrInstSrc *both_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolAnd, | ||
| 9325 | lower_range_ok, upper_range_ok, false); | ||
| 9326 | if (ok_bit) { | ||
| 9327 | ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, both_ok, ok_bit, false); | ||
| 9328 | } else { | ||
| 9329 | ok_bit = both_ok; | ||
| 9330 | } | ||
| 9331 | } else { | ||
| 9332 | IrInstSrc *item_value = ir_gen_node(irb, item_node, comptime_scope); | ||
| 9333 | if (item_value == irb->codegen->invalid_inst_src) | ||
| 9334 | return irb->codegen->invalid_inst_src; | ||
| 9335 | |||
| 9336 | IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); | ||
| 9337 | check_range->start = item_value; | ||
| 9338 | check_range->end = item_value; | ||
| 9339 | |||
| 9340 | IrInstSrc *cmp_ok = ir_build_bin_op(irb, scope, item_node, IrBinOpCmpEq, | ||
| 9341 | item_value, target_value, false); | ||
| 9342 | if (ok_bit) { | ||
| 9343 | ok_bit = ir_build_bin_op(irb, scope, item_node, IrBinOpBoolOr, cmp_ok, ok_bit, false); | ||
| 9344 | } else { | ||
| 9345 | ok_bit = cmp_ok; | ||
| 9346 | } | ||
| 9347 | } | ||
| 9348 | } | ||
| 9349 | |||
| 9350 | IrBasicBlockSrc *range_block_yes = ir_create_basic_block(irb, scope, "SwitchRangeYes"); | ||
| 9351 | IrBasicBlockSrc *range_block_no = ir_create_basic_block(irb, scope, "SwitchRangeNo"); | ||
| 9352 | |||
| 9353 | assert(ok_bit); | ||
| 9354 | assert(last_item_node); | ||
| 9355 | IrInstSrc *br_inst = ir_mark_gen(ir_build_cond_br(irb, scope, last_item_node, ok_bit, | ||
| 9356 | range_block_yes, range_block_no, is_comptime)); | ||
| 9357 | if (peer_parent->base.source_instruction == nullptr) { | ||
| 9358 | peer_parent->base.source_instruction = br_inst; | ||
| 9359 | } | ||
| 9360 | |||
| 9361 | if (peer_parent->peers.length > 0) { | ||
| 9362 | peer_parent->peers.last()->next_bb = range_block_yes; | ||
| 9363 | } | ||
| 9364 | peer_parent->peers.append(this_peer_result_loc); | ||
| 9365 | ir_set_cursor_at_end_and_append_block(irb, range_block_yes); | ||
| 9366 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, | ||
| 9367 | is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, | ||
| 9368 | &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base)) | ||
| 9369 | { | ||
| 9370 | return irb->codegen->invalid_inst_src; | ||
| 9371 | } | ||
| 9372 | |||
| 9373 | ir_set_cursor_at_end_and_append_block(irb, range_block_no); | ||
| 9374 | } else { | ||
| 9375 | if (prong_item_count == 0) { | ||
| 9376 | if (else_prong) { | ||
| 9377 | ErrorMsg *msg = add_node_error(irb->codegen, prong_node, | ||
| 9378 | buf_sprintf("multiple else prongs in switch expression")); | ||
| 9379 | add_error_note(irb->codegen, msg, else_prong, | ||
| 9380 | buf_sprintf("previous else prong is here")); | ||
| 9381 | return irb->codegen->invalid_inst_src; | ||
| 9382 | } | ||
| 9383 | else_prong = prong_node; | ||
| 9384 | } else if (prong_item_count == 1 && | ||
| 9385 | prong_node->data.switch_prong.items.at(0)->type == NodeTypeSymbol && | ||
| 9386 | buf_eql_str(prong_node->data.switch_prong.items.at(0)->data.symbol_expr.symbol, "_")) { | ||
| 9387 | if (underscore_prong) { | ||
| 9388 | ErrorMsg *msg = add_node_error(irb->codegen, prong_node, | ||
| 9389 | buf_sprintf("multiple '_' prongs in switch expression")); | ||
| 9390 | add_error_note(irb->codegen, msg, underscore_prong, | ||
| 9391 | buf_sprintf("previous '_' prong is here")); | ||
| 9392 | return irb->codegen->invalid_inst_src; | ||
| 9393 | } | ||
| 9394 | underscore_prong = prong_node; | ||
| 9395 | } else { | ||
| 9396 | continue; | ||
| 9397 | } | ||
| 9398 | if (underscore_prong && else_prong) { | ||
| 9399 | ErrorMsg *msg = add_node_error(irb->codegen, prong_node, | ||
| 9400 | buf_sprintf("else and '_' prong in switch expression")); | ||
| 9401 | if (underscore_prong == prong_node) | ||
| 9402 | add_error_note(irb->codegen, msg, else_prong, | ||
| 9403 | buf_sprintf("else prong is here")); | ||
| 9404 | else | ||
| 9405 | add_error_note(irb->codegen, msg, underscore_prong, | ||
| 9406 | buf_sprintf("'_' prong is here")); | ||
| 9407 | return irb->codegen->invalid_inst_src; | ||
| 9408 | } | ||
| 9409 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); | ||
| 9410 | |||
| 9411 | IrBasicBlockSrc *prev_block = irb->current_basic_block; | ||
| 9412 | if (peer_parent->peers.length > 0) { | ||
| 9413 | peer_parent->peers.last()->next_bb = else_block; | ||
| 9414 | } | ||
| 9415 | peer_parent->peers.append(this_peer_result_loc); | ||
| 9416 | ir_set_cursor_at_end_and_append_block(irb, else_block); | ||
| 9417 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, | ||
| 9418 | is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values, | ||
| 9419 | &switch_else_var, LValNone, &this_peer_result_loc->base)) | ||
| 9420 | { | ||
| 9421 | return irb->codegen->invalid_inst_src; | ||
| 9422 | } | ||
| 9423 | ir_set_cursor_at_end(irb, prev_block); | ||
| 9424 | } | ||
| 9425 | } | ||
| 9426 | 2138 | ||
| 9427 | // next do the non-else non-ranges | 2139 | ir_ref_inst_gen(ptr); |
| 9428 | for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { | ||
| 9429 | AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); | ||
| 9430 | size_t prong_item_count = prong_node->data.switch_prong.items.length; | ||
| 9431 | if (prong_item_count == 0) | ||
| 9432 | continue; | ||
| 9433 | if (prong_node->data.switch_prong.any_items_are_range) | ||
| 9434 | continue; | ||
| 9435 | if (underscore_prong == prong_node) | ||
| 9436 | continue; | ||
| 9437 | 2140 | ||
| 9438 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); | 2141 | return &instruction->base; |
| 2142 | } | ||
| 9439 | 2143 | ||
| 9440 | IrBasicBlockSrc *prong_block = ir_create_basic_block(irb, scope, "SwitchProng"); | 2144 | static IrInstGen *ir_build_atomic_store_gen(IrAnalyze *ira, IrInst *source_instr, |
| 9441 | IrInstSrc **items = heap::c_allocator.allocate<IrInstSrc *>(prong_item_count); | 2145 | IrInstGen *ptr, IrInstGen *value, AtomicOrder ordering) |
| 2146 | { | ||
| 2147 | IrInstGenAtomicStore *instruction = ir_build_inst_void<IrInstGenAtomicStore>(&ira->new_irb, | ||
| 2148 | source_instr->scope, source_instr->source_node); | ||
| 2149 | instruction->ptr = ptr; | ||
| 2150 | instruction->value = value; | ||
| 2151 | instruction->ordering = ordering; | ||
| 9442 | 2152 | ||
| 9443 | for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) { | 2153 | ir_ref_inst_gen(ptr); |
| 9444 | AstNode *item_node = prong_node->data.switch_prong.items.at(item_i); | 2154 | ir_ref_inst_gen(value); |
| 9445 | assert(item_node->type != NodeTypeSwitchRange); | ||
| 9446 | 2155 | ||
| 9447 | IrInstSrc *item_value = ir_gen_node(irb, item_node, comptime_scope); | 2156 | return &instruction->base; |
| 9448 | if (item_value == irb->codegen->invalid_inst_src) | 2157 | } |
| 9449 | return irb->codegen->invalid_inst_src; | ||
| 9450 | 2158 | ||
| 9451 | IrInstSrcCheckSwitchProngsRange *check_range = check_ranges.add_one(); | ||
| 9452 | check_range->start = item_value; | ||
| 9453 | check_range->end = item_value; | ||
| 9454 | 2159 | ||
| 9455 | IrInstSrcSwitchBrCase *this_case = cases.add_one(); | 2160 | static IrInstGen *ir_build_vector_to_array(IrAnalyze *ira, IrInst *source_instruction, |
| 9456 | this_case->value = item_value; | 2161 | ZigType *result_type, IrInstGen *vector, IrInstGen *result_loc) |
| 9457 | this_case->block = prong_block; | 2162 | { |
| 2163 | IrInstGenVectorToArray *instruction = ir_build_inst_gen<IrInstGenVectorToArray>(&ira->new_irb, | ||
| 2164 | source_instruction->scope, source_instruction->source_node); | ||
| 2165 | instruction->base.value->type = result_type; | ||
| 2166 | instruction->vector = vector; | ||
| 2167 | instruction->result_loc = result_loc; | ||
| 9458 | 2168 | ||
| 9459 | items[item_i] = item_value; | 2169 | ir_ref_inst_gen(vector); |
| 9460 | } | 2170 | ir_ref_inst_gen(result_loc); |
| 9461 | 2171 | ||
| 9462 | IrBasicBlockSrc *prev_block = irb->current_basic_block; | 2172 | return &instruction->base; |
| 9463 | if (peer_parent->peers.length > 0) { | 2173 | } |
| 9464 | peer_parent->peers.last()->next_bb = prong_block; | ||
| 9465 | } | ||
| 9466 | peer_parent->peers.append(this_peer_result_loc); | ||
| 9467 | ir_set_cursor_at_end_and_append_block(irb, prong_block); | ||
| 9468 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, | ||
| 9469 | is_comptime, var_is_comptime, target_value_ptr, items, prong_item_count, | ||
| 9470 | &incoming_blocks, &incoming_values, nullptr, LValNone, &this_peer_result_loc->base)) | ||
| 9471 | { | ||
| 9472 | return irb->codegen->invalid_inst_src; | ||
| 9473 | } | ||
| 9474 | 2174 | ||
| 9475 | ir_set_cursor_at_end(irb, prev_block); | 2175 | static IrInstGen *ir_build_ptr_of_array_to_slice(IrAnalyze *ira, IrInst *source_instruction, |
| 2176 | ZigType *result_type, IrInstGen *operand, IrInstGen *result_loc) | ||
| 2177 | { | ||
| 2178 | IrInstGenPtrOfArrayToSlice *instruction = ir_build_inst_gen<IrInstGenPtrOfArrayToSlice>(&ira->new_irb, | ||
| 2179 | source_instruction->scope, source_instruction->source_node); | ||
| 2180 | instruction->base.value->type = result_type; | ||
| 2181 | instruction->operand = operand; | ||
| 2182 | instruction->result_loc = result_loc; | ||
| 9476 | 2183 | ||
| 9477 | } | 2184 | ir_ref_inst_gen(operand); |
| 2185 | ir_ref_inst_gen(result_loc); | ||
| 9478 | 2186 | ||
| 9479 | IrInstSrc *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value, | 2187 | return &instruction->base; |
| 9480 | check_ranges.items, check_ranges.length, else_prong, underscore_prong != nullptr); | 2188 | } |
| 9481 | 2189 | ||
| 9482 | IrInstSrc *br_instruction; | 2190 | static IrInstGen *ir_build_array_to_vector(IrAnalyze *ira, IrInst *source_instruction, |
| 9483 | if (cases.length == 0) { | 2191 | IrInstGen *array, ZigType *result_type) |
| 9484 | br_instruction = ir_build_br(irb, scope, node, else_block, is_comptime); | 2192 | { |
| 9485 | } else { | 2193 | IrInstGenArrayToVector *instruction = ir_build_inst_gen<IrInstGenArrayToVector>(&ira->new_irb, |
| 9486 | IrInstSrcSwitchBr *switch_br = ir_build_switch_br_src(irb, scope, node, target_value, else_block, | 2194 | source_instruction->scope, source_instruction->source_node); |
| 9487 | cases.length, cases.items, is_comptime, switch_prongs_void); | 2195 | instruction->base.value->type = result_type; |
| 9488 | if (switch_else_var != nullptr) { | 2196 | instruction->array = array; |
| 9489 | switch_else_var->switch_br = switch_br; | ||
| 9490 | } | ||
| 9491 | br_instruction = &switch_br->base; | ||
| 9492 | } | ||
| 9493 | if (peer_parent->base.source_instruction == nullptr) { | ||
| 9494 | peer_parent->base.source_instruction = br_instruction; | ||
| 9495 | } | ||
| 9496 | for (size_t i = 0; i < peer_parent->peers.length; i += 1) { | ||
| 9497 | peer_parent->peers.at(i)->base.source_instruction = peer_parent->base.source_instruction; | ||
| 9498 | } | ||
| 9499 | 2197 | ||
| 9500 | if (!else_prong && !underscore_prong) { | 2198 | ir_ref_inst_gen(array); |
| 9501 | if (peer_parent->peers.length != 0) { | ||
| 9502 | peer_parent->peers.last()->next_bb = else_block; | ||
| 9503 | } | ||
| 9504 | ir_set_cursor_at_end_and_append_block(irb, else_block); | ||
| 9505 | ir_build_unreachable(irb, scope, node); | ||
| 9506 | } else { | ||
| 9507 | if (peer_parent->peers.length != 0) { | ||
| 9508 | peer_parent->peers.last()->next_bb = end_block; | ||
| 9509 | } | ||
| 9510 | } | ||
| 9511 | 2199 | ||
| 9512 | ir_set_cursor_at_end_and_append_block(irb, end_block); | 2200 | return &instruction->base; |
| 9513 | assert(incoming_blocks.length == incoming_values.length); | ||
| 9514 | IrInstSrc *result_instruction; | ||
| 9515 | if (incoming_blocks.length == 0) { | ||
| 9516 | result_instruction = ir_build_const_void(irb, scope, node); | ||
| 9517 | } else { | ||
| 9518 | result_instruction = ir_build_phi(irb, scope, node, incoming_blocks.length, | ||
| 9519 | incoming_blocks.items, incoming_values.items, peer_parent); | ||
| 9520 | } | ||
| 9521 | return ir_lval_wrap(irb, scope, result_instruction, lval, result_loc); | ||
| 9522 | } | 2201 | } |
| 9523 | 2202 | ||
| 9524 | static IrInstSrc *ir_gen_comptime(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval) { | 2203 | static IrInstGen *ir_build_assert_zero(IrAnalyze *ira, IrInst *source_instruction, |
| 9525 | assert(node->type == NodeTypeCompTime); | 2204 | IrInstGen *target) |
| 9526 | 2205 | { | |
| 9527 | Scope *child_scope = create_comptime_scope(irb->codegen, node, parent_scope); | 2206 | IrInstGenAssertZero *instruction = ir_build_inst_gen<IrInstGenAssertZero>(&ira->new_irb, |
| 9528 | // purposefully pass null for result_loc and let EndExpr handle it | 2207 | source_instruction->scope, source_instruction->source_node); |
| 9529 | return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr); | 2208 | instruction->base.value->type = ira->codegen->builtin_types.entry_void; |
| 9530 | } | 2209 | instruction->target = target; |
| 9531 | 2210 | ||
| 9532 | static IrInstSrc *ir_gen_nosuspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval) { | 2211 | ir_ref_inst_gen(target); |
| 9533 | assert(node->type == NodeTypeNoSuspend); | ||
| 9534 | 2212 | ||
| 9535 | Scope *child_scope = create_nosuspend_scope(irb->codegen, node, parent_scope); | 2213 | return &instruction->base; |
| 9536 | // purposefully pass null for result_loc and let EndExpr handle it | ||
| 9537 | return ir_gen_node_extra(irb, node->data.nosuspend_expr.expr, child_scope, lval, nullptr); | ||
| 9538 | } | 2214 | } |
| 9539 | 2215 | ||
| 9540 | static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) { | 2216 | static IrInstGen *ir_build_assert_non_null(IrAnalyze *ira, IrInst *source_instruction, |
| 9541 | IrInstSrc *is_comptime; | 2217 | IrInstGen *target) |
| 9542 | if (ir_should_inline(irb->exec, break_scope)) { | 2218 | { |
| 9543 | is_comptime = ir_build_const_bool(irb, break_scope, node, true); | 2219 | IrInstGenAssertNonNull *instruction = ir_build_inst_gen<IrInstGenAssertNonNull>(&ira->new_irb, |
| 9544 | } else { | 2220 | source_instruction->scope, source_instruction->source_node); |
| 9545 | is_comptime = block_scope->is_comptime; | 2221 | instruction->base.value->type = ira->codegen->builtin_types.entry_void; |
| 9546 | } | 2222 | instruction->target = target; |
| 9547 | |||
| 9548 | IrInstSrc *result_value; | ||
| 9549 | if (node->data.break_expr.expr) { | ||
| 9550 | ResultLocPeer *peer_result = create_peer_result(block_scope->peer_parent); | ||
| 9551 | block_scope->peer_parent->peers.append(peer_result); | ||
| 9552 | |||
| 9553 | result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, block_scope->lval, | ||
| 9554 | &peer_result->base); | ||
| 9555 | if (result_value == irb->codegen->invalid_inst_src) | ||
| 9556 | return irb->codegen->invalid_inst_src; | ||
| 9557 | } else { | ||
| 9558 | result_value = ir_build_const_void(irb, break_scope, node); | ||
| 9559 | } | ||
| 9560 | 2223 | ||
| 9561 | IrBasicBlockSrc *dest_block = block_scope->end_block; | 2224 | ir_ref_inst_gen(target); |
| 9562 | if (!ir_gen_defers_for_block(irb, break_scope, dest_block->scope, nullptr, nullptr)) | ||
| 9563 | return irb->codegen->invalid_inst_src; | ||
| 9564 | 2225 | ||
| 9565 | block_scope->incoming_blocks->append(irb->current_basic_block); | 2226 | return &instruction->base; |
| 9566 | block_scope->incoming_values->append(result_value); | ||
| 9567 | return ir_build_br(irb, break_scope, node, dest_block, is_comptime); | ||
| 9568 | } | 2227 | } |
| 9569 | 2228 | ||
| 9570 | static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *node) { | 2229 | static IrInstGenAlloca *ir_build_alloca_gen(IrAnalyze *ira, IrInst *source_instruction, |
| 9571 | assert(node->type == NodeTypeBreak); | 2230 | uint32_t align, const char *name_hint) |
| 2231 | { | ||
| 2232 | IrInstGenAlloca *instruction = ir_create_inst_gen<IrInstGenAlloca>(&ira->new_irb, | ||
| 2233 | source_instruction->scope, source_instruction->source_node); | ||
| 2234 | instruction->align = align; | ||
| 2235 | instruction->name_hint = name_hint; | ||
| 9572 | 2236 | ||
| 9573 | // Search up the scope. We'll find one of these things first: | 2237 | return instruction; |
| 9574 | // * function definition scope or global scope => error, break outside loop | 2238 | } |
| 9575 | // * defer expression scope => error, cannot break out of defer expression | ||
| 9576 | // * loop scope => OK | ||
| 9577 | // * (if it's a labeled break) labeled block => OK | ||
| 9578 | 2239 | ||
| 9579 | Scope *search_scope = break_scope; | 2240 | static IrInstGen *ir_build_suspend_finish_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGenSuspendBegin *begin) { |
| 9580 | ScopeLoop *loop_scope; | 2241 | IrInstGenSuspendFinish *inst = ir_build_inst_void<IrInstGenSuspendFinish>(&ira->new_irb, |
| 9581 | for (;;) { | 2242 | source_instr->scope, source_instr->source_node); |
| 9582 | if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) { | 2243 | inst->begin = begin; |
| 9583 | if (node->data.break_expr.name != nullptr) { | ||
| 9584 | add_node_error(irb->codegen, node, buf_sprintf("label not found: '%s'", buf_ptr(node->data.break_expr.name))); | ||
| 9585 | return irb->codegen->invalid_inst_src; | ||
| 9586 | } else { | ||
| 9587 | add_node_error(irb->codegen, node, buf_sprintf("break expression outside loop")); | ||
| 9588 | return irb->codegen->invalid_inst_src; | ||
| 9589 | } | ||
| 9590 | } else if (search_scope->id == ScopeIdDeferExpr) { | ||
| 9591 | add_node_error(irb->codegen, node, buf_sprintf("cannot break out of defer expression")); | ||
| 9592 | return irb->codegen->invalid_inst_src; | ||
| 9593 | } else if (search_scope->id == ScopeIdLoop) { | ||
| 9594 | ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope; | ||
| 9595 | if (node->data.break_expr.name == nullptr || | ||
| 9596 | (this_loop_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_loop_scope->name))) | ||
| 9597 | { | ||
| 9598 | this_loop_scope->name_used = true; | ||
| 9599 | loop_scope = this_loop_scope; | ||
| 9600 | break; | ||
| 9601 | } | ||
| 9602 | } else if (search_scope->id == ScopeIdBlock) { | ||
| 9603 | ScopeBlock *this_block_scope = (ScopeBlock *)search_scope; | ||
| 9604 | if (node->data.break_expr.name != nullptr && | ||
| 9605 | (this_block_scope->name != nullptr && buf_eql_buf(node->data.break_expr.name, this_block_scope->name))) | ||
| 9606 | { | ||
| 9607 | assert(this_block_scope->end_block != nullptr); | ||
| 9608 | this_block_scope->name_used = true; | ||
| 9609 | return ir_gen_return_from_block(irb, break_scope, node, this_block_scope); | ||
| 9610 | } | ||
| 9611 | } else if (search_scope->id == ScopeIdSuspend) { | ||
| 9612 | add_node_error(irb->codegen, node, buf_sprintf("cannot break out of suspend block")); | ||
| 9613 | return irb->codegen->invalid_inst_src; | ||
| 9614 | } | ||
| 9615 | search_scope = search_scope->parent; | ||
| 9616 | } | ||
| 9617 | 2244 | ||
| 9618 | IrInstSrc *is_comptime; | 2245 | ir_ref_inst_gen(&begin->base); |
| 9619 | if (ir_should_inline(irb->exec, break_scope)) { | ||
| 9620 | is_comptime = ir_build_const_bool(irb, break_scope, node, true); | ||
| 9621 | } else { | ||
| 9622 | is_comptime = loop_scope->is_comptime; | ||
| 9623 | } | ||
| 9624 | 2246 | ||
| 9625 | IrInstSrc *result_value; | 2247 | return &inst->base; |
| 9626 | if (node->data.break_expr.expr) { | 2248 | } |
| 9627 | ResultLocPeer *peer_result = create_peer_result(loop_scope->peer_parent); | ||
| 9628 | loop_scope->peer_parent->peers.append(peer_result); | ||
| 9629 | 2249 | ||
| 9630 | result_value = ir_gen_node_extra(irb, node->data.break_expr.expr, break_scope, | 2250 | static IrInstGenAwait *ir_build_await_gen(IrAnalyze *ira, IrInst *source_instruction, |
| 9631 | loop_scope->lval, &peer_result->base); | 2251 | IrInstGen *frame, ZigType *result_type, IrInstGen *result_loc, bool is_nosuspend) |
| 9632 | if (result_value == irb->codegen->invalid_inst_src) | 2252 | { |
| 9633 | return irb->codegen->invalid_inst_src; | 2253 | IrInstGenAwait *instruction = ir_build_inst_gen<IrInstGenAwait>(&ira->new_irb, |
| 9634 | } else { | 2254 | source_instruction->scope, source_instruction->source_node); |
| 9635 | result_value = ir_build_const_void(irb, break_scope, node); | 2255 | instruction->base.value->type = result_type; |
| 9636 | } | 2256 | instruction->frame = frame; |
| 2257 | instruction->result_loc = result_loc; | ||
| 2258 | instruction->is_nosuspend = is_nosuspend; | ||
| 9637 | 2259 | ||
| 9638 | IrBasicBlockSrc *dest_block = loop_scope->break_block; | 2260 | ir_ref_inst_gen(frame); |
| 9639 | if (!ir_gen_defers_for_block(irb, break_scope, dest_block->scope, nullptr, nullptr)) | 2261 | if (result_loc != nullptr) ir_ref_inst_gen(result_loc); |
| 9640 | return irb->codegen->invalid_inst_src; | ||
| 9641 | 2262 | ||
| 9642 | loop_scope->incoming_blocks->append(irb->current_basic_block); | 2263 | return instruction; |
| 9643 | loop_scope->incoming_values->append(result_value); | ||
| 9644 | return ir_build_br(irb, break_scope, node, dest_block, is_comptime); | ||
| 9645 | } | 2264 | } |
| 9646 | 2265 | ||
| 9647 | static IrInstSrc *ir_gen_continue(IrBuilderSrc *irb, Scope *continue_scope, AstNode *node) { | 2266 | static IrInstGen *ir_build_resume_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *frame) { |
| 9648 | assert(node->type == NodeTypeContinue); | 2267 | IrInstGenResume *instruction = ir_build_inst_void<IrInstGenResume>(&ira->new_irb, |
| 9649 | 2268 | source_instr->scope, source_instr->source_node); | |
| 9650 | // Search up the scope. We'll find one of these things first: | 2269 | instruction->frame = frame; |
| 9651 | // * function definition scope or global scope => error, break outside loop | ||
| 9652 | // * defer expression scope => error, cannot break out of defer expression | ||
| 9653 | // * loop scope => OK | ||
| 9654 | 2270 | ||
| 9655 | ZigList<ScopeRuntime *> runtime_scopes = {}; | 2271 | ir_ref_inst_gen(frame); |
| 9656 | 2272 | ||
| 9657 | Scope *search_scope = continue_scope; | 2273 | return &instruction->base; |
| 9658 | ScopeLoop *loop_scope; | 2274 | } |
| 9659 | for (;;) { | ||
| 9660 | if (search_scope == nullptr || search_scope->id == ScopeIdFnDef) { | ||
| 9661 | if (node->data.continue_expr.name != nullptr) { | ||
| 9662 | add_node_error(irb->codegen, node, buf_sprintf("labeled loop not found: '%s'", buf_ptr(node->data.continue_expr.name))); | ||
| 9663 | return irb->codegen->invalid_inst_src; | ||
| 9664 | } else { | ||
| 9665 | add_node_error(irb->codegen, node, buf_sprintf("continue expression outside loop")); | ||
| 9666 | return irb->codegen->invalid_inst_src; | ||
| 9667 | } | ||
| 9668 | } else if (search_scope->id == ScopeIdDeferExpr) { | ||
| 9669 | add_node_error(irb->codegen, node, buf_sprintf("cannot continue out of defer expression")); | ||
| 9670 | return irb->codegen->invalid_inst_src; | ||
| 9671 | } else if (search_scope->id == ScopeIdLoop) { | ||
| 9672 | ScopeLoop *this_loop_scope = (ScopeLoop *)search_scope; | ||
| 9673 | if (node->data.continue_expr.name == nullptr || | ||
| 9674 | (this_loop_scope->name != nullptr && buf_eql_buf(node->data.continue_expr.name, this_loop_scope->name))) | ||
| 9675 | { | ||
| 9676 | this_loop_scope->name_used = true; | ||
| 9677 | loop_scope = this_loop_scope; | ||
| 9678 | break; | ||
| 9679 | } | ||
| 9680 | } else if (search_scope->id == ScopeIdRuntime) { | ||
| 9681 | ScopeRuntime *scope_runtime = (ScopeRuntime *)search_scope; | ||
| 9682 | runtime_scopes.append(scope_runtime); | ||
| 9683 | } | ||
| 9684 | search_scope = search_scope->parent; | ||
| 9685 | } | ||
| 9686 | 2275 | ||
| 9687 | IrInstSrc *is_comptime; | 2276 | static IrInstGen *ir_build_spill_begin_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *operand, |
| 9688 | if (ir_should_inline(irb->exec, continue_scope)) { | 2277 | SpillId spill_id) |
| 9689 | is_comptime = ir_build_const_bool(irb, continue_scope, node, true); | 2278 | { |
| 9690 | } else { | 2279 | IrInstGenSpillBegin *instruction = ir_build_inst_void<IrInstGenSpillBegin>(&ira->new_irb, |
| 9691 | is_comptime = loop_scope->is_comptime; | 2280 | source_instr->scope, source_instr->source_node); |
| 9692 | } | 2281 | instruction->operand = operand; |
| 2282 | instruction->spill_id = spill_id; | ||
| 9693 | 2283 | ||
| 9694 | for (size_t i = 0; i < runtime_scopes.length; i += 1) { | 2284 | ir_ref_inst_gen(operand); |
| 9695 | ScopeRuntime *scope_runtime = runtime_scopes.at(i); | ||
| 9696 | ir_mark_gen(ir_build_check_runtime_scope(irb, continue_scope, node, scope_runtime->is_comptime, is_comptime)); | ||
| 9697 | } | ||
| 9698 | runtime_scopes.deinit(); | ||
| 9699 | 2285 | ||
| 9700 | IrBasicBlockSrc *dest_block = loop_scope->continue_block; | 2286 | return &instruction->base; |
| 9701 | if (!ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, nullptr, nullptr)) | ||
| 9702 | return irb->codegen->invalid_inst_src; | ||
| 9703 | return ir_mark_gen(ir_build_br(irb, continue_scope, node, dest_block, is_comptime)); | ||
| 9704 | } | 2287 | } |
| 9705 | 2288 | ||
| 9706 | static IrInstSrc *ir_gen_error_type(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | 2289 | static IrInstGen *ir_build_spill_end_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGenSpillBegin *begin, |
| 9707 | assert(node->type == NodeTypeErrorType); | 2290 | ZigType *result_type) |
| 9708 | return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_global_error_set); | 2291 | { |
| 9709 | } | 2292 | IrInstGenSpillEnd *instruction = ir_build_inst_gen<IrInstGenSpillEnd>(&ira->new_irb, |
| 2293 | source_instr->scope, source_instr->source_node); | ||
| 2294 | instruction->base.value->type = result_type; | ||
| 2295 | instruction->begin = begin; | ||
| 2296 | |||
| 2297 | ir_ref_inst_gen(&begin->base); | ||
| 9710 | 2298 | ||
| 9711 | static IrInstSrc *ir_gen_defer(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { | 2299 | return &instruction->base; |
| 9712 | assert(node->type == NodeTypeDefer); | 2300 | } |
| 9713 | 2301 | ||
| 9714 | ScopeDefer *defer_child_scope = create_defer_scope(irb->codegen, node, parent_scope); | 2302 | static IrInstGen *ir_build_vector_extract_elem(IrAnalyze *ira, IrInst *source_instruction, |
| 9715 | node->data.defer.child_scope = &defer_child_scope->base; | 2303 | IrInstGen *vector, IrInstGen *index) |
| 2304 | { | ||
| 2305 | IrInstGenVectorExtractElem *instruction = ir_build_inst_gen<IrInstGenVectorExtractElem>( | ||
| 2306 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | ||
| 2307 | instruction->base.value->type = vector->value->type->data.vector.elem_type; | ||
| 2308 | instruction->vector = vector; | ||
| 2309 | instruction->index = index; | ||
| 9716 | 2310 | ||
| 9717 | ScopeDeferExpr *defer_expr_scope = create_defer_expr_scope(irb->codegen, node, parent_scope); | 2311 | ir_ref_inst_gen(vector); |
| 9718 | node->data.defer.expr_scope = &defer_expr_scope->base; | 2312 | ir_ref_inst_gen(index); |
| 9719 | 2313 | ||
| 9720 | return ir_build_const_void(irb, parent_scope, node); | 2314 | return &instruction->base; |
| 9721 | } | 2315 | } |
| 9722 | 2316 | ||
| 9723 | static IrInstSrc *ir_gen_slice(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { | 2317 | static IrInstGen *ir_build_wasm_memory_size_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *index) { |
| 9724 | assert(node->type == NodeTypeSliceExpr); | 2318 | IrInstGenWasmMemorySize *instruction = ir_build_inst_gen<IrInstGenWasmMemorySize>(&ira->new_irb, |
| 9725 | 2319 | source_instr->scope, source_instr->source_node); | |
| 9726 | AstNodeSliceExpr *slice_expr = &node->data.slice_expr; | 2320 | instruction->base.value->type = ira->codegen->builtin_types.entry_u32; |
| 9727 | AstNode *array_node = slice_expr->array_ref_expr; | 2321 | instruction->index = index; |
| 9728 | AstNode *start_node = slice_expr->start; | ||
| 9729 | AstNode *end_node = slice_expr->end; | ||
| 9730 | AstNode *sentinel_node = slice_expr->sentinel; | ||
| 9731 | 2322 | ||
| 9732 | IrInstSrc *ptr_value = ir_gen_node_extra(irb, array_node, scope, LValPtr, nullptr); | 2323 | ir_ref_inst_gen(index); |
| 9733 | if (ptr_value == irb->codegen->invalid_inst_src) | ||
| 9734 | return irb->codegen->invalid_inst_src; | ||
| 9735 | 2324 | ||
| 9736 | IrInstSrc *start_value = ir_gen_node(irb, start_node, scope); | 2325 | return &instruction->base; |
| 9737 | if (start_value == irb->codegen->invalid_inst_src) | 2326 | } |
| 9738 | return irb->codegen->invalid_inst_src; | ||
| 9739 | 2327 | ||
| 9740 | IrInstSrc *end_value; | 2328 | static IrInstGen *ir_build_wasm_memory_grow_gen(IrAnalyze *ira, IrInst *source_instr, IrInstGen *index, IrInstGen *delta) { |
| 9741 | if (end_node) { | 2329 | IrInstGenWasmMemoryGrow *instruction = ir_build_inst_gen<IrInstGenWasmMemoryGrow>(&ira->new_irb, |
| 9742 | end_value = ir_gen_node(irb, end_node, scope); | 2330 | source_instr->scope, source_instr->source_node); |
| 9743 | if (end_value == irb->codegen->invalid_inst_src) | 2331 | instruction->base.value->type = ira->codegen->builtin_types.entry_i32; |
| 9744 | return irb->codegen->invalid_inst_src; | 2332 | instruction->index = index; |
| 9745 | } else { | 2333 | instruction->delta = delta; |
| 9746 | end_value = nullptr; | ||
| 9747 | } | ||
| 9748 | 2334 | ||
| 9749 | IrInstSrc *sentinel_value; | 2335 | ir_ref_inst_gen(index); |
| 9750 | if (sentinel_node) { | 2336 | ir_ref_inst_gen(delta); |
| 9751 | sentinel_value = ir_gen_node(irb, sentinel_node, scope); | ||
| 9752 | if (sentinel_value == irb->codegen->invalid_inst_src) | ||
| 9753 | return irb->codegen->invalid_inst_src; | ||
| 9754 | } else { | ||
| 9755 | sentinel_value = nullptr; | ||
| 9756 | } | ||
| 9757 | 2337 | ||
| 9758 | IrInstSrc *slice = ir_build_slice_src(irb, scope, node, ptr_value, start_value, end_value, | 2338 | return &instruction->base; |
| 9759 | sentinel_value, true, result_loc); | ||
| 9760 | return ir_lval_wrap(irb, scope, slice, lval, result_loc); | ||
| 9761 | } | 2339 | } |
| 9762 | 2340 | ||
| 9763 | static IrInstSrc *ir_gen_catch(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval, | 2341 | static Error parse_asm_template(IrAnalyze *ira, AstNode *source_node, Buf *asm_template, |
| 9764 | ResultLoc *result_loc) | 2342 | ZigList<AsmToken> *tok_list) |
| 9765 | { | 2343 | { |
| 9766 | assert(node->type == NodeTypeCatchExpr); | 2344 | // TODO Connect the errors in this function back up to the actual source location |
| 2345 | // rather than just the token. https://github.com/ziglang/zig/issues/2080 | ||
| 2346 | enum State { | ||
| 2347 | StateStart, | ||
| 2348 | StatePercent, | ||
| 2349 | StateTemplate, | ||
| 2350 | StateVar, | ||
| 2351 | }; | ||
| 2352 | |||
| 2353 | assert(tok_list->length == 0); | ||
| 9767 | 2354 | ||
| 9768 | AstNode *op1_node = node->data.unwrap_err_expr.op1; | 2355 | AsmToken *cur_tok = nullptr; |
| 9769 | AstNode *op2_node = node->data.unwrap_err_expr.op2; | 2356 | |
| 9770 | AstNode *var_node = node->data.unwrap_err_expr.symbol; | 2357 | enum State state = StateStart; |
| 9771 | 2358 | ||
| 9772 | if (op2_node->type == NodeTypeUnreachable) { | 2359 | for (size_t i = 0; i < buf_len(asm_template); i += 1) { |
| 9773 | if (var_node != nullptr) { | 2360 | uint8_t c = *((uint8_t*)buf_ptr(asm_template) + i); |
| 9774 | assert(var_node->type == NodeTypeSymbol); | 2361 | switch (state) { |
| 9775 | Buf *var_name = var_node->data.symbol_expr.symbol; | 2362 | case StateStart: |
| 9776 | add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); | 2363 | if (c == '%') { |
| 9777 | return irb->codegen->invalid_inst_src; | 2364 | tok_list->add_one(); |
| 2365 | cur_tok = &tok_list->last(); | ||
| 2366 | cur_tok->id = AsmTokenIdPercent; | ||
| 2367 | cur_tok->start = i; | ||
| 2368 | state = StatePercent; | ||
| 2369 | } else { | ||
| 2370 | tok_list->add_one(); | ||
| 2371 | cur_tok = &tok_list->last(); | ||
| 2372 | cur_tok->id = AsmTokenIdTemplate; | ||
| 2373 | cur_tok->start = i; | ||
| 2374 | state = StateTemplate; | ||
| 2375 | } | ||
| 2376 | break; | ||
| 2377 | case StatePercent: | ||
| 2378 | if (c == '%') { | ||
| 2379 | cur_tok->end = i; | ||
| 2380 | state = StateStart; | ||
| 2381 | } else if (c == '[') { | ||
| 2382 | cur_tok->id = AsmTokenIdVar; | ||
| 2383 | state = StateVar; | ||
| 2384 | } else if (c == '=') { | ||
| 2385 | cur_tok->id = AsmTokenIdUniqueId; | ||
| 2386 | cur_tok->end = i; | ||
| 2387 | state = StateStart; | ||
| 2388 | } else { | ||
| 2389 | add_node_error(ira->codegen, source_node, | ||
| 2390 | buf_create_from_str("expected a '%' or '['")); | ||
| 2391 | return ErrorSemanticAnalyzeFail; | ||
| 2392 | } | ||
| 2393 | break; | ||
| 2394 | case StateTemplate: | ||
| 2395 | if (c == '%') { | ||
| 2396 | cur_tok->end = i; | ||
| 2397 | i -= 1; | ||
| 2398 | cur_tok = nullptr; | ||
| 2399 | state = StateStart; | ||
| 2400 | } | ||
| 2401 | break; | ||
| 2402 | case StateVar: | ||
| 2403 | if (c == ']') { | ||
| 2404 | cur_tok->end = i; | ||
| 2405 | state = StateStart; | ||
| 2406 | } else if ((c >= 'a' && c <= 'z') || | ||
| 2407 | (c >= '0' && c <= '9') || | ||
| 2408 | (c == '_')) | ||
| 2409 | { | ||
| 2410 | // do nothing | ||
| 2411 | } else { | ||
| 2412 | add_node_error(ira->codegen, source_node, | ||
| 2413 | buf_sprintf("invalid substitution character: '%c'", c)); | ||
| 2414 | return ErrorSemanticAnalyzeFail; | ||
| 2415 | } | ||
| 2416 | break; | ||
| 9778 | } | 2417 | } |
| 9779 | return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, lval, result_loc); | ||
| 9780 | } | ||
| 9781 | |||
| 9782 | |||
| 9783 | ScopeExpr *spill_scope = create_expr_scope(irb->codegen, op1_node, parent_scope); | ||
| 9784 | spill_scope->spill_harder = true; | ||
| 9785 | |||
| 9786 | IrInstSrc *err_union_ptr = ir_gen_node_extra(irb, op1_node, &spill_scope->base, LValPtr, nullptr); | ||
| 9787 | if (err_union_ptr == irb->codegen->invalid_inst_src) | ||
| 9788 | return irb->codegen->invalid_inst_src; | ||
| 9789 | |||
| 9790 | IrInstSrc *is_err = ir_build_test_err_src(irb, parent_scope, node, err_union_ptr, true, false); | ||
| 9791 | |||
| 9792 | IrInstSrc *is_comptime; | ||
| 9793 | if (ir_should_inline(irb->exec, parent_scope)) { | ||
| 9794 | is_comptime = ir_build_const_bool(irb, parent_scope, node, true); | ||
| 9795 | } else { | ||
| 9796 | is_comptime = ir_build_test_comptime(irb, parent_scope, node, is_err); | ||
| 9797 | } | ||
| 9798 | |||
| 9799 | IrBasicBlockSrc *ok_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrOk"); | ||
| 9800 | IrBasicBlockSrc *err_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrError"); | ||
| 9801 | IrBasicBlockSrc *end_block = ir_create_basic_block(irb, parent_scope, "UnwrapErrEnd"); | ||
| 9802 | IrInstSrc *cond_br_inst = ir_build_cond_br(irb, parent_scope, node, is_err, err_block, ok_block, is_comptime); | ||
| 9803 | |||
| 9804 | ResultLocPeerParent *peer_parent = ir_build_binary_result_peers(irb, cond_br_inst, ok_block, end_block, result_loc, | ||
| 9805 | is_comptime); | ||
| 9806 | |||
| 9807 | ir_set_cursor_at_end_and_append_block(irb, err_block); | ||
| 9808 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, &spill_scope->base, is_comptime); | ||
| 9809 | Scope *err_scope; | ||
| 9810 | if (var_node) { | ||
| 9811 | assert(var_node->type == NodeTypeSymbol); | ||
| 9812 | Buf *var_name = var_node->data.symbol_expr.symbol; | ||
| 9813 | bool is_const = true; | ||
| 9814 | bool is_shadowable = false; | ||
| 9815 | ZigVar *var = ir_create_var(irb, node, subexpr_scope, var_name, | ||
| 9816 | is_const, is_const, is_shadowable, is_comptime); | ||
| 9817 | err_scope = var->child_scope; | ||
| 9818 | IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, err_scope, node, err_union_ptr); | ||
| 9819 | IrInstSrc *err_value = ir_build_load_ptr(irb, err_scope, var_node, err_ptr); | ||
| 9820 | build_decl_var_and_init(irb, err_scope, var_node, var, err_value, buf_ptr(var_name), is_comptime); | ||
| 9821 | } else { | ||
| 9822 | err_scope = subexpr_scope; | ||
| 9823 | } | ||
| 9824 | IrInstSrc *err_result = ir_gen_node_extra(irb, op2_node, err_scope, LValNone, &peer_parent->peers.at(0)->base); | ||
| 9825 | if (err_result == irb->codegen->invalid_inst_src) | ||
| 9826 | return irb->codegen->invalid_inst_src; | ||
| 9827 | IrBasicBlockSrc *after_err_block = irb->current_basic_block; | ||
| 9828 | if (!instr_is_unreachable(err_result)) | ||
| 9829 | ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); | ||
| 9830 | |||
| 9831 | ir_set_cursor_at_end_and_append_block(irb, ok_block); | ||
| 9832 | IrInstSrc *unwrapped_ptr = ir_build_unwrap_err_payload_src(irb, parent_scope, node, err_union_ptr, false, false); | ||
| 9833 | IrInstSrc *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); | ||
| 9834 | ir_build_end_expr(irb, parent_scope, node, unwrapped_payload, &peer_parent->peers.at(1)->base); | ||
| 9835 | IrBasicBlockSrc *after_ok_block = irb->current_basic_block; | ||
| 9836 | ir_build_br(irb, parent_scope, node, end_block, is_comptime); | ||
| 9837 | |||
| 9838 | ir_set_cursor_at_end_and_append_block(irb, end_block); | ||
| 9839 | IrInstSrc **incoming_values = heap::c_allocator.allocate<IrInstSrc *>(2); | ||
| 9840 | incoming_values[0] = err_result; | ||
| 9841 | incoming_values[1] = unwrapped_payload; | ||
| 9842 | IrBasicBlockSrc **incoming_blocks = heap::c_allocator.allocate<IrBasicBlockSrc *>(2); | ||
| 9843 | incoming_blocks[0] = after_err_block; | ||
| 9844 | incoming_blocks[1] = after_ok_block; | ||
| 9845 | IrInstSrc *phi = ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values, peer_parent); | ||
| 9846 | return ir_lval_wrap(irb, parent_scope, phi, lval, result_loc); | ||
| 9847 | } | ||
| 9848 | |||
| 9849 | static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *outer_scope, Scope *inner_scope) { | ||
| 9850 | if (inner_scope == nullptr || inner_scope == outer_scope) return false; | ||
| 9851 | bool need_comma = render_instance_name_recursive(codegen, name, outer_scope, inner_scope->parent); | ||
| 9852 | if (inner_scope->id != ScopeIdVarDecl) | ||
| 9853 | return need_comma; | ||
| 9854 | |||
| 9855 | ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope; | ||
| 9856 | if (need_comma) | ||
| 9857 | buf_append_char(name, ','); | ||
| 9858 | // TODO: const ptr reinterpret here to make the var type agree with the value? | ||
| 9859 | render_const_value(codegen, name, var_scope->var->const_value); | ||
| 9860 | return true; | ||
| 9861 | } | ||
| 9862 | |||
| 9863 | static Buf *get_anon_type_name(CodeGen *codegen, IrExecutableSrc *exec, const char *kind_name, | ||
| 9864 | Scope *scope, AstNode *source_node, Buf *out_bare_name) | ||
| 9865 | { | ||
| 9866 | if (exec != nullptr && exec->name) { | ||
| 9867 | ZigType *import = get_scope_import(scope); | ||
| 9868 | Buf *namespace_name = buf_alloc(); | ||
| 9869 | append_namespace_qualification(codegen, namespace_name, import); | ||
| 9870 | buf_append_buf(namespace_name, exec->name); | ||
| 9871 | buf_init_from_buf(out_bare_name, exec->name); | ||
| 9872 | return namespace_name; | ||
| 9873 | } else if (exec != nullptr && exec->name_fn != nullptr) { | ||
| 9874 | Buf *name = buf_alloc(); | ||
| 9875 | buf_append_buf(name, &exec->name_fn->symbol_name); | ||
| 9876 | buf_appendf(name, "("); | ||
| 9877 | render_instance_name_recursive(codegen, name, &exec->name_fn->fndef_scope->base, exec->begin_scope); | ||
| 9878 | buf_appendf(name, ")"); | ||
| 9879 | buf_init_from_buf(out_bare_name, name); | ||
| 9880 | return name; | ||
| 9881 | } else { | ||
| 9882 | ZigType *import = get_scope_import(scope); | ||
| 9883 | Buf *namespace_name = buf_alloc(); | ||
| 9884 | append_namespace_qualification(codegen, namespace_name, import); | ||
| 9885 | buf_appendf(namespace_name, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize, kind_name, | ||
| 9886 | source_node->line + 1, source_node->column + 1); | ||
| 9887 | buf_init_from_buf(out_bare_name, namespace_name); | ||
| 9888 | return namespace_name; | ||
| 9889 | } | 2418 | } |
| 9890 | } | ||
| 9891 | |||
| 9892 | static IrInstSrc *ir_gen_container_decl(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { | ||
| 9893 | assert(node->type == NodeTypeContainerDecl); | ||
| 9894 | 2419 | ||
| 9895 | ContainerKind kind = node->data.container_decl.kind; | 2420 | switch (state) { |
| 9896 | Buf *bare_name = buf_alloc(); | 2421 | case StateStart: |
| 9897 | Buf *name = get_anon_type_name(irb->codegen, irb->exec, container_string(kind), parent_scope, node, bare_name); | 2422 | break; |
| 9898 | 2423 | case StatePercent: | |
| 9899 | ContainerLayout layout = node->data.container_decl.layout; | 2424 | case StateVar: |
| 9900 | ZigType *container_type = get_partial_container_type(irb->codegen, parent_scope, | 2425 | add_node_error(ira->codegen, source_node, buf_sprintf("unexpected end of assembly template")); |
| 9901 | kind, node, buf_ptr(name), bare_name, layout); | 2426 | return ErrorSemanticAnalyzeFail; |
| 9902 | ScopeDecls *child_scope = get_container_scope(container_type); | 2427 | case StateTemplate: |
| 9903 | 2428 | cur_tok->end = buf_len(asm_template); | |
| 9904 | for (size_t i = 0; i < node->data.container_decl.decls.length; i += 1) { | 2429 | break; |
| 9905 | AstNode *child_node = node->data.container_decl.decls.at(i); | ||
| 9906 | scan_decls(irb->codegen, child_scope, child_node); | ||
| 9907 | } | 2430 | } |
| 9908 | 2431 | return ErrorNone; | |
| 9909 | TldContainer *tld_container = heap::c_allocator.create<TldContainer>(); | ||
| 9910 | init_tld(&tld_container->base, TldIdContainer, bare_name, VisibModPub, node, parent_scope); | ||
| 9911 | tld_container->type_entry = container_type; | ||
| 9912 | tld_container->decls_scope = child_scope; | ||
| 9913 | irb->codegen->resolve_queue.append(&tld_container->base); | ||
| 9914 | |||
| 9915 | // Add this to the list to mark as invalid if analyzing this exec fails. | ||
| 9916 | irb->exec->tld_list.append(&tld_container->base); | ||
| 9917 | |||
| 9918 | return ir_build_const_type(irb, parent_scope, node, container_type); | ||
| 9919 | } | 2432 | } |
| 9920 | 2433 | ||
| 9921 | // errors should be populated with set1's values | 2434 | // errors should be populated with set1's values |
| ... | @@ -10003,498 +2516,7 @@ static ZigType *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstN | ... | @@ -10003,498 +2516,7 @@ static ZigType *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstN |
| 10003 | return err_set_type; | 2516 | return err_set_type; |
| 10004 | } | 2517 | } |
| 10005 | 2518 | ||
| 10006 | static AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node) { | 2519 | static void invalidate_exec_gen(Stage1Air *exec, ErrorMsg *msg) { |
| 10007 | if (err_set_field_node->type == NodeTypeSymbol) { | ||
| 10008 | return err_set_field_node; | ||
| 10009 | } else if (err_set_field_node->type == NodeTypeErrorSetField) { | ||
| 10010 | assert(err_set_field_node->data.err_set_field.field_name->type == NodeTypeSymbol); | ||
| 10011 | return err_set_field_node->data.err_set_field.field_name; | ||
| 10012 | } else { | ||
| 10013 | return err_set_field_node; | ||
| 10014 | } | ||
| 10015 | } | ||
| 10016 | |||
| 10017 | static IrInstSrc *ir_gen_err_set_decl(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { | ||
| 10018 | assert(node->type == NodeTypeErrorSetDecl); | ||
| 10019 | |||
| 10020 | uint32_t err_count = node->data.err_set_decl.decls.length; | ||
| 10021 | |||
| 10022 | Buf bare_name = BUF_INIT; | ||
| 10023 | Buf *type_name = get_anon_type_name(irb->codegen, irb->exec, "error", parent_scope, node, &bare_name); | ||
| 10024 | ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); | ||
| 10025 | buf_init_from_buf(&err_set_type->name, type_name); | ||
| 10026 | err_set_type->data.error_set.err_count = err_count; | ||
| 10027 | err_set_type->size_in_bits = irb->codegen->builtin_types.entry_global_error_set->size_in_bits; | ||
| 10028 | err_set_type->abi_align = irb->codegen->builtin_types.entry_global_error_set->abi_align; | ||
| 10029 | err_set_type->abi_size = irb->codegen->builtin_types.entry_global_error_set->abi_size; | ||
| 10030 | err_set_type->data.error_set.errors = heap::c_allocator.allocate<ErrorTableEntry *>(err_count); | ||
| 10031 | |||
| 10032 | size_t errors_count = irb->codegen->errors_by_index.length + err_count; | ||
| 10033 | ErrorTableEntry **errors = heap::c_allocator.allocate<ErrorTableEntry *>(errors_count); | ||
| 10034 | |||
| 10035 | for (uint32_t i = 0; i < err_count; i += 1) { | ||
| 10036 | AstNode *field_node = node->data.err_set_decl.decls.at(i); | ||
| 10037 | AstNode *symbol_node = ast_field_to_symbol_node(field_node); | ||
| 10038 | Buf *err_name = symbol_node->data.symbol_expr.symbol; | ||
| 10039 | ErrorTableEntry *err = heap::c_allocator.create<ErrorTableEntry>(); | ||
| 10040 | err->decl_node = field_node; | ||
| 10041 | buf_init_from_buf(&err->name, err_name); | ||
| 10042 | |||
| 10043 | auto existing_entry = irb->codegen->error_table.put_unique(err_name, err); | ||
| 10044 | if (existing_entry) { | ||
| 10045 | err->value = existing_entry->value->value; | ||
| 10046 | } else { | ||
| 10047 | size_t error_value_count = irb->codegen->errors_by_index.length; | ||
| 10048 | assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)irb->codegen->err_tag_type->data.integral.bit_count)); | ||
| 10049 | err->value = error_value_count; | ||
| 10050 | irb->codegen->errors_by_index.append(err); | ||
| 10051 | } | ||
| 10052 | err_set_type->data.error_set.errors[i] = err; | ||
| 10053 | |||
| 10054 | ErrorTableEntry *prev_err = errors[err->value]; | ||
| 10055 | if (prev_err != nullptr) { | ||
| 10056 | ErrorMsg *msg = add_node_error(irb->codegen, ast_field_to_symbol_node(err->decl_node), | ||
| 10057 | buf_sprintf("duplicate error: '%s'", buf_ptr(&err->name))); | ||
| 10058 | add_error_note(irb->codegen, msg, ast_field_to_symbol_node(prev_err->decl_node), | ||
| 10059 | buf_sprintf("other error here")); | ||
| 10060 | return irb->codegen->invalid_inst_src; | ||
| 10061 | } | ||
| 10062 | errors[err->value] = err; | ||
| 10063 | } | ||
| 10064 | heap::c_allocator.deallocate(errors, errors_count); | ||
| 10065 | return ir_build_const_type(irb, parent_scope, node, err_set_type); | ||
| 10066 | } | ||
| 10067 | |||
| 10068 | static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { | ||
| 10069 | assert(node->type == NodeTypeFnProto); | ||
| 10070 | |||
| 10071 | size_t param_count = node->data.fn_proto.params.length; | ||
| 10072 | IrInstSrc **param_types = heap::c_allocator.allocate<IrInstSrc*>(param_count); | ||
| 10073 | |||
| 10074 | bool is_var_args = false; | ||
| 10075 | for (size_t i = 0; i < param_count; i += 1) { | ||
| 10076 | AstNode *param_node = node->data.fn_proto.params.at(i); | ||
| 10077 | if (param_node->data.param_decl.is_var_args) { | ||
| 10078 | is_var_args = true; | ||
| 10079 | break; | ||
| 10080 | } | ||
| 10081 | if (param_node->data.param_decl.anytype_token == nullptr) { | ||
| 10082 | AstNode *type_node = param_node->data.param_decl.type; | ||
| 10083 | IrInstSrc *type_value = ir_gen_node(irb, type_node, parent_scope); | ||
| 10084 | if (type_value == irb->codegen->invalid_inst_src) | ||
| 10085 | return irb->codegen->invalid_inst_src; | ||
| 10086 | param_types[i] = type_value; | ||
| 10087 | } else { | ||
| 10088 | param_types[i] = nullptr; | ||
| 10089 | } | ||
| 10090 | } | ||
| 10091 | |||
| 10092 | IrInstSrc *align_value = nullptr; | ||
| 10093 | if (node->data.fn_proto.align_expr != nullptr) { | ||
| 10094 | align_value = ir_gen_node(irb, node->data.fn_proto.align_expr, parent_scope); | ||
| 10095 | if (align_value == irb->codegen->invalid_inst_src) | ||
| 10096 | return irb->codegen->invalid_inst_src; | ||
| 10097 | } | ||
| 10098 | |||
| 10099 | IrInstSrc *callconv_value = nullptr; | ||
| 10100 | if (node->data.fn_proto.callconv_expr != nullptr) { | ||
| 10101 | callconv_value = ir_gen_node(irb, node->data.fn_proto.callconv_expr, parent_scope); | ||
| 10102 | if (callconv_value == irb->codegen->invalid_inst_src) | ||
| 10103 | return irb->codegen->invalid_inst_src; | ||
| 10104 | } | ||
| 10105 | |||
| 10106 | IrInstSrc *return_type; | ||
| 10107 | if (node->data.fn_proto.return_type == nullptr) { | ||
| 10108 | return_type = ir_build_const_type(irb, parent_scope, node, irb->codegen->builtin_types.entry_void); | ||
| 10109 | } else { | ||
| 10110 | return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope); | ||
| 10111 | if (return_type == irb->codegen->invalid_inst_src) | ||
| 10112 | return irb->codegen->invalid_inst_src; | ||
| 10113 | } | ||
| 10114 | |||
| 10115 | return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, callconv_value, return_type, is_var_args); | ||
| 10116 | } | ||
| 10117 | |||
| 10118 | static IrInstSrc *ir_gen_resume(IrBuilderSrc *irb, Scope *scope, AstNode *node) { | ||
| 10119 | assert(node->type == NodeTypeResume); | ||
| 10120 | |||
| 10121 | IrInstSrc *target_inst = ir_gen_node_extra(irb, node->data.resume_expr.expr, scope, LValPtr, nullptr); | ||
| 10122 | if (target_inst == irb->codegen->invalid_inst_src) | ||
| 10123 | return irb->codegen->invalid_inst_src; | ||
| 10124 | |||
| 10125 | return ir_build_resume_src(irb, scope, node, target_inst); | ||
| 10126 | } | ||
| 10127 | |||
| 10128 | static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, | ||
| 10129 | ResultLoc *result_loc) | ||
| 10130 | { | ||
| 10131 | assert(node->type == NodeTypeAwaitExpr); | ||
| 10132 | |||
| 10133 | bool is_nosuspend = get_scope_nosuspend(scope) != nullptr; | ||
| 10134 | |||
| 10135 | AstNode *expr_node = node->data.await_expr.expr; | ||
| 10136 | if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) { | ||
| 10137 | AstNode *fn_ref_expr = expr_node->data.fn_call_expr.fn_ref_expr; | ||
| 10138 | Buf *name = fn_ref_expr->data.symbol_expr.symbol; | ||
| 10139 | auto entry = irb->codegen->builtin_fn_table.maybe_get(name); | ||
| 10140 | if (entry != nullptr) { | ||
| 10141 | BuiltinFnEntry *builtin_fn = entry->value; | ||
| 10142 | if (builtin_fn->id == BuiltinFnIdAsyncCall) { | ||
| 10143 | return ir_gen_async_call(irb, scope, node, expr_node, lval, result_loc); | ||
| 10144 | } | ||
| 10145 | } | ||
| 10146 | } | ||
| 10147 | |||
| 10148 | ZigFn *fn_entry = exec_fn_entry(irb->exec); | ||
| 10149 | if (!fn_entry) { | ||
| 10150 | add_node_error(irb->codegen, node, buf_sprintf("await outside function definition")); | ||
| 10151 | return irb->codegen->invalid_inst_src; | ||
| 10152 | } | ||
| 10153 | ScopeSuspend *existing_suspend_scope = get_scope_suspend(scope); | ||
| 10154 | if (existing_suspend_scope) { | ||
| 10155 | if (!existing_suspend_scope->reported_err) { | ||
| 10156 | ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot await inside suspend block")); | ||
| 10157 | add_error_note(irb->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("suspend block here")); | ||
| 10158 | existing_suspend_scope->reported_err = true; | ||
| 10159 | } | ||
| 10160 | return irb->codegen->invalid_inst_src; | ||
| 10161 | } | ||
| 10162 | |||
| 10163 | IrInstSrc *target_inst = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); | ||
| 10164 | if (target_inst == irb->codegen->invalid_inst_src) | ||
| 10165 | return irb->codegen->invalid_inst_src; | ||
| 10166 | |||
| 10167 | IrInstSrc *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc, is_nosuspend); | ||
| 10168 | return ir_lval_wrap(irb, scope, await_inst, lval, result_loc); | ||
| 10169 | } | ||
| 10170 | |||
| 10171 | static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node) { | ||
| 10172 | assert(node->type == NodeTypeSuspend); | ||
| 10173 | |||
| 10174 | ZigFn *fn_entry = exec_fn_entry(irb->exec); | ||
| 10175 | if (!fn_entry) { | ||
| 10176 | add_node_error(irb->codegen, node, buf_sprintf("suspend outside function definition")); | ||
| 10177 | return irb->codegen->invalid_inst_src; | ||
| 10178 | } | ||
| 10179 | if (get_scope_nosuspend(parent_scope) != nullptr) { | ||
| 10180 | add_node_error(irb->codegen, node, buf_sprintf("suspend in nosuspend scope")); | ||
| 10181 | return irb->codegen->invalid_inst_src; | ||
| 10182 | } | ||
| 10183 | |||
| 10184 | ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope); | ||
| 10185 | if (existing_suspend_scope) { | ||
| 10186 | if (!existing_suspend_scope->reported_err) { | ||
| 10187 | ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot suspend inside suspend block")); | ||
| 10188 | add_error_note(irb->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("other suspend block here")); | ||
| 10189 | existing_suspend_scope->reported_err = true; | ||
| 10190 | } | ||
| 10191 | return irb->codegen->invalid_inst_src; | ||
| 10192 | } | ||
| 10193 | |||
| 10194 | IrInstSrcSuspendBegin *begin = ir_build_suspend_begin_src(irb, parent_scope, node); | ||
| 10195 | ScopeSuspend *suspend_scope = create_suspend_scope(irb->codegen, node, parent_scope); | ||
| 10196 | Scope *child_scope = &suspend_scope->base; | ||
| 10197 | IrInstSrc *susp_res = ir_gen_node(irb, node->data.suspend.block, child_scope); | ||
| 10198 | if (susp_res == irb->codegen->invalid_inst_src) | ||
| 10199 | return irb->codegen->invalid_inst_src; | ||
| 10200 | ir_mark_gen(ir_build_check_statement_is_void(irb, child_scope, node->data.suspend.block, susp_res)); | ||
| 10201 | |||
| 10202 | return ir_mark_gen(ir_build_suspend_finish_src(irb, parent_scope, node, begin)); | ||
| 10203 | } | ||
| 10204 | |||
| 10205 | static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope, | ||
| 10206 | LVal lval, ResultLoc *result_loc) | ||
| 10207 | { | ||
| 10208 | assert(scope); | ||
| 10209 | switch (node->type) { | ||
| 10210 | case NodeTypeStructValueField: | ||
| 10211 | case NodeTypeParamDecl: | ||
| 10212 | case NodeTypeUsingNamespace: | ||
| 10213 | case NodeTypeSwitchProng: | ||
| 10214 | case NodeTypeSwitchRange: | ||
| 10215 | case NodeTypeStructField: | ||
| 10216 | case NodeTypeErrorSetField: | ||
| 10217 | case NodeTypeFnDef: | ||
| 10218 | case NodeTypeTestDecl: | ||
| 10219 | zig_unreachable(); | ||
| 10220 | case NodeTypeBlock: | ||
| 10221 | return ir_gen_block(irb, scope, node, lval, result_loc); | ||
| 10222 | case NodeTypeGroupedExpr: | ||
| 10223 | return ir_gen_node_raw(irb, node->data.grouped_expr, scope, lval, result_loc); | ||
| 10224 | case NodeTypeBinOpExpr: | ||
| 10225 | return ir_gen_bin_op(irb, scope, node, lval, result_loc); | ||
| 10226 | case NodeTypeIntLiteral: | ||
| 10227 | return ir_lval_wrap(irb, scope, ir_gen_int_lit(irb, scope, node), lval, result_loc); | ||
| 10228 | case NodeTypeFloatLiteral: | ||
| 10229 | return ir_lval_wrap(irb, scope, ir_gen_float_lit(irb, scope, node), lval, result_loc); | ||
| 10230 | case NodeTypeCharLiteral: | ||
| 10231 | return ir_lval_wrap(irb, scope, ir_gen_char_lit(irb, scope, node), lval, result_loc); | ||
| 10232 | case NodeTypeSymbol: | ||
| 10233 | return ir_gen_symbol(irb, scope, node, lval, result_loc); | ||
| 10234 | case NodeTypeFnCallExpr: | ||
| 10235 | return ir_gen_fn_call(irb, scope, node, lval, result_loc); | ||
| 10236 | case NodeTypeIfBoolExpr: | ||
| 10237 | return ir_gen_if_bool_expr(irb, scope, node, lval, result_loc); | ||
| 10238 | case NodeTypePrefixOpExpr: | ||
| 10239 | return ir_gen_prefix_op_expr(irb, scope, node, lval, result_loc); | ||
| 10240 | case NodeTypeContainerInitExpr: | ||
| 10241 | return ir_gen_container_init_expr(irb, scope, node, lval, result_loc); | ||
| 10242 | case NodeTypeVariableDeclaration: | ||
| 10243 | return ir_gen_var_decl(irb, scope, node); | ||
| 10244 | case NodeTypeWhileExpr: | ||
| 10245 | return ir_gen_while_expr(irb, scope, node, lval, result_loc); | ||
| 10246 | case NodeTypeForExpr: | ||
| 10247 | return ir_gen_for_expr(irb, scope, node, lval, result_loc); | ||
| 10248 | case NodeTypeArrayAccessExpr: | ||
| 10249 | return ir_gen_array_access(irb, scope, node, lval, result_loc); | ||
| 10250 | case NodeTypeReturnExpr: | ||
| 10251 | return ir_gen_return(irb, scope, node, lval, result_loc); | ||
| 10252 | case NodeTypeFieldAccessExpr: | ||
| 10253 | { | ||
| 10254 | IrInstSrc *ptr_instruction = ir_gen_field_access(irb, scope, node); | ||
| 10255 | if (ptr_instruction == irb->codegen->invalid_inst_src) | ||
| 10256 | return ptr_instruction; | ||
| 10257 | if (lval == LValPtr || lval == LValAssign) | ||
| 10258 | return ptr_instruction; | ||
| 10259 | |||
| 10260 | IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, ptr_instruction); | ||
| 10261 | return ir_expr_wrap(irb, scope, load_ptr, result_loc); | ||
| 10262 | } | ||
| 10263 | case NodeTypePtrDeref: { | ||
| 10264 | AstNode *expr_node = node->data.ptr_deref_expr.target; | ||
| 10265 | |||
| 10266 | LVal child_lval = lval; | ||
| 10267 | if (child_lval == LValAssign) | ||
| 10268 | child_lval = LValPtr; | ||
| 10269 | |||
| 10270 | IrInstSrc *value = ir_gen_node_extra(irb, expr_node, scope, child_lval, nullptr); | ||
| 10271 | if (value == irb->codegen->invalid_inst_src) | ||
| 10272 | return value; | ||
| 10273 | |||
| 10274 | // We essentially just converted any lvalue from &(x.*) to (&x).*; | ||
| 10275 | // this inhibits checking that x is a pointer later, so we directly | ||
| 10276 | // record whether the pointer check is needed | ||
| 10277 | IrInstSrc *un_op = ir_build_un_op_lval(irb, scope, node, IrUnOpDereference, value, lval, result_loc); | ||
| 10278 | return ir_expr_wrap(irb, scope, un_op, result_loc); | ||
| 10279 | } | ||
| 10280 | case NodeTypeUnwrapOptional: { | ||
| 10281 | AstNode *expr_node = node->data.unwrap_optional.expr; | ||
| 10282 | |||
| 10283 | IrInstSrc *maybe_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr); | ||
| 10284 | if (maybe_ptr == irb->codegen->invalid_inst_src) | ||
| 10285 | return irb->codegen->invalid_inst_src; | ||
| 10286 | |||
| 10287 | IrInstSrc *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true ); | ||
| 10288 | if (lval == LValPtr || lval == LValAssign) | ||
| 10289 | return unwrapped_ptr; | ||
| 10290 | |||
| 10291 | IrInstSrc *load_ptr = ir_build_load_ptr(irb, scope, node, unwrapped_ptr); | ||
| 10292 | return ir_expr_wrap(irb, scope, load_ptr, result_loc); | ||
| 10293 | } | ||
| 10294 | case NodeTypeBoolLiteral: | ||
| 10295 | return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval, result_loc); | ||
| 10296 | case NodeTypeArrayType: | ||
| 10297 | return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval, result_loc); | ||
| 10298 | case NodeTypePointerType: | ||
| 10299 | return ir_lval_wrap(irb, scope, ir_gen_pointer_type(irb, scope, node), lval, result_loc); | ||
| 10300 | case NodeTypeAnyFrameType: | ||
| 10301 | return ir_lval_wrap(irb, scope, ir_gen_anyframe_type(irb, scope, node), lval, result_loc); | ||
| 10302 | case NodeTypeStringLiteral: | ||
| 10303 | return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval, result_loc); | ||
| 10304 | case NodeTypeUndefinedLiteral: | ||
| 10305 | return ir_lval_wrap(irb, scope, ir_gen_undefined_literal(irb, scope, node), lval, result_loc); | ||
| 10306 | case NodeTypeAsmExpr: | ||
| 10307 | return ir_lval_wrap(irb, scope, ir_gen_asm_expr(irb, scope, node), lval, result_loc); | ||
| 10308 | case NodeTypeNullLiteral: | ||
| 10309 | return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval, result_loc); | ||
| 10310 | case NodeTypeIfErrorExpr: | ||
| 10311 | return ir_gen_if_err_expr(irb, scope, node, lval, result_loc); | ||
| 10312 | case NodeTypeIfOptional: | ||
| 10313 | return ir_gen_if_optional_expr(irb, scope, node, lval, result_loc); | ||
| 10314 | case NodeTypeSwitchExpr: | ||
| 10315 | return ir_gen_switch_expr(irb, scope, node, lval, result_loc); | ||
| 10316 | case NodeTypeCompTime: | ||
| 10317 | return ir_expr_wrap(irb, scope, ir_gen_comptime(irb, scope, node, lval), result_loc); | ||
| 10318 | case NodeTypeNoSuspend: | ||
| 10319 | return ir_expr_wrap(irb, scope, ir_gen_nosuspend(irb, scope, node, lval), result_loc); | ||
| 10320 | case NodeTypeErrorType: | ||
| 10321 | return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval, result_loc); | ||
| 10322 | case NodeTypeBreak: | ||
| 10323 | return ir_lval_wrap(irb, scope, ir_gen_break(irb, scope, node), lval, result_loc); | ||
| 10324 | case NodeTypeContinue: | ||
| 10325 | return ir_lval_wrap(irb, scope, ir_gen_continue(irb, scope, node), lval, result_loc); | ||
| 10326 | case NodeTypeUnreachable: | ||
| 10327 | return ir_build_unreachable(irb, scope, node); | ||
| 10328 | case NodeTypeDefer: | ||
| 10329 | return ir_lval_wrap(irb, scope, ir_gen_defer(irb, scope, node), lval, result_loc); | ||
| 10330 | case NodeTypeSliceExpr: | ||
| 10331 | return ir_gen_slice(irb, scope, node, lval, result_loc); | ||
| 10332 | case NodeTypeCatchExpr: | ||
| 10333 | return ir_gen_catch(irb, scope, node, lval, result_loc); | ||
| 10334 | case NodeTypeContainerDecl: | ||
| 10335 | return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval, result_loc); | ||
| 10336 | case NodeTypeFnProto: | ||
| 10337 | return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval, result_loc); | ||
| 10338 | case NodeTypeErrorSetDecl: | ||
| 10339 | return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval, result_loc); | ||
| 10340 | case NodeTypeResume: | ||
| 10341 | return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval, result_loc); | ||
| 10342 | case NodeTypeAwaitExpr: | ||
| 10343 | return ir_gen_await_expr(irb, scope, node, lval, result_loc); | ||
| 10344 | case NodeTypeSuspend: | ||
| 10345 | return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval, result_loc); | ||
| 10346 | case NodeTypeEnumLiteral: | ||
| 10347 | return ir_lval_wrap(irb, scope, ir_gen_enum_literal(irb, scope, node), lval, result_loc); | ||
| 10348 | case NodeTypeInferredArrayType: | ||
| 10349 | add_node_error(irb->codegen, node, | ||
| 10350 | buf_sprintf("inferred array size invalid here")); | ||
| 10351 | return irb->codegen->invalid_inst_src; | ||
| 10352 | case NodeTypeAnyTypeField: | ||
| 10353 | return ir_lval_wrap(irb, scope, | ||
| 10354 | ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_anytype), lval, result_loc); | ||
| 10355 | } | ||
| 10356 | zig_unreachable(); | ||
| 10357 | } | ||
| 10358 | |||
| 10359 | static ResultLoc *no_result_loc(void) { | ||
| 10360 | ResultLocNone *result_loc_none = heap::c_allocator.create<ResultLocNone>(); | ||
| 10361 | result_loc_none->base.id = ResultLocIdNone; | ||
| 10362 | return &result_loc_none->base; | ||
| 10363 | } | ||
| 10364 | |||
| 10365 | static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *scope, LVal lval, | ||
| 10366 | ResultLoc *result_loc) | ||
| 10367 | { | ||
| 10368 | if (lval == LValAssign) { | ||
| 10369 | switch (node->type) { | ||
| 10370 | case NodeTypeStructValueField: | ||
| 10371 | case NodeTypeParamDecl: | ||
| 10372 | case NodeTypeUsingNamespace: | ||
| 10373 | case NodeTypeSwitchProng: | ||
| 10374 | case NodeTypeSwitchRange: | ||
| 10375 | case NodeTypeStructField: | ||
| 10376 | case NodeTypeErrorSetField: | ||
| 10377 | case NodeTypeFnDef: | ||
| 10378 | case NodeTypeTestDecl: | ||
| 10379 | zig_unreachable(); | ||
| 10380 | |||
| 10381 | // cannot be assigned to | ||
| 10382 | case NodeTypeBlock: | ||
| 10383 | case NodeTypeGroupedExpr: | ||
| 10384 | case NodeTypeBinOpExpr: | ||
| 10385 | case NodeTypeIntLiteral: | ||
| 10386 | case NodeTypeFloatLiteral: | ||
| 10387 | case NodeTypeCharLiteral: | ||
| 10388 | case NodeTypeIfBoolExpr: | ||
| 10389 | case NodeTypeContainerInitExpr: | ||
| 10390 | case NodeTypeVariableDeclaration: | ||
| 10391 | case NodeTypeWhileExpr: | ||
| 10392 | case NodeTypeForExpr: | ||
| 10393 | case NodeTypeReturnExpr: | ||
| 10394 | case NodeTypeBoolLiteral: | ||
| 10395 | case NodeTypeArrayType: | ||
| 10396 | case NodeTypePointerType: | ||
| 10397 | case NodeTypeAnyFrameType: | ||
| 10398 | case NodeTypeStringLiteral: | ||
| 10399 | case NodeTypeUndefinedLiteral: | ||
| 10400 | case NodeTypeAsmExpr: | ||
| 10401 | case NodeTypeNullLiteral: | ||
| 10402 | case NodeTypeIfErrorExpr: | ||
| 10403 | case NodeTypeIfOptional: | ||
| 10404 | case NodeTypeSwitchExpr: | ||
| 10405 | case NodeTypeCompTime: | ||
| 10406 | case NodeTypeNoSuspend: | ||
| 10407 | case NodeTypeErrorType: | ||
| 10408 | case NodeTypeBreak: | ||
| 10409 | case NodeTypeContinue: | ||
| 10410 | case NodeTypeUnreachable: | ||
| 10411 | case NodeTypeDefer: | ||
| 10412 | case NodeTypeSliceExpr: | ||
| 10413 | case NodeTypeCatchExpr: | ||
| 10414 | case NodeTypeContainerDecl: | ||
| 10415 | case NodeTypeFnProto: | ||
| 10416 | case NodeTypeErrorSetDecl: | ||
| 10417 | case NodeTypeResume: | ||
| 10418 | case NodeTypeAwaitExpr: | ||
| 10419 | case NodeTypeSuspend: | ||
| 10420 | case NodeTypeEnumLiteral: | ||
| 10421 | case NodeTypeInferredArrayType: | ||
| 10422 | case NodeTypeAnyTypeField: | ||
| 10423 | case NodeTypePrefixOpExpr: | ||
| 10424 | add_node_error(irb->codegen, node, | ||
| 10425 | buf_sprintf("invalid left-hand side to assignment")); | ||
| 10426 | return irb->codegen->invalid_inst_src; | ||
| 10427 | |||
| 10428 | // @field can be assigned to | ||
| 10429 | case NodeTypeFnCallExpr: | ||
| 10430 | if (node->data.fn_call_expr.modifier == CallModifierBuiltin) { | ||
| 10431 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; | ||
| 10432 | Buf *name = fn_ref_expr->data.symbol_expr.symbol; | ||
| 10433 | auto entry = irb->codegen->builtin_fn_table.maybe_get(name); | ||
| 10434 | |||
| 10435 | if (!entry) { | ||
| 10436 | add_node_error(irb->codegen, node, | ||
| 10437 | buf_sprintf("invalid builtin function: '%s'", buf_ptr(name))); | ||
| 10438 | return irb->codegen->invalid_inst_src; | ||
| 10439 | } | ||
| 10440 | |||
| 10441 | if (entry->value->id == BuiltinFnIdField) { | ||
| 10442 | break; | ||
| 10443 | } | ||
| 10444 | } | ||
| 10445 | add_node_error(irb->codegen, node, | ||
| 10446 | buf_sprintf("invalid left-hand side to assignment")); | ||
| 10447 | return irb->codegen->invalid_inst_src; | ||
| 10448 | |||
| 10449 | |||
| 10450 | // can be assigned to | ||
| 10451 | case NodeTypeUnwrapOptional: | ||
| 10452 | case NodeTypePtrDeref: | ||
| 10453 | case NodeTypeFieldAccessExpr: | ||
| 10454 | case NodeTypeArrayAccessExpr: | ||
| 10455 | case NodeTypeSymbol: | ||
| 10456 | break; | ||
| 10457 | } | ||
| 10458 | } | ||
| 10459 | if (result_loc == nullptr) { | ||
| 10460 | // Create a result location indicating there is none - but if one gets created | ||
| 10461 | // it will be properly distributed. | ||
| 10462 | result_loc = no_result_loc(); | ||
| 10463 | ir_build_reset_result(irb, scope, node, result_loc); | ||
| 10464 | } | ||
| 10465 | Scope *child_scope; | ||
| 10466 | if (irb->exec->is_inline || | ||
| 10467 | (irb->exec->fn_entry != nullptr && irb->exec->fn_entry->child_scope == scope)) | ||
| 10468 | { | ||
| 10469 | child_scope = scope; | ||
| 10470 | } else { | ||
| 10471 | child_scope = &create_expr_scope(irb->codegen, node, scope)->base; | ||
| 10472 | } | ||
| 10473 | IrInstSrc *result = ir_gen_node_raw(irb, node, child_scope, lval, result_loc); | ||
| 10474 | if (result == irb->codegen->invalid_inst_src) { | ||
| 10475 | if (irb->exec->first_err_trace_msg == nullptr) { | ||
| 10476 | irb->exec->first_err_trace_msg = irb->codegen->trace_err; | ||
| 10477 | } | ||
| 10478 | } | ||
| 10479 | return result; | ||
| 10480 | } | ||
| 10481 | |||
| 10482 | static IrInstSrc *ir_gen_node(IrBuilderSrc *irb, AstNode *node, Scope *scope) { | ||
| 10483 | return ir_gen_node_extra(irb, node, scope, LValNone, nullptr); | ||
| 10484 | } | ||
| 10485 | |||
| 10486 | static void invalidate_exec(IrExecutableSrc *exec, ErrorMsg *msg) { | ||
| 10487 | if (exec->first_err_trace_msg != nullptr) | ||
| 10488 | return; | ||
| 10489 | |||
| 10490 | exec->first_err_trace_msg = msg; | ||
| 10491 | |||
| 10492 | for (size_t i = 0; i < exec->tld_list.length; i += 1) { | ||
| 10493 | exec->tld_list.items[i]->resolution = TldResolutionInvalid; | ||
| 10494 | } | ||
| 10495 | } | ||
| 10496 | |||
| 10497 | static void invalidate_exec_gen(IrExecutableGen *exec, ErrorMsg *msg) { | ||
| 10498 | if (exec->first_err_trace_msg != nullptr) | 2520 | if (exec->first_err_trace_msg != nullptr) |
| 10499 | return; | 2521 | return; |
| 10500 | 2522 | ||
| ... | @@ -10509,79 +2531,7 @@ static void invalidate_exec_gen(IrExecutableGen *exec, ErrorMsg *msg) { | ... | @@ -10509,79 +2531,7 @@ static void invalidate_exec_gen(IrExecutableGen *exec, ErrorMsg *msg) { |
| 10509 | } | 2531 | } |
| 10510 | 2532 | ||
| 10511 | 2533 | ||
| 10512 | bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutableSrc *ir_executable) { | 2534 | static ErrorMsg *exec_add_error_node_gen(CodeGen *codegen, Stage1Air *exec, AstNode *source_node, Buf *msg) { |
| 10513 | assert(node->owner); | ||
| 10514 | |||
| 10515 | IrBuilderSrc ir_builder = {0}; | ||
| 10516 | IrBuilderSrc *irb = &ir_builder; | ||
| 10517 | |||
| 10518 | irb->codegen = codegen; | ||
| 10519 | irb->exec = ir_executable; | ||
| 10520 | irb->main_block_node = node; | ||
| 10521 | |||
| 10522 | IrBasicBlockSrc *entry_block = ir_create_basic_block(irb, scope, "Entry"); | ||
| 10523 | ir_set_cursor_at_end_and_append_block(irb, entry_block); | ||
| 10524 | // Entry block gets a reference because we enter it to begin. | ||
| 10525 | ir_ref_bb(irb->current_basic_block); | ||
| 10526 | |||
| 10527 | IrInstSrc *result = ir_gen_node_extra(irb, node, scope, LValNone, nullptr); | ||
| 10528 | |||
| 10529 | if (result == irb->codegen->invalid_inst_src) | ||
| 10530 | return false; | ||
| 10531 | |||
| 10532 | if (irb->exec->first_err_trace_msg != nullptr) { | ||
| 10533 | codegen->trace_err = irb->exec->first_err_trace_msg; | ||
| 10534 | return false; | ||
| 10535 | } | ||
| 10536 | |||
| 10537 | if (!instr_is_unreachable(result)) { | ||
| 10538 | ir_mark_gen(ir_build_add_implicit_return_type(irb, scope, result->base.source_node, result, nullptr)); | ||
| 10539 | // no need for save_err_ret_addr because this cannot return error | ||
| 10540 | ResultLocReturn *result_loc_ret = heap::c_allocator.create<ResultLocReturn>(); | ||
| 10541 | result_loc_ret->base.id = ResultLocIdReturn; | ||
| 10542 | ir_build_reset_result(irb, scope, node, &result_loc_ret->base); | ||
| 10543 | ir_mark_gen(ir_build_end_expr(irb, scope, node, result, &result_loc_ret->base)); | ||
| 10544 | ir_mark_gen(ir_build_return_src(irb, scope, result->base.source_node, result)); | ||
| 10545 | } | ||
| 10546 | |||
| 10547 | return true; | ||
| 10548 | } | ||
| 10549 | |||
| 10550 | bool ir_gen_fn(CodeGen *codegen, ZigFn *fn_entry) { | ||
| 10551 | assert(fn_entry); | ||
| 10552 | |||
| 10553 | IrExecutableSrc *ir_executable = fn_entry->ir_executable; | ||
| 10554 | AstNode *body_node = fn_entry->body_node; | ||
| 10555 | |||
| 10556 | assert(fn_entry->child_scope); | ||
| 10557 | |||
| 10558 | return ir_gen(codegen, body_node, fn_entry->child_scope, ir_executable); | ||
| 10559 | } | ||
| 10560 | |||
| 10561 | static void ir_add_call_stack_errors_gen(CodeGen *codegen, IrExecutableGen *exec, ErrorMsg *err_msg, int limit) { | ||
| 10562 | if (!exec || !exec->source_node || limit < 0) return; | ||
| 10563 | add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); | ||
| 10564 | |||
| 10565 | ir_add_call_stack_errors_gen(codegen, exec->parent_exec, err_msg, limit - 1); | ||
| 10566 | } | ||
| 10567 | |||
| 10568 | static void ir_add_call_stack_errors(CodeGen *codegen, IrExecutableSrc *exec, ErrorMsg *err_msg, int limit) { | ||
| 10569 | if (!exec || !exec->source_node || limit < 0) return; | ||
| 10570 | add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); | ||
| 10571 | |||
| 10572 | ir_add_call_stack_errors_gen(codegen, exec->parent_exec, err_msg, limit - 1); | ||
| 10573 | } | ||
| 10574 | |||
| 10575 | static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutableSrc *exec, AstNode *source_node, Buf *msg) { | ||
| 10576 | ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); | ||
| 10577 | invalidate_exec(exec, err_msg); | ||
| 10578 | if (exec->parent_exec) { | ||
| 10579 | ir_add_call_stack_errors(codegen, exec, err_msg, 10); | ||
| 10580 | } | ||
| 10581 | return err_msg; | ||
| 10582 | } | ||
| 10583 | |||
| 10584 | static ErrorMsg *exec_add_error_node_gen(CodeGen *codegen, IrExecutableGen *exec, AstNode *source_node, Buf *msg) { | ||
| 10585 | ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); | 2535 | ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); |
| 10586 | invalidate_exec_gen(exec, err_msg); | 2536 | invalidate_exec_gen(exec, err_msg); |
| 10587 | if (exec->parent_exec) { | 2537 | if (exec->parent_exec) { |
| ... | @@ -10605,11 +2555,6 @@ static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInst *source_instruction, Buf *m | ... | @@ -10605,11 +2555,6 @@ static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInst *source_instruction, Buf *m |
| 10605 | return ir_add_error_node(ira, source_instruction->source_node, msg); | 2555 | return ir_add_error_node(ira, source_instruction->source_node, msg); |
| 10606 | } | 2556 | } |
| 10607 | 2557 | ||
| 10608 | static void ir_assert_impl(bool ok, IrInst *source_instruction, char const *file, unsigned int line) { | ||
| 10609 | if (ok) return; | ||
| 10610 | src_assert_impl(ok, source_instruction->source_node, file, line); | ||
| 10611 | } | ||
| 10612 | |||
| 10613 | static void ir_assert_gen_impl(bool ok, IrInstGen *source_instruction, char const *file, unsigned int line) { | 2558 | static void ir_assert_gen_impl(bool ok, IrInstGen *source_instruction, char const *file, unsigned int line) { |
| 10614 | if (ok) return; | 2559 | if (ok) return; |
| 10615 | src_assert_impl(ok, source_instruction->base.source_node, file, line); | 2560 | src_assert_impl(ok, source_instruction->base.source_node, file, line); |
| ... | @@ -10660,7 +2605,7 @@ ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_va | ... | @@ -10660,7 +2605,7 @@ ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_va |
| 10660 | return val; | 2605 | return val; |
| 10661 | } | 2606 | } |
| 10662 | 2607 | ||
| 10663 | static Error ir_exec_scan_for_side_effects(CodeGen *codegen, IrExecutableGen *exec) { | 2608 | static Error ir_exec_scan_for_side_effects(CodeGen *codegen, Stage1Air *exec) { |
| 10664 | IrBasicBlockGen *bb = exec->basic_block_list.at(0); | 2609 | IrBasicBlockGen *bb = exec->basic_block_list.at(0); |
| 10665 | for (size_t i = 0; i < bb->instruction_list.length; i += 1) { | 2610 | for (size_t i = 0; i < bb->instruction_list.length; i += 1) { |
| 10666 | IrInstGen *instruction = bb->instruction_list.at(i); | 2611 | IrInstGen *instruction = bb->instruction_list.at(i); |
| ... | @@ -10690,7 +2635,7 @@ static Error ir_exec_scan_for_side_effects(CodeGen *codegen, IrExecutableGen *ex | ... | @@ -10690,7 +2635,7 @@ static Error ir_exec_scan_for_side_effects(CodeGen *codegen, IrExecutableGen *ex |
| 10690 | } | 2635 | } |
| 10691 | 2636 | ||
| 10692 | static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInst* source_instruction) { | 2637 | static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInst* source_instruction) { |
| 10693 | if (ir_should_inline(ira->old_irb.exec, source_instruction->scope)) { | 2638 | if (ir_should_inline(ira->zir, source_instruction->scope)) { |
| 10694 | ir_add_error(ira, source_instruction, buf_sprintf("unable to evaluate constant expression")); | 2639 | ir_add_error(ira, source_instruction, buf_sprintf("unable to evaluate constant expression")); |
| 10695 | return false; | 2640 | return false; |
| 10696 | } | 2641 | } |
| ... | @@ -12315,7 +4260,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -12315,7 +4260,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 12315 | continue; | 4260 | continue; |
| 12316 | } | 4261 | } |
| 12317 | bool allow_infer = cur_type->data.error_set.infer_fn != nullptr && | 4262 | bool allow_infer = cur_type->data.error_set.infer_fn != nullptr && |
| 12318 | cur_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; | 4263 | cur_type->data.error_set.infer_fn == ira->fn; |
| 12319 | if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->base.source_node)) { | 4264 | if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->base.source_node)) { |
| 12320 | return ira->codegen->builtin_types.entry_invalid; | 4265 | return ira->codegen->builtin_types.entry_invalid; |
| 12321 | } | 4266 | } |
| ... | @@ -12383,7 +4328,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -12383,7 +4328,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 12383 | } | 4328 | } |
| 12384 | ZigType *cur_err_set_type = cur_type->data.error_union.err_set_type; | 4329 | ZigType *cur_err_set_type = cur_type->data.error_union.err_set_type; |
| 12385 | bool allow_infer = cur_err_set_type->data.error_set.infer_fn != nullptr && | 4330 | bool allow_infer = cur_err_set_type->data.error_set.infer_fn != nullptr && |
| 12386 | cur_err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; | 4331 | cur_err_set_type->data.error_set.infer_fn == ira->fn; |
| 12387 | if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->base.source_node)) { | 4332 | if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->base.source_node)) { |
| 12388 | return ira->codegen->builtin_types.entry_invalid; | 4333 | return ira->codegen->builtin_types.entry_invalid; |
| 12389 | } | 4334 | } |
| ... | @@ -12438,7 +4383,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -12438,7 +4383,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 12438 | 4383 | ||
| 12439 | if (cur_type->id == ZigTypeIdErrorSet) { | 4384 | if (cur_type->id == ZigTypeIdErrorSet) { |
| 12440 | bool allow_infer = cur_type->data.error_set.infer_fn != nullptr && | 4385 | bool allow_infer = cur_type->data.error_set.infer_fn != nullptr && |
| 12441 | cur_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; | 4386 | cur_type->data.error_set.infer_fn == ira->fn; |
| 12442 | if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->base.source_node)) { | 4387 | if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->base.source_node)) { |
| 12443 | return ira->codegen->builtin_types.entry_invalid; | 4388 | return ira->codegen->builtin_types.entry_invalid; |
| 12444 | } | 4389 | } |
| ... | @@ -12457,7 +4402,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -12457,7 +4402,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 12457 | if (prev_type->id == ZigTypeIdErrorUnion) { | 4402 | if (prev_type->id == ZigTypeIdErrorUnion) { |
| 12458 | err_set_type = prev_type->data.error_union.err_set_type; | 4403 | err_set_type = prev_type->data.error_union.err_set_type; |
| 12459 | allow_infer = err_set_type->data.error_set.infer_fn != nullptr && | 4404 | allow_infer = err_set_type->data.error_set.infer_fn != nullptr && |
| 12460 | err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; | 4405 | err_set_type->data.error_set.infer_fn == ira->fn; |
| 12461 | } else { | 4406 | } else { |
| 12462 | err_set_type = cur_type; | 4407 | err_set_type = cur_type; |
| 12463 | } | 4408 | } |
| ... | @@ -12521,9 +4466,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -12521,9 +4466,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 12521 | continue; | 4466 | continue; |
| 12522 | 4467 | ||
| 12523 | bool allow_infer_prev = prev_err_set_type->data.error_set.infer_fn != nullptr && | 4468 | bool allow_infer_prev = prev_err_set_type->data.error_set.infer_fn != nullptr && |
| 12524 | prev_err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; | 4469 | prev_err_set_type->data.error_set.infer_fn == ira->fn; |
| 12525 | bool allow_infer_cur = cur_err_set_type->data.error_set.infer_fn != nullptr && | 4470 | bool allow_infer_cur = cur_err_set_type->data.error_set.infer_fn != nullptr && |
| 12526 | cur_err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; | 4471 | cur_err_set_type->data.error_set.infer_fn == ira->fn; |
| 12527 | 4472 | ||
| 12528 | if (!allow_infer_prev && !resolve_inferred_error_set(ira->codegen, prev_err_set_type, cur_inst->base.source_node)) { | 4473 | if (!allow_infer_prev && !resolve_inferred_error_set(ira->codegen, prev_err_set_type, cur_inst->base.source_node)) { |
| 12529 | return ira->codegen->builtin_types.entry_invalid; | 4474 | return ira->codegen->builtin_types.entry_invalid; |
| ... | @@ -12707,7 +4652,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -12707,7 +4652,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 12707 | if (err_set_type != nullptr) { | 4652 | if (err_set_type != nullptr) { |
| 12708 | ZigType *cur_err_set_type = cur_type->data.error_union.err_set_type; | 4653 | ZigType *cur_err_set_type = cur_type->data.error_union.err_set_type; |
| 12709 | bool allow_infer = cur_err_set_type->data.error_set.infer_fn != nullptr && | 4654 | bool allow_infer = cur_err_set_type->data.error_set.infer_fn != nullptr && |
| 12710 | cur_err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry; | 4655 | cur_err_set_type->data.error_set.infer_fn == ira->fn; |
| 12711 | if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->base.source_node)) { | 4656 | if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->base.source_node)) { |
| 12712 | return ira->codegen->builtin_types.entry_invalid; | 4657 | return ira->codegen->builtin_types.entry_invalid; |
| 12713 | } | 4658 | } |
| ... | @@ -13316,7 +5261,7 @@ static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* sourc | ... | @@ -13316,7 +5261,7 @@ static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* sourc |
| 13316 | return ir_build_ptr_of_array_to_slice(ira, source_instr, wanted_type, array_ptr, result_loc_inst); | 5261 | return ir_build_ptr_of_array_to_slice(ira, source_instr, wanted_type, array_ptr, result_loc_inst); |
| 13317 | } | 5262 | } |
| 13318 | 5263 | ||
| 13319 | static IrBasicBlockGen *ir_get_new_bb(IrAnalyze *ira, IrBasicBlockSrc *old_bb, IrInst *ref_old_instruction) { | 5264 | static IrBasicBlockGen *ir_get_new_bb(IrAnalyze *ira, Stage1ZirBasicBlock *old_bb, IrInst *ref_old_instruction) { |
| 13320 | assert(old_bb); | 5265 | assert(old_bb); |
| 13321 | 5266 | ||
| 13322 | if (old_bb->child) { | 5267 | if (old_bb->child) { |
| ... | @@ -13331,7 +5276,7 @@ static IrBasicBlockGen *ir_get_new_bb(IrAnalyze *ira, IrBasicBlockSrc *old_bb, I | ... | @@ -13331,7 +5276,7 @@ static IrBasicBlockGen *ir_get_new_bb(IrAnalyze *ira, IrBasicBlockSrc *old_bb, I |
| 13331 | return new_bb; | 5276 | return new_bb; |
| 13332 | } | 5277 | } |
| 13333 | 5278 | ||
| 13334 | static IrBasicBlockGen *ir_get_new_bb_runtime(IrAnalyze *ira, IrBasicBlockSrc *old_bb, IrInst *ref_old_instruction) { | 5279 | static IrBasicBlockGen *ir_get_new_bb_runtime(IrAnalyze *ira, Stage1ZirBasicBlock *old_bb, IrInst *ref_old_instruction) { |
| 13335 | assert(ref_old_instruction != nullptr); | 5280 | assert(ref_old_instruction != nullptr); |
| 13336 | IrBasicBlockGen *new_bb = ir_get_new_bb(ira, old_bb, ref_old_instruction); | 5281 | IrBasicBlockGen *new_bb = ir_get_new_bb(ira, old_bb, ref_old_instruction); |
| 13337 | if (new_bb->must_be_comptime_source_instr) { | 5282 | if (new_bb->must_be_comptime_source_instr) { |
| ... | @@ -13344,36 +5289,36 @@ static IrBasicBlockGen *ir_get_new_bb_runtime(IrAnalyze *ira, IrBasicBlockSrc *o | ... | @@ -13344,36 +5289,36 @@ static IrBasicBlockGen *ir_get_new_bb_runtime(IrAnalyze *ira, IrBasicBlockSrc *o |
| 13344 | return new_bb; | 5289 | return new_bb; |
| 13345 | } | 5290 | } |
| 13346 | 5291 | ||
| 13347 | static void ir_start_bb(IrAnalyze *ira, IrBasicBlockSrc *old_bb, IrBasicBlockSrc *const_predecessor_bb) { | 5292 | static void ir_start_bb(IrAnalyze *ira, Stage1ZirBasicBlock *old_bb, Stage1ZirBasicBlock *const_predecessor_bb) { |
| 13348 | ir_assert(!old_bb->suspended, (old_bb->instruction_list.length != 0) ? &old_bb->instruction_list.at(0)->base : nullptr); | 5293 | ir_assert(!old_bb->suspended, (old_bb->instruction_list.length != 0) ? &old_bb->instruction_list.at(0)->base : nullptr); |
| 13349 | ira->instruction_index = 0; | 5294 | ira->instruction_index = 0; |
| 13350 | ira->old_irb.current_basic_block = old_bb; | 5295 | ira->zir_current_basic_block = old_bb; |
| 13351 | ira->const_predecessor_bb = const_predecessor_bb; | 5296 | ira->const_predecessor_bb = const_predecessor_bb; |
| 13352 | ira->old_bb_index = old_bb->index; | 5297 | ira->old_bb_index = old_bb->index; |
| 13353 | } | 5298 | } |
| 13354 | 5299 | ||
| 13355 | static IrInstGen *ira_suspend(IrAnalyze *ira, IrInst *old_instruction, IrBasicBlockSrc *next_bb, | 5300 | static IrInstGen *ira_suspend(IrAnalyze *ira, IrInst *old_instruction, Stage1ZirBasicBlock *next_bb, |
| 13356 | IrSuspendPosition *suspend_pos) | 5301 | IrSuspendPosition *suspend_pos) |
| 13357 | { | 5302 | { |
| 13358 | if (ira->codegen->verbose_ir) { | 5303 | if (ira->codegen->verbose_ir) { |
| 13359 | fprintf(stderr, "suspend %s_%" PRIu32 " %s_%" PRIu32 " #%" PRIu32 " (%zu,%zu)\n", | 5304 | fprintf(stderr, "suspend %s_%" PRIu32 " %s_%" PRIu32 " #%" PRIu32 " (%zu,%zu)\n", |
| 13360 | ira->old_irb.current_basic_block->name_hint, | 5305 | ira->zir_current_basic_block->name_hint, |
| 13361 | ira->old_irb.current_basic_block->debug_id, | 5306 | ira->zir_current_basic_block->debug_id, |
| 13362 | ira->old_irb.exec->basic_block_list.at(ira->old_bb_index)->name_hint, | 5307 | ira->zir->basic_block_list.at(ira->old_bb_index)->name_hint, |
| 13363 | ira->old_irb.exec->basic_block_list.at(ira->old_bb_index)->debug_id, | 5308 | ira->zir->basic_block_list.at(ira->old_bb_index)->debug_id, |
| 13364 | ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index)->base.debug_id, | 5309 | ira->zir_current_basic_block->instruction_list.at(ira->instruction_index)->base.debug_id, |
| 13365 | ira->old_bb_index, ira->instruction_index); | 5310 | ira->old_bb_index, ira->instruction_index); |
| 13366 | } | 5311 | } |
| 13367 | suspend_pos->basic_block_index = ira->old_bb_index; | 5312 | suspend_pos->basic_block_index = ira->old_bb_index; |
| 13368 | suspend_pos->instruction_index = ira->instruction_index; | 5313 | suspend_pos->instruction_index = ira->instruction_index; |
| 13369 | 5314 | ||
| 13370 | ira->old_irb.current_basic_block->suspended = true; | 5315 | ira->zir_current_basic_block->suspended = true; |
| 13371 | 5316 | ||
| 13372 | // null next_bb means that the caller plans to call ira_resume before returning | 5317 | // null next_bb means that the caller plans to call ira_resume before returning |
| 13373 | if (next_bb != nullptr) { | 5318 | if (next_bb != nullptr) { |
| 13374 | ira->old_bb_index = next_bb->index; | 5319 | ira->old_bb_index = next_bb->index; |
| 13375 | ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index); | 5320 | ira->zir_current_basic_block = ira->zir->basic_block_list.at(ira->old_bb_index); |
| 13376 | assert(ira->old_irb.current_basic_block == next_bb); | 5321 | assert(ira->zir_current_basic_block == next_bb); |
| 13377 | ira->instruction_index = 0; | 5322 | ira->instruction_index = 0; |
| 13378 | ira->const_predecessor_bb = nullptr; | 5323 | ira->const_predecessor_bb = nullptr; |
| 13379 | next_bb->child = ir_get_new_bb_runtime(ira, next_bb, old_instruction); | 5324 | next_bb->child = ir_get_new_bb_runtime(ira, next_bb, old_instruction); |
| ... | @@ -13388,19 +5333,19 @@ static IrInstGen *ira_resume(IrAnalyze *ira) { | ... | @@ -13388,19 +5333,19 @@ static IrInstGen *ira_resume(IrAnalyze *ira) { |
| 13388 | fprintf(stderr, "resume (%zu,%zu) ", pos.basic_block_index, pos.instruction_index); | 5333 | fprintf(stderr, "resume (%zu,%zu) ", pos.basic_block_index, pos.instruction_index); |
| 13389 | } | 5334 | } |
| 13390 | ira->old_bb_index = pos.basic_block_index; | 5335 | ira->old_bb_index = pos.basic_block_index; |
| 13391 | ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index); | 5336 | ira->zir_current_basic_block = ira->zir->basic_block_list.at(ira->old_bb_index); |
| 13392 | assert(ira->old_irb.current_basic_block->in_resume_stack); | 5337 | assert(ira->zir_current_basic_block->in_resume_stack); |
| 13393 | ira->old_irb.current_basic_block->in_resume_stack = false; | 5338 | ira->zir_current_basic_block->in_resume_stack = false; |
| 13394 | ira->old_irb.current_basic_block->suspended = false; | 5339 | ira->zir_current_basic_block->suspended = false; |
| 13395 | ira->instruction_index = pos.instruction_index; | 5340 | ira->instruction_index = pos.instruction_index; |
| 13396 | assert(pos.instruction_index < ira->old_irb.current_basic_block->instruction_list.length); | 5341 | assert(pos.instruction_index < ira->zir_current_basic_block->instruction_list.length); |
| 13397 | if (ira->codegen->verbose_ir) { | 5342 | if (ira->codegen->verbose_ir) { |
| 13398 | fprintf(stderr, "%s_%" PRIu32 " #%" PRIu32 "\n", ira->old_irb.current_basic_block->name_hint, | 5343 | fprintf(stderr, "%s_%" PRIu32 " #%" PRIu32 "\n", ira->zir_current_basic_block->name_hint, |
| 13399 | ira->old_irb.current_basic_block->debug_id, | 5344 | ira->zir_current_basic_block->debug_id, |
| 13400 | ira->old_irb.current_basic_block->instruction_list.at(pos.instruction_index)->base.debug_id); | 5345 | ira->zir_current_basic_block->instruction_list.at(pos.instruction_index)->base.debug_id); |
| 13401 | } | 5346 | } |
| 13402 | ira->const_predecessor_bb = nullptr; | 5347 | ira->const_predecessor_bb = nullptr; |
| 13403 | ira->new_irb.current_basic_block = ira->old_irb.current_basic_block->child; | 5348 | ira->new_irb.current_basic_block = ira->zir_current_basic_block->child; |
| 13404 | assert(ira->new_irb.current_basic_block != nullptr); | 5349 | assert(ira->new_irb.current_basic_block != nullptr); |
| 13405 | return ira->codegen->unreach_instruction; | 5350 | return ira->codegen->unreach_instruction; |
| 13406 | } | 5351 | } |
| ... | @@ -13410,8 +5355,8 @@ static void ir_start_next_bb(IrAnalyze *ira) { | ... | @@ -13410,8 +5355,8 @@ static void ir_start_next_bb(IrAnalyze *ira) { |
| 13410 | 5355 | ||
| 13411 | bool need_repeat = true; | 5356 | bool need_repeat = true; |
| 13412 | for (;;) { | 5357 | for (;;) { |
| 13413 | while (ira->old_bb_index < ira->old_irb.exec->basic_block_list.length) { | 5358 | while (ira->old_bb_index < ira->zir->basic_block_list.length) { |
| 13414 | IrBasicBlockSrc *old_bb = ira->old_irb.exec->basic_block_list.at(ira->old_bb_index); | 5359 | Stage1ZirBasicBlock *old_bb = ira->zir->basic_block_list.at(ira->old_bb_index); |
| 13415 | if (old_bb->child == nullptr && old_bb->suspend_instruction_ref == nullptr) { | 5360 | if (old_bb->child == nullptr && old_bb->suspend_instruction_ref == nullptr) { |
| 13416 | ira->old_bb_index += 1; | 5361 | ira->old_bb_index += 1; |
| 13417 | continue; | 5362 | continue; |
| ... | @@ -13463,8 +5408,8 @@ static void ir_finish_bb(IrAnalyze *ira) { | ... | @@ -13463,8 +5408,8 @@ static void ir_finish_bb(IrAnalyze *ira) { |
| 13463 | } | 5408 | } |
| 13464 | } | 5409 | } |
| 13465 | ira->instruction_index += 1; | 5410 | ira->instruction_index += 1; |
| 13466 | while (ira->instruction_index < ira->old_irb.current_basic_block->instruction_list.length) { | 5411 | while (ira->instruction_index < ira->zir_current_basic_block->instruction_list.length) { |
| 13467 | IrInstSrc *next_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); | 5412 | IrInstSrc *next_instruction = ira->zir_current_basic_block->instruction_list.at(ira->instruction_index); |
| 13468 | if (!next_instruction->is_gen) { | 5413 | if (!next_instruction->is_gen) { |
| 13469 | ir_add_error(ira, &next_instruction->base, buf_sprintf("unreachable code")); | 5414 | ir_add_error(ira, &next_instruction->base, buf_sprintf("unreachable code")); |
| 13470 | break; | 5415 | break; |
| ... | @@ -13484,8 +5429,8 @@ static IrInstGen *ir_unreach_error(IrAnalyze *ira) { | ... | @@ -13484,8 +5429,8 @@ static IrInstGen *ir_unreach_error(IrAnalyze *ira) { |
| 13484 | } | 5429 | } |
| 13485 | 5430 | ||
| 13486 | static bool ir_emit_backward_branch(IrAnalyze *ira, IrInst* source_instruction) { | 5431 | static bool ir_emit_backward_branch(IrAnalyze *ira, IrInst* source_instruction) { |
| 13487 | size_t *bbc = ira->new_irb.exec->backward_branch_count; | 5432 | size_t *bbc = ira->backward_branch_count; |
| 13488 | size_t *quota = ira->new_irb.exec->backward_branch_quota; | 5433 | size_t *quota = ira->backward_branch_quota; |
| 13489 | 5434 | ||
| 13490 | // If we're already over quota, we've already given an error message for this. | 5435 | // If we're already over quota, we've already given an error message for this. |
| 13491 | if (*bbc > *quota) { | 5436 | if (*bbc > *quota) { |
| ... | @@ -13502,14 +5447,14 @@ static bool ir_emit_backward_branch(IrAnalyze *ira, IrInst* source_instruction) | ... | @@ -13502,14 +5447,14 @@ static bool ir_emit_backward_branch(IrAnalyze *ira, IrInst* source_instruction) |
| 13502 | return true; | 5447 | return true; |
| 13503 | } | 5448 | } |
| 13504 | 5449 | ||
| 13505 | static IrInstGen *ir_inline_bb(IrAnalyze *ira, IrInst* source_instruction, IrBasicBlockSrc *old_bb) { | 5450 | static IrInstGen *ir_inline_bb(IrAnalyze *ira, IrInst* source_instruction, Stage1ZirBasicBlock *old_bb) { |
| 13506 | if (old_bb->debug_id <= ira->old_irb.current_basic_block->debug_id) { | 5451 | if (old_bb->debug_id <= ira->zir_current_basic_block->debug_id) { |
| 13507 | if (!ir_emit_backward_branch(ira, source_instruction)) | 5452 | if (!ir_emit_backward_branch(ira, source_instruction)) |
| 13508 | return ir_unreach_error(ira); | 5453 | return ir_unreach_error(ira); |
| 13509 | } | 5454 | } |
| 13510 | 5455 | ||
| 13511 | old_bb->child = ira->old_irb.current_basic_block->child; | 5456 | old_bb->child = ira->zir_current_basic_block->child; |
| 13512 | ir_start_bb(ira, old_bb, ira->old_irb.current_basic_block); | 5457 | ir_start_bb(ira, old_bb, ira->zir_current_basic_block); |
| 13513 | return ira->codegen->unreach_instruction; | 5458 | return ira->codegen->unreach_instruction; |
| 13514 | } | 5459 | } |
| 13515 | 5460 | ||
| ... | @@ -13591,7 +5536,7 @@ static IrInstGen *ir_get_const_ptr(IrAnalyze *ira, IrInst *instruction, | ... | @@ -13591,7 +5536,7 @@ static IrInstGen *ir_get_const_ptr(IrAnalyze *ira, IrInst *instruction, |
| 13591 | return const_instr; | 5536 | return const_instr; |
| 13592 | } | 5537 | } |
| 13593 | 5538 | ||
| 13594 | static Error ir_resolve_const_val(CodeGen *codegen, IrExecutableGen *exec, AstNode *source_node, | 5539 | static Error ir_resolve_const_val(CodeGen *codegen, Stage1Air *exec, AstNode *source_node, |
| 13595 | ZigValue *val, UndefAllowed undef_allowed) | 5540 | ZigValue *val, UndefAllowed undef_allowed) |
| 13596 | { | 5541 | { |
| 13597 | Error err; | 5542 | Error err; |
| ... | @@ -13638,7 +5583,7 @@ static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstGen *value, UndefAllowed | ... | @@ -13638,7 +5583,7 @@ static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstGen *value, UndefAllowed |
| 13638 | Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, | 5583 | Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, |
| 13639 | ZigValue *return_ptr, size_t *backward_branch_count, size_t *backward_branch_quota, | 5584 | ZigValue *return_ptr, size_t *backward_branch_count, size_t *backward_branch_quota, |
| 13640 | ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, | 5585 | ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, |
| 13641 | IrExecutableGen *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef_allowed) | 5586 | Stage1Air *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef_allowed) |
| 13642 | { | 5587 | { |
| 13643 | Error err; | 5588 | Error err; |
| 13644 | 5589 | ||
| ... | @@ -13647,43 +5592,38 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, | ... | @@ -13647,43 +5592,38 @@ Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, |
| 13647 | if (type_is_invalid(return_ptr->type)) | 5592 | if (type_is_invalid(return_ptr->type)) |
| 13648 | return ErrorSemanticAnalyzeFail; | 5593 | return ErrorSemanticAnalyzeFail; |
| 13649 | 5594 | ||
| 13650 | IrExecutableSrc *ir_executable = heap::c_allocator.create<IrExecutableSrc>(); | 5595 | Stage1Zir *stage1_zir = heap::c_allocator.create<Stage1Zir>(); |
| 13651 | ir_executable->source_node = source_node; | 5596 | stage1_zir->name = exec_name; |
| 13652 | ir_executable->parent_exec = parent_exec; | 5597 | stage1_zir->is_inline = true; |
| 13653 | ir_executable->name = exec_name; | 5598 | stage1_zir->begin_scope = scope; |
| 13654 | ir_executable->is_inline = true; | 5599 | |
| 13655 | ir_executable->fn_entry = fn_entry; | 5600 | bool in_c_import_scope = c_import_buf != nullptr; |
| 13656 | ir_executable->c_import_buf = c_import_buf; | ||
| 13657 | ir_executable->begin_scope = scope; | ||
| 13658 | 5601 | ||
| 13659 | if (!ir_gen(codegen, node, scope, ir_executable)) | 5602 | if (!stage1_astgen(codegen, node, scope, stage1_zir, fn_entry, in_c_import_scope)) |
| 13660 | return ErrorSemanticAnalyzeFail; | 5603 | return ErrorSemanticAnalyzeFail; |
| 13661 | 5604 | ||
| 13662 | if (ir_executable->first_err_trace_msg != nullptr) { | 5605 | if (stage1_zir->first_err_trace_msg != nullptr) { |
| 13663 | codegen->trace_err = ir_executable->first_err_trace_msg; | 5606 | codegen->trace_err = stage1_zir->first_err_trace_msg; |
| 13664 | return ErrorSemanticAnalyzeFail; | 5607 | return ErrorSemanticAnalyzeFail; |
| 13665 | } | 5608 | } |
| 13666 | 5609 | ||
| 13667 | if (codegen->verbose_ir) { | 5610 | if (codegen->verbose_ir) { |
| 13668 | fprintf(stderr, "\nSource: "); | ||
| 13669 | ast_render(stderr, node, 4); | ||
| 13670 | fprintf(stderr, "\n{ // (IR)\n"); | 5611 | fprintf(stderr, "\n{ // (IR)\n"); |
| 13671 | ir_print_src(codegen, stderr, ir_executable, 2); | 5612 | ir_print_src(codegen, stderr, stage1_zir, 2); |
| 13672 | fprintf(stderr, "}\n"); | 5613 | fprintf(stderr, "}\n"); |
| 13673 | } | 5614 | } |
| 13674 | IrExecutableGen *analyzed_executable = heap::c_allocator.create<IrExecutableGen>(); | 5615 | Stage1Air *analyzed_executable = heap::c_allocator.create<Stage1Air>(); |
| 13675 | analyzed_executable->source_node = source_node; | 5616 | analyzed_executable->source_node = source_node; |
| 13676 | analyzed_executable->parent_exec = parent_exec; | 5617 | analyzed_executable->parent_exec = parent_exec; |
| 13677 | analyzed_executable->source_exec = ir_executable; | 5618 | analyzed_executable->source_exec = stage1_zir; |
| 13678 | analyzed_executable->name = exec_name; | 5619 | analyzed_executable->name = exec_name; |
| 13679 | analyzed_executable->is_inline = true; | 5620 | analyzed_executable->is_inline = true; |
| 13680 | analyzed_executable->fn_entry = fn_entry; | ||
| 13681 | analyzed_executable->c_import_buf = c_import_buf; | 5621 | analyzed_executable->c_import_buf = c_import_buf; |
| 13682 | analyzed_executable->backward_branch_count = backward_branch_count; | ||
| 13683 | analyzed_executable->backward_branch_quota = backward_branch_quota; | ||
| 13684 | analyzed_executable->begin_scope = scope; | 5622 | analyzed_executable->begin_scope = scope; |
| 13685 | ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, | 5623 | ZigType *result_type = ir_analyze(codegen, stage1_zir, analyzed_executable, |
| 13686 | return_ptr->type->data.pointer.child_type, expected_type_source_node, return_ptr); | 5624 | backward_branch_count, backward_branch_quota, |
| 5625 | return_ptr->type->data.pointer.child_type, expected_type_source_node, return_ptr, | ||
| 5626 | fn_entry); | ||
| 13687 | if (type_is_invalid(result_type)) { | 5627 | if (type_is_invalid(result_type)) { |
| 13688 | return ErrorSemanticAnalyzeFail; | 5628 | return ErrorSemanticAnalyzeFail; |
| 13689 | } | 5629 | } |
| ... | @@ -13724,7 +5664,7 @@ static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstGen *err_value) { | ... | @@ -13724,7 +5664,7 @@ static ErrorTableEntry *ir_resolve_error(IrAnalyze *ira, IrInstGen *err_value) { |
| 13724 | return const_val->data.x_err_set; | 5664 | return const_val->data.x_err_set; |
| 13725 | } | 5665 | } |
| 13726 | 5666 | ||
| 13727 | static ZigType *ir_resolve_const_type(CodeGen *codegen, IrExecutableGen *exec, AstNode *source_node, | 5667 | static ZigType *ir_resolve_const_type(CodeGen *codegen, Stage1Air *exec, AstNode *source_node, |
| 13728 | ZigValue *val) | 5668 | ZigValue *val) |
| 13729 | { | 5669 | { |
| 13730 | Error err; | 5670 | Error err; |
| ... | @@ -14976,7 +6916,7 @@ static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* sou | ... | @@ -14976,7 +6916,7 @@ static IrInstGen *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInst* sou |
| 14976 | size_t instr_field_count = actual_type->data.structure.src_field_count; | 6916 | size_t instr_field_count = actual_type->data.structure.src_field_count; |
| 14977 | assert(array_len == instr_field_count); | 6917 | assert(array_len == instr_field_count); |
| 14978 | 6918 | ||
| 14979 | bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope) | 6919 | bool need_comptime = ir_should_inline(ira->zir, source_instr->scope) |
| 14980 | || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes; | 6920 | || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes; |
| 14981 | bool is_comptime = true; | 6921 | bool is_comptime = true; |
| 14982 | 6922 | ||
| ... | @@ -15066,7 +7006,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so | ... | @@ -15066,7 +7006,7 @@ static IrInstGen *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInst* so |
| 15066 | size_t actual_field_count = wanted_type->data.structure.src_field_count; | 7006 | size_t actual_field_count = wanted_type->data.structure.src_field_count; |
| 15067 | size_t instr_field_count = actual_type->data.structure.src_field_count; | 7007 | size_t instr_field_count = actual_type->data.structure.src_field_count; |
| 15068 | 7008 | ||
| 15069 | bool need_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope) | 7009 | bool need_comptime = ir_should_inline(ira->zir, source_instr->scope) |
| 15070 | || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes; | 7010 | || type_requires_comptime(ira->codegen, wanted_type) == ReqCompTimeYes; |
| 15071 | bool is_comptime = true; | 7011 | bool is_comptime = true; |
| 15072 | 7012 | ||
| ... | @@ -16132,7 +8072,7 @@ static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst* source_instruction, IrIns | ... | @@ -16132,7 +8072,7 @@ static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst* source_instruction, IrIns |
| 16132 | return ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type, result_loc_inst); | 8072 | return ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type, result_loc_inst); |
| 16133 | } | 8073 | } |
| 16134 | 8074 | ||
| 16135 | static bool ir_resolve_const_align(CodeGen *codegen, IrExecutableGen *exec, AstNode *source_node, | 8075 | static bool ir_resolve_const_align(CodeGen *codegen, Stage1Air *exec, AstNode *source_node, |
| 16136 | ZigValue *const_val, uint32_t *out) | 8076 | ZigValue *const_val, uint32_t *out) |
| 16137 | { | 8077 | { |
| 16138 | Error err; | 8078 | Error err; |
| ... | @@ -19085,7 +11025,7 @@ static IrInstGen *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstSrcDeclV | ... | @@ -19085,7 +11025,7 @@ static IrInstGen *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstSrcDeclV |
| 19085 | return ira->codegen->invalid_inst_gen; | 11025 | return ira->codegen->invalid_inst_gen; |
| 19086 | } | 11026 | } |
| 19087 | 11027 | ||
| 19088 | ZigFn *fn_entry = ira->new_irb.exec->fn_entry; | 11028 | ZigFn *fn_entry = ira->fn; |
| 19089 | if (fn_entry) | 11029 | if (fn_entry) |
| 19090 | fn_entry->variable_list.append(var); | 11030 | fn_entry->variable_list.append(var); |
| 19091 | 11031 | ||
| ... | @@ -19481,9 +11421,9 @@ static IrInstGen *ir_analyze_instruction_extern(IrAnalyze *ira, IrInstSrcExtern | ... | @@ -19481,9 +11421,9 @@ static IrInstGen *ir_analyze_instruction_extern(IrAnalyze *ira, IrInstSrcExtern |
| 19481 | is_thread_local, expr_type); | 11421 | is_thread_local, expr_type); |
| 19482 | } | 11422 | } |
| 19483 | 11423 | ||
| 19484 | static bool exec_has_err_ret_trace(CodeGen *g, IrExecutableSrc *exec) { | 11424 | static bool ira_has_err_ret_trace(IrAnalyze *ira) { |
| 19485 | ZigFn *fn_entry = exec_fn_entry(exec); | 11425 | ZigFn *fn = ira->fn; |
| 19486 | return fn_entry != nullptr && fn_entry->calls_or_awaits_errorable_fn && g->have_err_ret_tracing; | 11426 | return fn != nullptr && fn->calls_or_awaits_errorable_fn && ira->codegen->have_err_ret_tracing; |
| 19487 | } | 11427 | } |
| 19488 | 11428 | ||
| 19489 | static IrInstGen *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, | 11429 | static IrInstGen *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, |
| ... | @@ -19492,7 +11432,7 @@ static IrInstGen *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, | ... | @@ -19492,7 +11432,7 @@ static IrInstGen *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, |
| 19492 | ZigType *ptr_to_stack_trace_type = get_pointer_to_type(ira->codegen, get_stack_trace_type(ira->codegen), false); | 11432 | ZigType *ptr_to_stack_trace_type = get_pointer_to_type(ira->codegen, get_stack_trace_type(ira->codegen), false); |
| 19493 | if (instruction->optional == IrInstErrorReturnTraceNull) { | 11433 | if (instruction->optional == IrInstErrorReturnTraceNull) { |
| 19494 | ZigType *optional_type = get_optional_type(ira->codegen, ptr_to_stack_trace_type); | 11434 | ZigType *optional_type = get_optional_type(ira->codegen, ptr_to_stack_trace_type); |
| 19495 | if (!exec_has_err_ret_trace(ira->codegen, ira->old_irb.exec)) { | 11435 | if (!ira_has_err_ret_trace(ira)) { |
| 19496 | IrInstGen *result = ir_const(ira, &instruction->base.base, optional_type); | 11436 | IrInstGen *result = ir_const(ira, &instruction->base.base, optional_type); |
| 19497 | ZigValue *out_val = result->value; | 11437 | ZigValue *out_val = result->value; |
| 19498 | assert(get_src_ptr_type(optional_type) != nullptr); | 11438 | assert(get_src_ptr_type(optional_type) != nullptr); |
| ... | @@ -19564,7 +11504,7 @@ static IrInstGen *ir_analyze_alloca(IrAnalyze *ira, IrInst *source_inst, ZigType | ... | @@ -19564,7 +11504,7 @@ static IrInstGen *ir_analyze_alloca(IrAnalyze *ira, IrInst *source_inst, ZigType |
| 19564 | PtrLenSingle, align, 0, 0, false); | 11504 | PtrLenSingle, align, 0, 0, false); |
| 19565 | 11505 | ||
| 19566 | if (!force_comptime) { | 11506 | if (!force_comptime) { |
| 19567 | ZigFn *fn_entry = ira->new_irb.exec->fn_entry; | 11507 | ZigFn *fn_entry = ira->fn; |
| 19568 | if (fn_entry != nullptr) { | 11508 | if (fn_entry != nullptr) { |
| 19569 | fn_entry->alloca_gen_list.append(result); | 11509 | fn_entry->alloca_gen_list.append(result); |
| 19570 | } | 11510 | } |
| ... | @@ -19663,7 +11603,7 @@ static IrInstGen *ir_resolve_no_result_loc(IrAnalyze *ira, IrInst *suspend_sourc | ... | @@ -19663,7 +11603,7 @@ static IrInstGen *ir_resolve_no_result_loc(IrAnalyze *ira, IrInst *suspend_sourc |
| 19663 | alloca_gen->base.value->type = get_pointer_to_type_extra(ira->codegen, value_type, false, false, | 11603 | alloca_gen->base.value->type = get_pointer_to_type_extra(ira->codegen, value_type, false, false, |
| 19664 | PtrLenSingle, 0, 0, 0, false); | 11604 | PtrLenSingle, 0, 0, 0, false); |
| 19665 | set_up_result_loc_for_inferred_comptime(ira, &alloca_gen->base); | 11605 | set_up_result_loc_for_inferred_comptime(ira, &alloca_gen->base); |
| 19666 | ZigFn *fn_entry = ira->new_irb.exec->fn_entry; | 11606 | ZigFn *fn_entry = ira->fn; |
| 19667 | if (fn_entry != nullptr && get_scope_typeof(suspend_source_instr->scope) == nullptr) { | 11607 | if (fn_entry != nullptr && get_scope_typeof(suspend_source_instr->scope) == nullptr) { |
| 19668 | fn_entry->alloca_gen_list.append(alloca_gen); | 11608 | fn_entry->alloca_gen_list.append(alloca_gen); |
| 19669 | } | 11609 | } |
| ... | @@ -20191,7 +12131,7 @@ static IrInstGen *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstSr | ... | @@ -20191,7 +12131,7 @@ static IrInstGen *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstSr |
| 20191 | if (result_loc != nullptr) | 12131 | if (result_loc != nullptr) |
| 20192 | return result_loc; | 12132 | return result_loc; |
| 20193 | 12133 | ||
| 20194 | ZigFn *fn = ira->new_irb.exec->fn_entry; | 12134 | ZigFn *fn = ira->fn; |
| 20195 | if (fn != nullptr && fn->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync && | 12135 | if (fn != nullptr && fn->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync && |
| 20196 | instruction->result_loc->id == ResultLocIdReturn) | 12136 | instruction->result_loc->id == ResultLocIdReturn) |
| 20197 | { | 12137 | { |
| ... | @@ -20319,7 +12259,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node | ... | @@ -20319,7 +12259,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node |
| 20319 | assert(param_decl_node->type == NodeTypeParamDecl); | 12259 | assert(param_decl_node->type == NodeTypeParamDecl); |
| 20320 | 12260 | ||
| 20321 | IrInstGen *casted_arg; | 12261 | IrInstGen *casted_arg; |
| 20322 | if (param_decl_node->data.param_decl.anytype_token == nullptr) { | 12262 | if (param_decl_node->data.param_decl.anytype_token == 0) { |
| 20323 | AstNode *param_type_node = param_decl_node->data.param_decl.type; | 12263 | AstNode *param_type_node = param_decl_node->data.param_decl.type; |
| 20324 | ZigType *param_type = ir_analyze_type_expr(ira, *exec_scope, param_type_node); | 12264 | ZigType *param_type = ir_analyze_type_expr(ira, *exec_scope, param_type_node); |
| 20325 | if (type_is_invalid(param_type)) | 12265 | if (type_is_invalid(param_type)) |
| ... | @@ -20362,7 +12302,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod | ... | @@ -20362,7 +12302,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod |
| 20362 | casted_arg = arg; | 12302 | casted_arg = arg; |
| 20363 | param_info_type = arg->value->type; | 12303 | param_info_type = arg->value->type; |
| 20364 | } else { | 12304 | } else { |
| 20365 | if (param_decl_node->data.param_decl.anytype_token == nullptr) { | 12305 | if (param_decl_node->data.param_decl.anytype_token == 0) { |
| 20366 | AstNode *param_type_node = param_decl_node->data.param_decl.type; | 12306 | AstNode *param_type_node = param_decl_node->data.param_decl.type; |
| 20367 | ZigType *param_type = ir_analyze_type_expr(ira, *child_scope, param_type_node); | 12307 | ZigType *param_type = ir_analyze_type_expr(ira, *child_scope, param_type_node); |
| 20368 | if (type_is_invalid(param_type)) | 12308 | if (type_is_invalid(param_type)) |
| ... | @@ -20813,7 +12753,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -20813,7 +12753,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 20813 | create_result_ptr(ira->codegen, return_type, &result, &result_ptr); | 12753 | create_result_ptr(ira->codegen, return_type, &result, &result_ptr); |
| 20814 | 12754 | ||
| 20815 | if ((err = ir_eval_const_value(ira->codegen, exec_scope, body_node, result_ptr, | 12755 | if ((err = ir_eval_const_value(ira->codegen, exec_scope, body_node, result_ptr, |
| 20816 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, | 12756 | ira->backward_branch_count, ira->backward_branch_quota, |
| 20817 | fn_entry, nullptr, source_instr->source_node, nullptr, ira->new_irb.exec, return_type_node, | 12757 | fn_entry, nullptr, source_instr->source_node, nullptr, ira->new_irb.exec, return_type_node, |
| 20818 | UndefOk))) | 12758 | UndefOk))) |
| 20819 | { | 12759 | { |
| ... | @@ -20909,7 +12849,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -20909,7 +12849,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 20909 | } | 12849 | } |
| 20910 | } | 12850 | } |
| 20911 | 12851 | ||
| 20912 | ZigFn *parent_fn_entry = ira->new_irb.exec->fn_entry; | 12852 | ZigFn *parent_fn_entry = ira->fn; |
| 20913 | assert(parent_fn_entry); | 12853 | assert(parent_fn_entry); |
| 20914 | for (size_t call_i = 0; call_i < args_len; call_i += 1) { | 12854 | for (size_t call_i = 0; call_i < args_len; call_i += 1) { |
| 20915 | IrInstGen *arg = args_ptr[call_i]; | 12855 | IrInstGen *arg = args_ptr[call_i]; |
| ... | @@ -20930,7 +12870,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -20930,7 +12870,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 20930 | create_result_ptr(ira->codegen, get_align_amt_type(ira->codegen), &align_result, &result_ptr); | 12870 | create_result_ptr(ira->codegen, get_align_amt_type(ira->codegen), &align_result, &result_ptr); |
| 20931 | if ((err = ir_eval_const_value(ira->codegen, impl_fn->child_scope, | 12871 | if ((err = ir_eval_const_value(ira->codegen, impl_fn->child_scope, |
| 20932 | fn_proto_node->data.fn_proto.align_expr, result_ptr, | 12872 | fn_proto_node->data.fn_proto.align_expr, result_ptr, |
| 20933 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, | 12873 | ira->backward_branch_count, ira->backward_branch_quota, |
| 20934 | nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, | 12874 | nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, |
| 20935 | nullptr, UndefBad))) | 12875 | nullptr, UndefBad))) |
| 20936 | { | 12876 | { |
| ... | @@ -20994,12 +12934,9 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -20994,12 +12934,9 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 20994 | if (type_is_invalid(impl_fn->type_entry)) | 12934 | if (type_is_invalid(impl_fn->type_entry)) |
| 20995 | return ira->codegen->invalid_inst_gen; | 12935 | return ira->codegen->invalid_inst_gen; |
| 20996 | 12936 | ||
| 20997 | impl_fn->ir_executable->source_node = source_instr->source_node; | ||
| 20998 | impl_fn->ir_executable->parent_exec = ira->new_irb.exec; | ||
| 20999 | impl_fn->analyzed_executable.source_node = source_instr->source_node; | 12937 | impl_fn->analyzed_executable.source_node = source_instr->source_node; |
| 21000 | impl_fn->analyzed_executable.parent_exec = ira->new_irb.exec; | 12938 | impl_fn->analyzed_executable.parent_exec = ira->new_irb.exec; |
| 21001 | impl_fn->analyzed_executable.backward_branch_quota = ira->new_irb.exec->backward_branch_quota; | 12939 | impl_fn->branch_quota = *ira->backward_branch_quota; |
| 21002 | impl_fn->analyzed_executable.is_generic_instantiation = true; | ||
| 21003 | 12940 | ||
| 21004 | ira->codegen->fn_defs.append(impl_fn); | 12941 | ira->codegen->fn_defs.append(impl_fn); |
| 21005 | } | 12942 | } |
| ... | @@ -21079,7 +13016,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -21079,7 +13016,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 21079 | return ir_finish_anal(ira, &new_call_instruction->base); | 13016 | return ir_finish_anal(ira, &new_call_instruction->base); |
| 21080 | } | 13017 | } |
| 21081 | 13018 | ||
| 21082 | ZigFn *parent_fn_entry = ira->new_irb.exec->fn_entry; | 13019 | ZigFn *parent_fn_entry = ira->fn; |
| 21083 | assert(fn_type_id->return_type != nullptr); | 13020 | assert(fn_type_id->return_type != nullptr); |
| 21084 | assert(parent_fn_entry != nullptr); | 13021 | assert(parent_fn_entry != nullptr); |
| 21085 | if (fn_type_can_fail(fn_type_id)) { | 13022 | if (fn_type_can_fail(fn_type_id)) { |
| ... | @@ -21275,7 +13212,7 @@ static IrInstGen *ir_analyze_call_extra(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -21275,7 +13212,7 @@ static IrInstGen *ir_analyze_call_extra(IrAnalyze *ira, IrInst* source_instr, |
| 21275 | return ira->codegen->invalid_inst_gen; | 13212 | return ira->codegen->invalid_inst_gen; |
| 21276 | CallModifier modifier = (CallModifier)bigint_as_u32(&modifier_val->data.x_enum_tag); | 13213 | CallModifier modifier = (CallModifier)bigint_as_u32(&modifier_val->data.x_enum_tag); |
| 21277 | 13214 | ||
| 21278 | if (ir_should_inline(ira->old_irb.exec, source_instr->scope)) { | 13215 | if (ir_should_inline(ira->zir, source_instr->scope)) { |
| 21279 | switch (modifier) { | 13216 | switch (modifier) { |
| 21280 | case CallModifierBuiltin: | 13217 | case CallModifierBuiltin: |
| 21281 | zig_unreachable(); | 13218 | zig_unreachable(); |
| ... | @@ -21364,7 +13301,7 @@ static IrInstGen *ir_analyze_async_call_extra(IrAnalyze *ira, IrInst* source_ins | ... | @@ -21364,7 +13301,7 @@ static IrInstGen *ir_analyze_async_call_extra(IrAnalyze *ira, IrInst* source_ins |
| 21364 | if (type_is_invalid(fn_ref->value->type)) | 13301 | if (type_is_invalid(fn_ref->value->type)) |
| 21365 | return ira->codegen->invalid_inst_gen; | 13302 | return ira->codegen->invalid_inst_gen; |
| 21366 | 13303 | ||
| 21367 | if (ir_should_inline(ira->old_irb.exec, source_instr->scope)) { | 13304 | if (ir_should_inline(ira->zir, source_instr->scope)) { |
| 21368 | ir_add_error(ira, source_instr, buf_sprintf("TODO: comptime @asyncCall")); | 13305 | ir_add_error(ira, source_instr, buf_sprintf("TODO: comptime @asyncCall")); |
| 21369 | return ira->codegen->invalid_inst_gen; | 13306 | return ira->codegen->invalid_inst_gen; |
| 21370 | } | 13307 | } |
| ... | @@ -21477,7 +13414,7 @@ static IrInstGen *ir_analyze_instruction_call(IrAnalyze *ira, IrInstSrcCall *cal | ... | @@ -21477,7 +13414,7 @@ static IrInstGen *ir_analyze_instruction_call(IrAnalyze *ira, IrInstSrcCall *cal |
| 21477 | return ira->codegen->invalid_inst_gen; | 13414 | return ira->codegen->invalid_inst_gen; |
| 21478 | 13415 | ||
| 21479 | bool is_comptime = (call_instruction->modifier == CallModifierCompileTime) || | 13416 | bool is_comptime = (call_instruction->modifier == CallModifierCompileTime) || |
| 21480 | ir_should_inline(ira->old_irb.exec, call_instruction->base.base.scope); | 13417 | ir_should_inline(ira->zir, call_instruction->base.base.scope); |
| 21481 | CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier; | 13418 | CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier; |
| 21482 | 13419 | ||
| 21483 | if (is_comptime || instr_is_comptime(fn_ref)) { | 13420 | if (is_comptime || instr_is_comptime(fn_ref)) { |
| ... | @@ -21839,20 +13776,20 @@ static IrInstGen *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstSrcUnOp *in | ... | @@ -21839,20 +13776,20 @@ static IrInstGen *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstSrcUnOp *in |
| 21839 | } | 13776 | } |
| 21840 | 13777 | ||
| 21841 | static void ir_push_resume(IrAnalyze *ira, IrSuspendPosition pos) { | 13778 | static void ir_push_resume(IrAnalyze *ira, IrSuspendPosition pos) { |
| 21842 | IrBasicBlockSrc *old_bb = ira->old_irb.exec->basic_block_list.at(pos.basic_block_index); | 13779 | Stage1ZirBasicBlock *old_bb = ira->zir->basic_block_list.at(pos.basic_block_index); |
| 21843 | if (old_bb->in_resume_stack) return; | 13780 | if (old_bb->in_resume_stack) return; |
| 21844 | ira->resume_stack.append(pos); | 13781 | ira->resume_stack.append(pos); |
| 21845 | old_bb->in_resume_stack = true; | 13782 | old_bb->in_resume_stack = true; |
| 21846 | } | 13783 | } |
| 21847 | 13784 | ||
| 21848 | static void ir_push_resume_block(IrAnalyze *ira, IrBasicBlockSrc *old_bb) { | 13785 | static void ir_push_resume_block(IrAnalyze *ira, Stage1ZirBasicBlock *old_bb) { |
| 21849 | if (ira->resume_stack.length != 0) { | 13786 | if (ira->resume_stack.length != 0) { |
| 21850 | ir_push_resume(ira, {old_bb->index, 0}); | 13787 | ir_push_resume(ira, {old_bb->index, 0}); |
| 21851 | } | 13788 | } |
| 21852 | } | 13789 | } |
| 21853 | 13790 | ||
| 21854 | static IrInstGen *ir_analyze_instruction_br(IrAnalyze *ira, IrInstSrcBr *br_instruction) { | 13791 | static IrInstGen *ir_analyze_instruction_br(IrAnalyze *ira, IrInstSrcBr *br_instruction) { |
| 21855 | IrBasicBlockSrc *old_dest_block = br_instruction->dest_block; | 13792 | Stage1ZirBasicBlock *old_dest_block = br_instruction->dest_block; |
| 21856 | 13793 | ||
| 21857 | bool is_comptime; | 13794 | bool is_comptime; |
| 21858 | if (!ir_resolve_comptime(ira, br_instruction->is_comptime->child, &is_comptime)) | 13795 | if (!ir_resolve_comptime(ira, br_instruction->is_comptime->child, &is_comptime)) |
| ... | @@ -21890,7 +13827,7 @@ static IrInstGen *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstSrcCondBr | ... | @@ -21890,7 +13827,7 @@ static IrInstGen *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstSrcCondBr |
| 21890 | if (!ir_resolve_bool(ira, casted_condition, &cond_is_true)) | 13827 | if (!ir_resolve_bool(ira, casted_condition, &cond_is_true)) |
| 21891 | return ir_unreach_error(ira); | 13828 | return ir_unreach_error(ira); |
| 21892 | 13829 | ||
| 21893 | IrBasicBlockSrc *old_dest_block = cond_is_true ? | 13830 | Stage1ZirBasicBlock *old_dest_block = cond_is_true ? |
| 21894 | cond_br_instruction->then_block : cond_br_instruction->else_block; | 13831 | cond_br_instruction->then_block : cond_br_instruction->else_block; |
| 21895 | 13832 | ||
| 21896 | if (is_comptime || (old_dest_block->ref_count == 1 && old_dest_block->suspend_instruction_ref == nullptr)) | 13833 | if (is_comptime || (old_dest_block->ref_count == 1 && old_dest_block->suspend_instruction_ref == nullptr)) |
| ... | @@ -21926,7 +13863,7 @@ static IrInstGen *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstSrcCondBr | ... | @@ -21926,7 +13863,7 @@ static IrInstGen *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstSrcCondBr |
| 21926 | static IrInstGen *ir_analyze_instruction_unreachable(IrAnalyze *ira, | 13863 | static IrInstGen *ir_analyze_instruction_unreachable(IrAnalyze *ira, |
| 21927 | IrInstSrcUnreachable *unreachable_instruction) | 13864 | IrInstSrcUnreachable *unreachable_instruction) |
| 21928 | { | 13865 | { |
| 21929 | if (ir_should_inline(ira->old_irb.exec, unreachable_instruction->base.base.scope)) { | 13866 | if (ir_should_inline(ira->zir, unreachable_instruction->base.base.scope)) { |
| 21930 | ir_add_error(ira, &unreachable_instruction->base.base, buf_sprintf("reached unreachable code")); | 13867 | ir_add_error(ira, &unreachable_instruction->base.base, buf_sprintf("reached unreachable code")); |
| 21931 | return ir_unreach_error(ira); | 13868 | return ir_unreach_error(ira); |
| 21932 | } | 13869 | } |
| ... | @@ -21940,7 +13877,7 @@ static IrInstGen *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstSrcPhi *phi_i | ... | @@ -21940,7 +13877,7 @@ static IrInstGen *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstSrcPhi *phi_i |
| 21940 | 13877 | ||
| 21941 | if (ira->const_predecessor_bb) { | 13878 | if (ira->const_predecessor_bb) { |
| 21942 | for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { | 13879 | for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { |
| 21943 | IrBasicBlockSrc *predecessor = phi_instruction->incoming_blocks[i]; | 13880 | Stage1ZirBasicBlock *predecessor = phi_instruction->incoming_blocks[i]; |
| 21944 | if (predecessor != ira->const_predecessor_bb) | 13881 | if (predecessor != ira->const_predecessor_bb) |
| 21945 | continue; | 13882 | continue; |
| 21946 | IrInstGen *value = phi_instruction->incoming_values[i]->child; | 13883 | IrInstGen *value = phi_instruction->incoming_values[i]->child; |
| ... | @@ -22040,7 +13977,7 @@ static IrInstGen *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstSrcPhi *phi_i | ... | @@ -22040,7 +13977,7 @@ static IrInstGen *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstSrcPhi *phi_i |
| 22040 | ZigList<IrInstGen*> new_incoming_values = {0}; | 13977 | ZigList<IrInstGen*> new_incoming_values = {0}; |
| 22041 | 13978 | ||
| 22042 | for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { | 13979 | for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { |
| 22043 | IrBasicBlockSrc *predecessor = phi_instruction->incoming_blocks[i]; | 13980 | Stage1ZirBasicBlock *predecessor = phi_instruction->incoming_blocks[i]; |
| 22044 | if (predecessor->ref_count == 0) | 13981 | if (predecessor->ref_count == 0) |
| 22045 | continue; | 13982 | continue; |
| 22046 | 13983 | ||
| ... | @@ -23593,6 +15530,25 @@ static IrInstGen *ir_analyze_instruction_slice_type(IrAnalyze *ira, IrInstSrcSli | ... | @@ -23593,6 +15530,25 @@ static IrInstGen *ir_analyze_instruction_slice_type(IrAnalyze *ira, IrInstSrcSli |
| 23593 | return result; | 15530 | return result; |
| 23594 | } | 15531 | } |
| 23595 | 15532 | ||
| 15533 | static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_template) { | ||
| 15534 | const char *ptr = buf_ptr(src_template) + tok->start + 2; | ||
| 15535 | size_t len = tok->end - tok->start - 2; | ||
| 15536 | size_t result = 0; | ||
| 15537 | for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1, result += 1) { | ||
| 15538 | AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); | ||
| 15539 | if (buf_eql_mem(asm_output->asm_symbolic_name, ptr, len)) { | ||
| 15540 | return result; | ||
| 15541 | } | ||
| 15542 | } | ||
| 15543 | for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1, result += 1) { | ||
| 15544 | AsmInput *asm_input = node->data.asm_expr.input_list.at(i); | ||
| 15545 | if (buf_eql_mem(asm_input->asm_symbolic_name, ptr, len)) { | ||
| 15546 | return result; | ||
| 15547 | } | ||
| 15548 | } | ||
| 15549 | return SIZE_MAX; | ||
| 15550 | } | ||
| 15551 | |||
| 23596 | static IrInstGen *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstSrcAsm *asm_instruction) { | 15552 | static IrInstGen *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstSrcAsm *asm_instruction) { |
| 23597 | Error err; | 15553 | Error err; |
| 23598 | 15554 | ||
| ... | @@ -24040,7 +15996,7 @@ static IrInstGen *ir_analyze_instruction_switch_br(IrAnalyze *ira, | ... | @@ -24040,7 +15996,7 @@ static IrInstGen *ir_analyze_instruction_switch_br(IrAnalyze *ira, |
| 24040 | if (!target_val) | 15996 | if (!target_val) |
| 24041 | return ir_unreach_error(ira); | 15997 | return ir_unreach_error(ira); |
| 24042 | 15998 | ||
| 24043 | IrBasicBlockSrc *old_dest_block = switch_br_instruction->else_block; | 15999 | Stage1ZirBasicBlock *old_dest_block = switch_br_instruction->else_block; |
| 24044 | for (size_t i = 0; i < case_count; i += 1) { | 16000 | for (size_t i = 0; i < case_count; i += 1) { |
| 24045 | IrInstSrcSwitchBrCase *old_case = &switch_br_instruction->cases[i]; | 16001 | IrInstSrcSwitchBrCase *old_case = &switch_br_instruction->cases[i]; |
| 24046 | IrInstGen *case_value = old_case->value->child; | 16002 | IrInstGen *case_value = old_case->value->child; |
| ... | @@ -24522,7 +16478,7 @@ static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instructi | ... | @@ -24522,7 +16478,7 @@ static IrInstGen *ir_analyze_union_init(IrAnalyze *ira, IrInst* source_instructi |
| 24522 | } | 16478 | } |
| 24523 | } | 16479 | } |
| 24524 | 16480 | ||
| 24525 | bool is_comptime = ir_should_inline(ira->old_irb.exec, source_instruction->scope) | 16481 | bool is_comptime = ir_should_inline(ira->zir, source_instruction->scope) |
| 24526 | || type_requires_comptime(ira->codegen, union_type) == ReqCompTimeYes; | 16482 | || type_requires_comptime(ira->codegen, union_type) == ReqCompTimeYes; |
| 24527 | 16483 | ||
| 24528 | IrInstGen *result = ir_get_deref(ira, source_instruction, result_loc, nullptr); | 16484 | IrInstGen *result = ir_get_deref(ira, source_instruction, result_loc, nullptr); |
| ... | @@ -24575,7 +16531,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc | ... | @@ -24575,7 +16531,7 @@ static IrInstGen *ir_analyze_container_init_fields(IrAnalyze *ira, IrInst *sourc |
| 24575 | AstNode **field_assign_nodes = heap::c_allocator.allocate<AstNode *>(actual_field_count); | 16531 | AstNode **field_assign_nodes = heap::c_allocator.allocate<AstNode *>(actual_field_count); |
| 24576 | ZigList<IrInstGen *> const_ptrs = {}; | 16532 | ZigList<IrInstGen *> const_ptrs = {}; |
| 24577 | 16533 | ||
| 24578 | bool is_comptime = ir_should_inline(ira->old_irb.exec, source_instr->scope) | 16534 | bool is_comptime = ir_should_inline(ira->zir, source_instr->scope) |
| 24579 | || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes; | 16535 | || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes; |
| 24580 | 16536 | ||
| 24581 | 16537 | ||
| ... | @@ -24762,7 +16718,7 @@ static IrInstGen *ir_analyze_instruction_container_init_list(IrAnalyze *ira, | ... | @@ -24762,7 +16718,7 @@ static IrInstGen *ir_analyze_instruction_container_init_list(IrAnalyze *ira, |
| 24762 | case ReqCompTimeInvalid: | 16718 | case ReqCompTimeInvalid: |
| 24763 | return ira->codegen->invalid_inst_gen; | 16719 | return ira->codegen->invalid_inst_gen; |
| 24764 | case ReqCompTimeNo: | 16720 | case ReqCompTimeNo: |
| 24765 | is_comptime = ir_should_inline(ira->old_irb.exec, instruction->base.base.scope); | 16721 | is_comptime = ir_should_inline(ira->zir, instruction->base.base.scope); |
| 24766 | break; | 16722 | break; |
| 24767 | case ReqCompTimeYes: | 16723 | case ReqCompTimeYes: |
| 24768 | is_comptime = true; | 16724 | is_comptime = true; |
| ... | @@ -26534,7 +18490,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI | ... | @@ -26534,7 +18490,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI |
| 26534 | 18490 | ||
| 26535 | Buf *bare_name = buf_alloc(); | 18491 | Buf *bare_name = buf_alloc(); |
| 26536 | Buf *full_name = get_anon_type_name(ira->codegen, | 18492 | Buf *full_name = get_anon_type_name(ira->codegen, |
| 26537 | ira->old_irb.exec, "opaque", source_instr->scope, source_instr->source_node, bare_name); | 18493 | ira->zir, "opaque", source_instr->scope, source_instr->source_node, bare_name); |
| 26538 | return get_opaque_type(ira->codegen, | 18494 | return get_opaque_type(ira->codegen, |
| 26539 | source_instr->scope, source_instr->source_node, buf_ptr(full_name), bare_name); | 18495 | source_instr->scope, source_instr->source_node, buf_ptr(full_name), bare_name); |
| 26540 | } | 18496 | } |
| ... | @@ -26581,7 +18537,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI | ... | @@ -26581,7 +18537,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI |
| 26581 | assert(is_slice(slice->type)); | 18537 | assert(is_slice(slice->type)); |
| 26582 | ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); | 18538 | ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); |
| 26583 | Buf bare_name = BUF_INIT; | 18539 | Buf bare_name = BUF_INIT; |
| 26584 | buf_init_from_buf(&err_set_type->name, get_anon_type_name(ira->codegen, ira->old_irb.exec, "error", source_instr->scope, source_instr->source_node, &bare_name)); | 18540 | buf_init_from_buf(&err_set_type->name, get_anon_type_name(ira->codegen, ira->zir, "error", source_instr->scope, source_instr->source_node, &bare_name)); |
| 26585 | err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits; | 18541 | err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits; |
| 26586 | err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align; | 18542 | err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align; |
| 26587 | err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size; | 18543 | err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size; |
| ... | @@ -26660,7 +18616,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI | ... | @@ -26660,7 +18616,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI |
| 26660 | 18616 | ||
| 26661 | ZigType *entry = new_type_table_entry(ZigTypeIdStruct); | 18617 | ZigType *entry = new_type_table_entry(ZigTypeIdStruct); |
| 26662 | buf_init_from_buf(&entry->name, | 18618 | buf_init_from_buf(&entry->name, |
| 26663 | get_anon_type_name(ira->codegen, ira->old_irb.exec, "struct", source_instr->scope, source_instr->source_node, &entry->name)); | 18619 | get_anon_type_name(ira->codegen, ira->zir, "struct", source_instr->scope, source_instr->source_node, &entry->name)); |
| 26664 | entry->data.structure.decl_node = source_instr->source_node; | 18620 | entry->data.structure.decl_node = source_instr->source_node; |
| 26665 | entry->data.structure.fields = alloc_type_struct_fields(fields_len); | 18621 | entry->data.structure.fields = alloc_type_struct_fields(fields_len); |
| 26666 | entry->data.structure.fields_by_name.init(fields_len); | 18622 | entry->data.structure.fields_by_name.init(fields_len); |
| ... | @@ -26770,7 +18726,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI | ... | @@ -26770,7 +18726,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI |
| 26770 | 18726 | ||
| 26771 | ZigType *entry = new_type_table_entry(ZigTypeIdEnum); | 18727 | ZigType *entry = new_type_table_entry(ZigTypeIdEnum); |
| 26772 | buf_init_from_buf(&entry->name, | 18728 | buf_init_from_buf(&entry->name, |
| 26773 | get_anon_type_name(ira->codegen, ira->old_irb.exec, "enum", source_instr->scope, source_instr->source_node, &entry->name)); | 18729 | get_anon_type_name(ira->codegen, ira->zir, "enum", source_instr->scope, source_instr->source_node, &entry->name)); |
| 26774 | entry->data.enumeration.decl_node = source_instr->source_node; | 18730 | entry->data.enumeration.decl_node = source_instr->source_node; |
| 26775 | entry->data.enumeration.tag_int_type = tag_type; | 18731 | entry->data.enumeration.tag_int_type = tag_type; |
| 26776 | entry->data.enumeration.decls_scope = create_decls_scope( | 18732 | entry->data.enumeration.decls_scope = create_decls_scope( |
| ... | @@ -26852,7 +18808,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI | ... | @@ -26852,7 +18808,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI |
| 26852 | 18808 | ||
| 26853 | ZigType *entry = new_type_table_entry(ZigTypeIdUnion); | 18809 | ZigType *entry = new_type_table_entry(ZigTypeIdUnion); |
| 26854 | buf_init_from_buf(&entry->name, | 18810 | buf_init_from_buf(&entry->name, |
| 26855 | get_anon_type_name(ira->codegen, ira->old_irb.exec, "union", source_instr->scope, source_instr->source_node, &entry->name)); | 18811 | get_anon_type_name(ira->codegen, ira->zir, "union", source_instr->scope, source_instr->source_node, &entry->name)); |
| 26856 | entry->data.unionation.decl_node = source_instr->source_node; | 18812 | entry->data.unionation.decl_node = source_instr->source_node; |
| 26857 | entry->data.unionation.fields = heap::c_allocator.allocate<TypeUnionField>(fields_len); | 18813 | entry->data.unionation.fields = heap::c_allocator.allocate<TypeUnionField>(fields_len); |
| 26858 | entry->data.unionation.fields_by_name.init(fields_len); | 18814 | entry->data.unionation.fields_by_name.init(fields_len); |
| ... | @@ -27022,8 +18978,8 @@ static IrInstGen *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira, | ... | @@ -27022,8 +18978,8 @@ static IrInstGen *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira, |
| 27022 | if (!ir_resolve_unsigned(ira, instruction->new_quota->child, ira->codegen->builtin_types.entry_u32, &new_quota)) | 18978 | if (!ir_resolve_unsigned(ira, instruction->new_quota->child, ira->codegen->builtin_types.entry_u32, &new_quota)) |
| 27023 | return ira->codegen->invalid_inst_gen; | 18979 | return ira->codegen->invalid_inst_gen; |
| 27024 | 18980 | ||
| 27025 | if (new_quota > *ira->new_irb.exec->backward_branch_quota) { | 18981 | if (new_quota > *ira->backward_branch_quota) { |
| 27026 | *ira->new_irb.exec->backward_branch_quota = new_quota; | 18982 | *ira->backward_branch_quota = new_quota; |
| 27027 | } | 18983 | } |
| 27028 | 18984 | ||
| 27029 | return ir_const_void(ira, &instruction->base.base); | 18985 | return ir_const_void(ira, &instruction->base.base); |
| ... | @@ -27057,7 +19013,7 @@ static IrInstGen *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstSrcCImpo | ... | @@ -27057,7 +19013,7 @@ static IrInstGen *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstSrcCImpo |
| 27057 | ZigValue *result_ptr; | 19013 | ZigValue *result_ptr; |
| 27058 | create_result_ptr(ira->codegen, void_type, &cimport_result, &result_ptr); | 19014 | create_result_ptr(ira->codegen, void_type, &cimport_result, &result_ptr); |
| 27059 | if ((err = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, result_ptr, | 19015 | if ((err = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, result_ptr, |
| 27060 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, | 19016 | ira->backward_branch_count, ira->backward_branch_quota, nullptr, |
| 27061 | &cimport_scope->buf, block_node, nullptr, nullptr, nullptr, UndefBad))) | 19017 | &cimport_scope->buf, block_node, nullptr, nullptr, nullptr, UndefBad))) |
| 27062 | { | 19018 | { |
| 27063 | return ira->codegen->invalid_inst_gen; | 19019 | return ira->codegen->invalid_inst_gen; |
| ... | @@ -27066,8 +19022,10 @@ static IrInstGen *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstSrcCImpo | ... | @@ -27066,8 +19022,10 @@ static IrInstGen *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstSrcCImpo |
| 27066 | return ira->codegen->invalid_inst_gen; | 19022 | return ira->codegen->invalid_inst_gen; |
| 27067 | 19023 | ||
| 27068 | ZigPackage *cur_scope_pkg = scope_package(instruction->base.base.scope); | 19024 | ZigPackage *cur_scope_pkg = scope_package(instruction->base.base.scope); |
| 27069 | Buf *namespace_name = buf_sprintf("%s.cimport:%" ZIG_PRI_usize ":%" ZIG_PRI_usize, | 19025 | RootStruct *root_struct = node->owner->data.structure.root_struct; |
| 27070 | buf_ptr(&cur_scope_pkg->pkg_path), node->line + 1, node->column + 1); | 19026 | TokenLoc tok_loc = root_struct->token_locs[node->main_token]; |
| 19027 | Buf *namespace_name = buf_sprintf("%s.cimport:%" PRIu32 ":%" PRIu32, | ||
| 19028 | buf_ptr(&cur_scope_pkg->pkg_path), tok_loc.line + 1, tok_loc.column + 1); | ||
| 27071 | 19029 | ||
| 27072 | ZigPackage *cimport_pkg = new_anonymous_package(); | 19030 | ZigPackage *cimport_pkg = new_anonymous_package(); |
| 27073 | cimport_pkg->package_table.put(buf_create_from_str("builtin"), ira->codegen->compile_var_package); | 19031 | cimport_pkg->package_table.put(buf_create_from_str("builtin"), ira->codegen->compile_var_package); |
| ... | @@ -27095,12 +19053,14 @@ static IrInstGen *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstSrcCImpo | ... | @@ -27095,12 +19053,14 @@ static IrInstGen *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstSrcCImpo |
| 27095 | } | 19053 | } |
| 27096 | for (size_t i = 0; i < errors_len; i += 1) { | 19054 | for (size_t i = 0; i < errors_len; i += 1) { |
| 27097 | Stage2ErrorMsg *clang_err = &errors_ptr[i]; | 19055 | Stage2ErrorMsg *clang_err = &errors_ptr[i]; |
| 27098 | // Clang can emit "too many errors, stopping now", in which case `source` and `filename_ptr` are null | 19056 | // Clang can emit "too many errors, stopping now", in which case |
| 19057 | // `source` and `filename_ptr` are null | ||
| 27099 | if (clang_err->source && clang_err->filename_ptr) { | 19058 | if (clang_err->source && clang_err->filename_ptr) { |
| 27100 | ErrorMsg *err_msg = err_msg_create_with_offset( | 19059 | ErrorMsg *err_msg = err_msg_create_with_offset( |
| 27101 | clang_err->filename_ptr ? | 19060 | clang_err->filename_ptr ? |
| 27102 | buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(), | 19061 | buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : |
| 27103 | clang_err->line, clang_err->column, clang_err->offset, clang_err->source, | 19062 | buf_alloc(), |
| 19063 | clang_err->offset, clang_err->source, | ||
| 27104 | buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len)); | 19064 | buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len)); |
| 27105 | err_msg_add_note(parent_err_msg, err_msg); | 19065 | err_msg_add_note(parent_err_msg, err_msg); |
| 27106 | } | 19066 | } |
| ... | @@ -27225,7 +19185,7 @@ static IrInstGen *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstSrcEmb | ... | @@ -27225,7 +19185,7 @@ static IrInstGen *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstSrcEmb |
| 27225 | } | 19185 | } |
| 27226 | 19186 | ||
| 27227 | IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); | 19187 | IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr); |
| 27228 | init_const_str_lit(ira->codegen, result->value, file_contents); | 19188 | init_const_str_lit(ira->codegen, result->value, file_contents, true); |
| 27229 | return result; | 19189 | return result; |
| 27230 | } | 19190 | } |
| 27231 | 19191 | ||
| ... | @@ -29108,7 +21068,7 @@ static IrInstGen *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrInstSrc | ... | @@ -29108,7 +21068,7 @@ static IrInstGen *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrInstSrc |
| 29108 | } | 21068 | } |
| 29109 | 21069 | ||
| 29110 | static IrInstGen *ir_analyze_instruction_frame_handle(IrAnalyze *ira, IrInstSrcFrameHandle *instruction) { | 21070 | static IrInstGen *ir_analyze_instruction_frame_handle(IrAnalyze *ira, IrInstSrcFrameHandle *instruction) { |
| 29111 | ZigFn *fn = ira->new_irb.exec->fn_entry; | 21071 | ZigFn *fn = ira->fn; |
| 29112 | ir_assert(fn != nullptr, &instruction->base.base); | 21072 | ir_assert(fn != nullptr, &instruction->base.base); |
| 29113 | 21073 | ||
| 29114 | if (fn->inferred_async_node == nullptr) { | 21074 | if (fn->inferred_async_node == nullptr) { |
| ... | @@ -30043,7 +22003,7 @@ static IrInstGen *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstSrcPanic *i | ... | @@ -30043,7 +22003,7 @@ static IrInstGen *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstSrcPanic *i |
| 30043 | if (type_is_invalid(msg->value->type)) | 22003 | if (type_is_invalid(msg->value->type)) |
| 30044 | return ir_unreach_error(ira); | 22004 | return ir_unreach_error(ira); |
| 30045 | 22005 | ||
| 30046 | if (ir_should_inline(ira->old_irb.exec, instruction->base.base.scope)) { | 22006 | if (ir_should_inline(ira->zir, instruction->base.base.scope)) { |
| 30047 | ir_add_error(ira, &instruction->base.base, buf_sprintf("encountered @panic at compile-time")); | 22007 | ir_add_error(ira, &instruction->base.base, buf_sprintf("encountered @panic at compile-time")); |
| 30048 | return ir_unreach_error(ira); | 22008 | return ir_unreach_error(ira); |
| 30049 | } | 22009 | } |
| ... | @@ -30971,7 +22931,7 @@ static IrInstGen *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, IrInstS | ... | @@ -30971,7 +22931,7 @@ static IrInstGen *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, IrInstS |
| 30971 | return ira->codegen->invalid_inst_gen; | 22931 | return ira->codegen->invalid_inst_gen; |
| 30972 | } | 22932 | } |
| 30973 | 22933 | ||
| 30974 | ZigFn *fn_entry = ira->new_irb.exec->fn_entry; | 22934 | ZigFn *fn_entry = ira->fn; |
| 30975 | if (fn_entry == nullptr) { | 22935 | if (fn_entry == nullptr) { |
| 30976 | ir_add_error(ira, &instruction->base.base, buf_sprintf("@setAlignStack outside function")); | 22936 | ir_add_error(ira, &instruction->base.base, buf_sprintf("@setAlignStack outside function")); |
| 30977 | return ira->codegen->invalid_inst_gen; | 22937 | return ira->codegen->invalid_inst_gen; |
| ... | @@ -31851,6 +23811,22 @@ static IrInstGen *ir_analyze_instruction_has_decl(IrAnalyze *ira, IrInstSrcHasDe | ... | @@ -31851,6 +23811,22 @@ static IrInstGen *ir_analyze_instruction_has_decl(IrAnalyze *ira, IrInstSrcHasDe |
| 31851 | return ir_const_bool(ira, &instruction->base.base, true); | 23811 | return ir_const_bool(ira, &instruction->base.base, true); |
| 31852 | } | 23812 | } |
| 31853 | 23813 | ||
| 23814 | static void populate_invalid_variable_in_scope(CodeGen *g, Scope *scope, AstNode *node, Buf *var_name) { | ||
| 23815 | ScopeDecls *scope_decls = nullptr; | ||
| 23816 | while (scope != nullptr) { | ||
| 23817 | if (scope->id == ScopeIdDecls) { | ||
| 23818 | scope_decls = reinterpret_cast<ScopeDecls *>(scope); | ||
| 23819 | } | ||
| 23820 | scope = scope->parent; | ||
| 23821 | } | ||
| 23822 | TldVar *tld_var = heap::c_allocator.create<TldVar>(); | ||
| 23823 | init_tld(&tld_var->base, TldIdVar, var_name, VisibModPub, node, &scope_decls->base); | ||
| 23824 | tld_var->base.resolution = TldResolutionInvalid; | ||
| 23825 | tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false, | ||
| 23826 | g->invalid_inst_gen->value, &tld_var->base, g->builtin_types.entry_invalid); | ||
| 23827 | scope_decls->decl_table.put(var_name, &tld_var->base); | ||
| 23828 | } | ||
| 23829 | |||
| 31854 | static IrInstGen *ir_analyze_instruction_undeclared_ident(IrAnalyze *ira, IrInstSrcUndeclaredIdent *instruction) { | 23830 | static IrInstGen *ir_analyze_instruction_undeclared_ident(IrAnalyze *ira, IrInstSrcUndeclaredIdent *instruction) { |
| 31855 | // put a variable of same name with invalid type in global scope | 23831 | // put a variable of same name with invalid type in global scope |
| 31856 | // so that future references to this same name will find a variable with an invalid type | 23832 | // so that future references to this same name will find a variable with an invalid type |
| ... | @@ -31975,7 +23951,7 @@ static IrInstGen *ir_analyze_instruction_suspend_finish(IrAnalyze *ira, IrInstSr | ... | @@ -31975,7 +23951,7 @@ static IrInstGen *ir_analyze_instruction_suspend_finish(IrAnalyze *ira, IrInstSr |
| 31975 | ir_assert(begin_base->id == IrInstGenIdSuspendBegin, &instruction->base.base); | 23951 | ir_assert(begin_base->id == IrInstGenIdSuspendBegin, &instruction->base.base); |
| 31976 | IrInstGenSuspendBegin *begin = reinterpret_cast<IrInstGenSuspendBegin *>(begin_base); | 23952 | IrInstGenSuspendBegin *begin = reinterpret_cast<IrInstGenSuspendBegin *>(begin_base); |
| 31977 | 23953 | ||
| 31978 | ZigFn *fn_entry = ira->new_irb.exec->fn_entry; | 23954 | ZigFn *fn_entry = ira->fn; |
| 31979 | ir_assert(fn_entry != nullptr, &instruction->base.base); | 23955 | ir_assert(fn_entry != nullptr, &instruction->base.base); |
| 31980 | 23956 | ||
| 31981 | if (fn_entry->inferred_async_node == nullptr) { | 23957 | if (fn_entry->inferred_async_node == nullptr) { |
| ... | @@ -32042,7 +24018,7 @@ static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *i | ... | @@ -32042,7 +24018,7 @@ static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *i |
| 32042 | 24018 | ||
| 32043 | ZigType *result_type = frame->value->type->data.any_frame.result_type; | 24019 | ZigType *result_type = frame->value->type->data.any_frame.result_type; |
| 32044 | 24020 | ||
| 32045 | ZigFn *fn_entry = ira->new_irb.exec->fn_entry; | 24021 | ZigFn *fn_entry = ira->fn; |
| 32046 | ir_assert(fn_entry != nullptr, &instruction->base.base); | 24022 | ir_assert(fn_entry != nullptr, &instruction->base.base); |
| 32047 | 24023 | ||
| 32048 | // If it's not @Frame(func) then it's definitely a suspend point | 24024 | // If it's not @Frame(func) then it's definitely a suspend point |
| ... | @@ -32100,7 +24076,7 @@ static IrInstGen *ir_analyze_instruction_resume(IrAnalyze *ira, IrInstSrcResume | ... | @@ -32100,7 +24076,7 @@ static IrInstGen *ir_analyze_instruction_resume(IrAnalyze *ira, IrInstSrcResume |
| 32100 | } | 24076 | } |
| 32101 | 24077 | ||
| 32102 | static IrInstGen *ir_analyze_instruction_spill_begin(IrAnalyze *ira, IrInstSrcSpillBegin *instruction) { | 24078 | static IrInstGen *ir_analyze_instruction_spill_begin(IrAnalyze *ira, IrInstSrcSpillBegin *instruction) { |
| 32103 | if (ir_should_inline(ira->old_irb.exec, instruction->base.base.scope)) | 24079 | if (ir_should_inline(ira->zir, instruction->base.base.scope)) |
| 32104 | return ir_const_void(ira, &instruction->base.base); | 24080 | return ir_const_void(ira, &instruction->base.base); |
| 32105 | 24081 | ||
| 32106 | IrInstGen *operand = instruction->operand->child; | 24082 | IrInstGen *operand = instruction->operand->child; |
| ... | @@ -32126,7 +24102,7 @@ static IrInstGen *ir_analyze_instruction_spill_end(IrAnalyze *ira, IrInstSrcSpil | ... | @@ -32126,7 +24102,7 @@ static IrInstGen *ir_analyze_instruction_spill_end(IrAnalyze *ira, IrInstSrcSpil |
| 32126 | if (type_is_invalid(operand->value->type)) | 24102 | if (type_is_invalid(operand->value->type)) |
| 32127 | return ira->codegen->invalid_inst_gen; | 24103 | return ira->codegen->invalid_inst_gen; |
| 32128 | 24104 | ||
| 32129 | if (ir_should_inline(ira->old_irb.exec, instruction->base.base.scope) || | 24105 | if (ir_should_inline(ira->zir, instruction->base.base.scope) || |
| 32130 | !type_has_bits(ira->codegen, operand->value->type) || | 24106 | !type_has_bits(ira->codegen, operand->value->type) || |
| 32131 | instr_is_comptime(operand)) | 24107 | instr_is_comptime(operand)) |
| 32132 | { | 24108 | { |
| ... | @@ -32169,7 +24145,8 @@ static IrInstGen *ir_analyze_instruction_src(IrAnalyze *ira, IrInstSrcSrc *instr | ... | @@ -32169,7 +24145,8 @@ static IrInstGen *ir_analyze_instruction_src(IrAnalyze *ira, IrInstSrcSrc *instr |
| 32169 | fields[0]->special = ConstValSpecialStatic; | 24145 | fields[0]->special = ConstValSpecialStatic; |
| 32170 | 24146 | ||
| 32171 | ZigType *import = instruction->base.base.source_node->owner; | 24147 | ZigType *import = instruction->base.base.source_node->owner; |
| 32172 | Buf *path = import->data.structure.root_struct->path; | 24148 | RootStruct *root_struct = import->data.structure.root_struct; |
| 24149 | Buf *path = root_struct->path; | ||
| 32173 | ZigValue *file_name = create_const_str_lit(ira->codegen, path)->data.x_ptr.data.ref.pointee; | 24150 | ZigValue *file_name = create_const_str_lit(ira->codegen, path)->data.x_ptr.data.ref.pointee; |
| 32174 | init_const_slice(ira->codegen, fields[0], file_name, 0, buf_len(path), true); | 24151 | init_const_slice(ira->codegen, fields[0], file_name, 0, buf_len(path), true); |
| 32175 | fields[0]->type = u8_slice; | 24152 | fields[0]->type = u8_slice; |
| ... | @@ -32182,17 +24159,20 @@ static IrInstGen *ir_analyze_instruction_src(IrAnalyze *ira, IrInstSrcSrc *instr | ... | @@ -32182,17 +24159,20 @@ static IrInstGen *ir_analyze_instruction_src(IrAnalyze *ira, IrInstSrcSrc *instr |
| 32182 | init_const_slice(ira->codegen, fields[1], fn_name, 0, buf_len(&fn_entry->symbol_name), true); | 24159 | init_const_slice(ira->codegen, fields[1], fn_name, 0, buf_len(&fn_entry->symbol_name), true); |
| 32183 | fields[1]->type = u8_slice; | 24160 | fields[1]->type = u8_slice; |
| 32184 | 24161 | ||
| 24162 | |||
| 24163 | TokenLoc tok_loc = root_struct->token_locs[instruction->base.base.source_node->main_token]; | ||
| 24164 | |||
| 32185 | // line: u32 | 24165 | // line: u32 |
| 32186 | ensure_field_index(source_location_type, "line", 2); | 24166 | ensure_field_index(source_location_type, "line", 2); |
| 32187 | fields[2]->special = ConstValSpecialStatic; | 24167 | fields[2]->special = ConstValSpecialStatic; |
| 32188 | fields[2]->type = ira->codegen->builtin_types.entry_u32; | 24168 | fields[2]->type = ira->codegen->builtin_types.entry_u32; |
| 32189 | bigint_init_unsigned(&fields[2]->data.x_bigint, instruction->base.base.source_node->line + 1); | 24169 | bigint_init_unsigned(&fields[2]->data.x_bigint, tok_loc.line + 1); |
| 32190 | 24170 | ||
| 32191 | // column: u32 | 24171 | // column: u32 |
| 32192 | ensure_field_index(source_location_type, "column", 3); | 24172 | ensure_field_index(source_location_type, "column", 3); |
| 32193 | fields[3]->special = ConstValSpecialStatic; | 24173 | fields[3]->special = ConstValSpecialStatic; |
| 32194 | fields[3]->type = ira->codegen->builtin_types.entry_u32; | 24174 | fields[3]->type = ira->codegen->builtin_types.entry_u32; |
| 32195 | bigint_init_unsigned(&fields[3]->data.x_bigint, instruction->base.base.source_node->column + 1); | 24175 | bigint_init_unsigned(&fields[3]->data.x_bigint, tok_loc.column + 1); |
| 32196 | 24176 | ||
| 32197 | return ir_const_move(ira, &instruction->base.base, result); | 24177 | return ir_const_move(ira, &instruction->base.base, result); |
| 32198 | } | 24178 | } |
| ... | @@ -32484,29 +24464,31 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc | ... | @@ -32484,29 +24464,31 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc |
| 32484 | zig_unreachable(); | 24464 | zig_unreachable(); |
| 32485 | } | 24465 | } |
| 32486 | 24466 | ||
| 32487 | // This function attempts to evaluate IR code while doing type checking and other analysis. | 24467 | // This function attempts to evaluate stage1 ZIR code while doing type checking and other analysis. |
| 32488 | // It emits to a new IrExecutableGen which is partially evaluated IR code. | 24468 | // It emits to a new Stage1Air which is partially evaluated IR code. |
| 32489 | ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen *new_exec, | 24469 | ZigType *ir_analyze(CodeGen *codegen, Stage1Zir *stage1_zir, Stage1Air *stage1_air, |
| 32490 | ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *result_ptr) | 24470 | size_t *backward_branch_count, size_t *backward_branch_quota, |
| 24471 | ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *result_ptr, ZigFn *fn) | ||
| 32491 | { | 24472 | { |
| 32492 | assert(old_exec->first_err_trace_msg == nullptr); | 24473 | assert(stage1_zir->first_err_trace_msg == nullptr); |
| 32493 | assert(expected_type == nullptr || !type_is_invalid(expected_type)); | 24474 | assert(expected_type == nullptr || !type_is_invalid(expected_type)); |
| 32494 | 24475 | ||
| 32495 | IrAnalyze *ira = heap::c_allocator.create<IrAnalyze>(); | 24476 | IrAnalyze *ira = heap::c_allocator.create<IrAnalyze>(); |
| 24477 | ira->fn = fn; | ||
| 24478 | ira->backward_branch_count = backward_branch_count; | ||
| 24479 | ira->backward_branch_quota = backward_branch_quota; | ||
| 32496 | ira->ref_count = 1; | 24480 | ira->ref_count = 1; |
| 32497 | old_exec->analysis = ira; | ||
| 32498 | ira->codegen = codegen; | 24481 | ira->codegen = codegen; |
| 32499 | 24482 | ||
| 32500 | ira->explicit_return_type = expected_type; | 24483 | ira->explicit_return_type = expected_type; |
| 32501 | ira->explicit_return_type_source_node = expected_type_source_node; | 24484 | ira->explicit_return_type_source_node = expected_type_source_node; |
| 32502 | 24485 | ||
| 32503 | ira->old_irb.codegen = codegen; | 24486 | ira->zir = stage1_zir; |
| 32504 | ira->old_irb.exec = old_exec; | ||
| 32505 | 24487 | ||
| 32506 | ira->new_irb.codegen = codegen; | 24488 | ira->new_irb.codegen = codegen; |
| 32507 | ira->new_irb.exec = new_exec; | 24489 | ira->new_irb.exec = stage1_air; |
| 32508 | 24490 | ||
| 32509 | IrBasicBlockSrc *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0); | 24491 | Stage1ZirBasicBlock *old_entry_bb = ira->zir->basic_block_list.at(0); |
| 32510 | IrBasicBlockGen *new_entry_bb = ir_get_new_bb(ira, old_entry_bb, nullptr); | 24492 | IrBasicBlockGen *new_entry_bb = ir_get_new_bb(ira, old_entry_bb, nullptr); |
| 32511 | ira->new_irb.current_basic_block = new_entry_bb; | 24493 | ira->new_irb.current_basic_block = new_entry_bb; |
| 32512 | ira->old_bb_index = 0; | 24494 | ira->old_bb_index = 0; |
| ... | @@ -32516,18 +24498,18 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen | ... | @@ -32516,18 +24498,18 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen |
| 32516 | if (result_ptr != nullptr) { | 24498 | if (result_ptr != nullptr) { |
| 32517 | assert(result_ptr->type->id == ZigTypeIdPointer); | 24499 | assert(result_ptr->type->id == ZigTypeIdPointer); |
| 32518 | IrInstGenConst *const_inst = ir_create_inst_noval<IrInstGenConst>( | 24500 | IrInstGenConst *const_inst = ir_create_inst_noval<IrInstGenConst>( |
| 32519 | &ira->new_irb, new_exec->begin_scope, new_exec->source_node); | 24501 | &ira->new_irb, stage1_air->begin_scope, stage1_air->source_node); |
| 32520 | const_inst->base.value = result_ptr; | 24502 | const_inst->base.value = result_ptr; |
| 32521 | ira->return_ptr = &const_inst->base; | 24503 | ira->return_ptr = &const_inst->base; |
| 32522 | } else { | 24504 | } else { |
| 32523 | assert(new_exec->begin_scope != nullptr); | 24505 | assert(stage1_air->begin_scope != nullptr); |
| 32524 | assert(new_exec->source_node != nullptr); | 24506 | assert(stage1_air->source_node != nullptr); |
| 32525 | ira->return_ptr = ir_build_return_ptr(ira, new_exec->begin_scope, new_exec->source_node, | 24507 | ira->return_ptr = ir_build_return_ptr(ira, stage1_air->begin_scope, stage1_air->source_node, |
| 32526 | get_pointer_to_type(codegen, expected_type, false)); | 24508 | get_pointer_to_type(codegen, expected_type, false)); |
| 32527 | } | 24509 | } |
| 32528 | 24510 | ||
| 32529 | while (ira->old_bb_index < ira->old_irb.exec->basic_block_list.length) { | 24511 | while (ira->old_bb_index < ira->zir->basic_block_list.length) { |
| 32530 | IrInstSrc *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); | 24512 | IrInstSrc *old_instruction = ira->zir_current_basic_block->instruction_list.at(ira->instruction_index); |
| 32531 | 24513 | ||
| 32532 | if (old_instruction->base.ref_count == 0 && !ir_inst_src_has_side_effects(old_instruction)) { | 24514 | if (old_instruction->base.ref_count == 0 && !ir_inst_src_has_side_effects(old_instruction)) { |
| 32533 | ira->instruction_index += 1; | 24515 | ira->instruction_index += 1; |
| ... | @@ -32539,20 +24521,6 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen | ... | @@ -32539,20 +24521,6 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen |
| 32539 | old_instruction->src(); | 24521 | old_instruction->src(); |
| 32540 | fprintf(stderr, "~ "); | 24522 | fprintf(stderr, "~ "); |
| 32541 | ir_print_inst_src(codegen, stderr, old_instruction, 0); | 24523 | ir_print_inst_src(codegen, stderr, old_instruction, 0); |
| 32542 | bool want_break = false; | ||
| 32543 | if (ira->break_debug_id == old_instruction->base.debug_id) { | ||
| 32544 | want_break = true; | ||
| 32545 | } else if (old_instruction->base.source_node != nullptr) { | ||
| 32546 | for (size_t i = 0; i < dbg_ir_breakpoints_count; i += 1) { | ||
| 32547 | if (dbg_ir_breakpoints_buf[i].line == old_instruction->base.source_node->line + 1 && | ||
| 32548 | buf_ends_with_str(old_instruction->base.source_node->owner->data.structure.root_struct->path, | ||
| 32549 | dbg_ir_breakpoints_buf[i].src_file)) | ||
| 32550 | { | ||
| 32551 | want_break = true; | ||
| 32552 | } | ||
| 32553 | } | ||
| 32554 | } | ||
| 32555 | if (want_break) BREAKPOINT; | ||
| 32556 | } | 24524 | } |
| 32557 | IrInstGen *new_instruction = ir_analyze_instruction_base(ira, old_instruction); | 24525 | IrInstGen *new_instruction = ir_analyze_instruction_base(ira, old_instruction); |
| 32558 | if (new_instruction != nullptr) { | 24526 | if (new_instruction != nullptr) { |
| ... | @@ -32564,16 +24532,16 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen | ... | @@ -32564,16 +24532,16 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen |
| 32564 | fprintf(stderr, "-> (invalid)"); | 24532 | fprintf(stderr, "-> (invalid)"); |
| 32565 | } | 24533 | } |
| 32566 | 24534 | ||
| 32567 | if (new_exec->first_err_trace_msg != nullptr) { | 24535 | if (stage1_air->first_err_trace_msg != nullptr) { |
| 32568 | ira->codegen->trace_err = new_exec->first_err_trace_msg; | 24536 | ira->codegen->trace_err = stage1_air->first_err_trace_msg; |
| 32569 | } else { | 24537 | } else { |
| 32570 | new_exec->first_err_trace_msg = ira->codegen->trace_err; | 24538 | stage1_air->first_err_trace_msg = ira->codegen->trace_err; |
| 32571 | } | 24539 | } |
| 32572 | if (new_exec->first_err_trace_msg != nullptr && | 24540 | if (stage1_air->first_err_trace_msg != nullptr && |
| 32573 | !old_instruction->base.source_node->already_traced_this_node) | 24541 | !old_instruction->base.source_node->already_traced_this_node) |
| 32574 | { | 24542 | { |
| 32575 | old_instruction->base.source_node->already_traced_this_node = true; | 24543 | old_instruction->base.source_node->already_traced_this_node = true; |
| 32576 | new_exec->first_err_trace_msg = add_error_note(ira->codegen, new_exec->first_err_trace_msg, | 24544 | stage1_air->first_err_trace_msg = add_error_note(ira->codegen, stage1_air->first_err_trace_msg, |
| 32577 | old_instruction->base.source_node, buf_create_from_str("referenced here")); | 24545 | old_instruction->base.source_node, buf_create_from_str("referenced here")); |
| 32578 | } | 24546 | } |
| 32579 | return ira->codegen->builtin_types.entry_invalid; | 24547 | return ira->codegen->builtin_types.entry_invalid; |
| ... | @@ -32599,14 +24567,14 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen | ... | @@ -32599,14 +24567,14 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutableSrc *old_exec, IrExecutableGen |
| 32599 | } | 24567 | } |
| 32600 | 24568 | ||
| 32601 | ZigType *res_type; | 24569 | ZigType *res_type; |
| 32602 | if (new_exec->first_err_trace_msg != nullptr) { | 24570 | if (stage1_air->first_err_trace_msg != nullptr) { |
| 32603 | codegen->trace_err = new_exec->first_err_trace_msg; | 24571 | codegen->trace_err = stage1_air->first_err_trace_msg; |
| 32604 | if (codegen->trace_err != nullptr && new_exec->source_node != nullptr && | 24572 | if (codegen->trace_err != nullptr && stage1_air->source_node != nullptr && |
| 32605 | !new_exec->source_node->already_traced_this_node) | 24573 | !stage1_air->source_node->already_traced_this_node) |
| 32606 | { | 24574 | { |
| 32607 | new_exec->source_node->already_traced_this_node = true; | 24575 | stage1_air->source_node->already_traced_this_node = true; |
| 32608 | codegen->trace_err = add_error_note(codegen, codegen->trace_err, | 24576 | codegen->trace_err = add_error_note(codegen, codegen->trace_err, |
| 32609 | new_exec->source_node, buf_create_from_str("referenced here")); | 24577 | stage1_air->source_node, buf_create_from_str("referenced here")); |
| 32610 | } | 24578 | } |
| 32611 | res_type = ira->codegen->builtin_types.entry_invalid; | 24579 | res_type = ira->codegen->builtin_types.entry_invalid; |
| 32612 | } else if (ira->src_implicit_return_type_list.length == 0) { | 24580 | } else if (ira->src_implicit_return_type_list.length == 0) { |
| ... | @@ -33541,11 +25509,3 @@ void IrAnalyze::dump() { | ... | @@ -33541,11 +25509,3 @@ void IrAnalyze::dump() { |
| 33541 | ir_print_basic_block_gen(this->codegen, stderr, this->new_irb.current_basic_block, 1); | 25509 | ir_print_basic_block_gen(this->codegen, stderr, this->new_irb.current_basic_block, 1); |
| 33542 | } | 25510 | } |
| 33543 | } | 25511 | } |
| 33544 | |||
| 33545 | void dbg_ir_break(const char *src_file, uint32_t line) { | ||
| 33546 | dbg_ir_breakpoints_buf[dbg_ir_breakpoints_count] = {src_file, line}; | ||
| 33547 | dbg_ir_breakpoints_count += 1; | ||
| 33548 | } | ||
| 33549 | void dbg_ir_clear(void) { | ||
| 33550 | dbg_ir_breakpoints_count = 0; | ||
| 33551 | } |
src/stage1/ir.hpp+5-11| ... | @@ -10,31 +10,25 @@ | ... | @@ -10,31 +10,25 @@ |
| 10 | 10 | ||
| 11 | #include "all_types.hpp" | 11 | #include "all_types.hpp" |
| 12 | 12 | ||
| 13 | bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutableSrc *ir_executable); | ||
| 14 | bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); | ||
| 15 | |||
| 16 | IrInstGen *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, | 13 | IrInstGen *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, |
| 17 | ZigType *var_type, const char *name_hint); | 14 | ZigType *var_type, const char *name_hint); |
| 18 | 15 | ||
| 19 | Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, | 16 | Error ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, |
| 20 | ZigValue *return_ptr, size_t *backward_branch_count, size_t *backward_branch_quota, | 17 | ZigValue *return_ptr, size_t *backward_branch_count, size_t *backward_branch_quota, |
| 21 | ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, | 18 | ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, |
| 22 | IrExecutableGen *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef); | 19 | Stage1Air *parent_exec, AstNode *expected_type_source_node, UndefAllowed undef); |
| 23 | 20 | ||
| 24 | Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val); | 21 | Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val); |
| 25 | 22 | ||
| 26 | ZigType *ir_analyze(CodeGen *g, IrExecutableSrc *old_executable, IrExecutableGen *new_executable, | 23 | ZigType *ir_analyze(CodeGen *codegen, Stage1Zir *stage1_zir, Stage1Air *stage1_air, |
| 27 | ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *return_ptr); | 24 | size_t *backward_branch_count, size_t *backward_branch_quota, |
| 25 | ZigType *expected_type, AstNode *expected_type_source_node, ZigValue *result_ptr, | ||
| 26 | ZigFn *fn); | ||
| 28 | 27 | ||
| 29 | bool ir_inst_gen_has_side_effects(IrInstGen *inst); | 28 | bool ir_inst_gen_has_side_effects(IrInstGen *inst); |
| 30 | bool ir_inst_src_has_side_effects(IrInstSrc *inst); | ||
| 31 | 29 | ||
| 32 | struct IrAnalyze; | 30 | struct IrAnalyze; |
| 33 | ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_val, | 31 | ZigValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ZigValue *const_val, |
| 34 | AstNode *source_node); | 32 | AstNode *source_node); |
| 35 | 33 | ||
| 36 | // for debugging purposes | ||
| 37 | void dbg_ir_break(const char *src_file, uint32_t line); | ||
| 38 | void dbg_ir_clear(void); | ||
| 39 | |||
| 40 | #endif | 34 | #endif |
src/stage1/ir_print.cpp+7-6| ... | @@ -8,6 +8,7 @@ | ... | @@ -8,6 +8,7 @@ |
| 8 | #include "all_types.hpp" | 8 | #include "all_types.hpp" |
| 9 | #include "analyze.hpp" | 9 | #include "analyze.hpp" |
| 10 | #include "ir.hpp" | 10 | #include "ir.hpp" |
| 11 | #include "astgen.hpp" | ||
| 11 | #include "ir_print.hpp" | 12 | #include "ir_print.hpp" |
| 12 | #include "os.hpp" | 13 | #include "os.hpp" |
| 13 | 14 | ||
| ... | @@ -632,7 +633,7 @@ static void ir_print_other_inst_gen(IrPrintGen *irp, IrInstGen *inst) { | ... | @@ -632,7 +633,7 @@ static void ir_print_other_inst_gen(IrPrintGen *irp, IrInstGen *inst) { |
| 632 | } | 633 | } |
| 633 | } | 634 | } |
| 634 | 635 | ||
| 635 | static void ir_print_other_block(IrPrintSrc *irp, IrBasicBlockSrc *bb) { | 636 | static void ir_print_other_block(IrPrintSrc *irp, Stage1ZirBasicBlock *bb) { |
| 636 | if (bb == nullptr) { | 637 | if (bb == nullptr) { |
| 637 | fprintf(irp->f, "(null block)"); | 638 | fprintf(irp->f, "(null block)"); |
| 638 | } else { | 639 | } else { |
| ... | @@ -1005,7 +1006,7 @@ static void ir_print_phi(IrPrintSrc *irp, IrInstSrcPhi *phi_instruction) { | ... | @@ -1005,7 +1006,7 @@ static void ir_print_phi(IrPrintSrc *irp, IrInstSrcPhi *phi_instruction) { |
| 1005 | assert(phi_instruction->incoming_count != 0); | 1006 | assert(phi_instruction->incoming_count != 0); |
| 1006 | assert(phi_instruction->incoming_count != SIZE_MAX); | 1007 | assert(phi_instruction->incoming_count != SIZE_MAX); |
| 1007 | for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { | 1008 | for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { |
| 1008 | IrBasicBlockSrc *incoming_block = phi_instruction->incoming_blocks[i]; | 1009 | Stage1ZirBasicBlock *incoming_block = phi_instruction->incoming_blocks[i]; |
| 1009 | IrInstSrc *incoming_value = phi_instruction->incoming_values[i]; | 1010 | IrInstSrc *incoming_value = phi_instruction->incoming_values[i]; |
| 1010 | if (i != 0) | 1011 | if (i != 0) |
| 1011 | fprintf(irp->f, " "); | 1012 | fprintf(irp->f, " "); |
| ... | @@ -3349,7 +3350,7 @@ static void ir_print_inst_gen(IrPrintGen *irp, IrInstGen *instruction, bool trai | ... | @@ -3349,7 +3350,7 @@ static void ir_print_inst_gen(IrPrintGen *irp, IrInstGen *instruction, bool trai |
| 3349 | fprintf(irp->f, "\n"); | 3350 | fprintf(irp->f, "\n"); |
| 3350 | } | 3351 | } |
| 3351 | 3352 | ||
| 3352 | static void irp_print_basic_block_src(IrPrintSrc *irp, IrBasicBlockSrc *current_block) { | 3353 | static void irp_print_basic_block_src(IrPrintSrc *irp, Stage1ZirBasicBlock *current_block) { |
| 3353 | fprintf(irp->f, "%s_%" PRIu32 ":\n", current_block->name_hint, current_block->debug_id); | 3354 | fprintf(irp->f, "%s_%" PRIu32 ":\n", current_block->name_hint, current_block->debug_id); |
| 3354 | for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) { | 3355 | for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) { |
| 3355 | IrInstSrc *instruction = current_block->instruction_list.at(instr_i); | 3356 | IrInstSrc *instruction = current_block->instruction_list.at(instr_i); |
| ... | @@ -3369,7 +3370,7 @@ static void irp_print_basic_block_gen(IrPrintGen *irp, IrBasicBlockGen *current_ | ... | @@ -3369,7 +3370,7 @@ static void irp_print_basic_block_gen(IrPrintGen *irp, IrBasicBlockGen *current_ |
| 3369 | } | 3370 | } |
| 3370 | } | 3371 | } |
| 3371 | 3372 | ||
| 3372 | void ir_print_basic_block_src(CodeGen *codegen, FILE *f, IrBasicBlockSrc *bb, int indent_size) { | 3373 | void ir_print_basic_block_src(CodeGen *codegen, FILE *f, Stage1ZirBasicBlock *bb, int indent_size) { |
| 3373 | IrPrintSrc ir_print = {}; | 3374 | IrPrintSrc ir_print = {}; |
| 3374 | ir_print.codegen = codegen; | 3375 | ir_print.codegen = codegen; |
| 3375 | ir_print.f = f; | 3376 | ir_print.f = f; |
| ... | @@ -3395,7 +3396,7 @@ void ir_print_basic_block_gen(CodeGen *codegen, FILE *f, IrBasicBlockGen *bb, in | ... | @@ -3395,7 +3396,7 @@ void ir_print_basic_block_gen(CodeGen *codegen, FILE *f, IrBasicBlockGen *bb, in |
| 3395 | ir_print.printed.deinit(); | 3396 | ir_print.printed.deinit(); |
| 3396 | } | 3397 | } |
| 3397 | 3398 | ||
| 3398 | void ir_print_src(CodeGen *codegen, FILE *f, IrExecutableSrc *executable, int indent_size) { | 3399 | void ir_print_src(CodeGen *codegen, FILE *f, Stage1Zir *executable, int indent_size) { |
| 3399 | IrPrintSrc ir_print = {}; | 3400 | IrPrintSrc ir_print = {}; |
| 3400 | IrPrintSrc *irp = &ir_print; | 3401 | IrPrintSrc *irp = &ir_print; |
| 3401 | irp->codegen = codegen; | 3402 | irp->codegen = codegen; |
| ... | @@ -3408,7 +3409,7 @@ void ir_print_src(CodeGen *codegen, FILE *f, IrExecutableSrc *executable, int in | ... | @@ -3408,7 +3409,7 @@ void ir_print_src(CodeGen *codegen, FILE *f, IrExecutableSrc *executable, int in |
| 3408 | } | 3409 | } |
| 3409 | } | 3410 | } |
| 3410 | 3411 | ||
| 3411 | void ir_print_gen(CodeGen *codegen, FILE *f, IrExecutableGen *executable, int indent_size) { | 3412 | void ir_print_gen(CodeGen *codegen, FILE *f, Stage1Air *executable, int indent_size) { |
| 3412 | IrPrintGen ir_print = {}; | 3413 | IrPrintGen ir_print = {}; |
| 3413 | IrPrintGen *irp = &ir_print; | 3414 | IrPrintGen *irp = &ir_print; |
| 3414 | irp->codegen = codegen; | 3415 | irp->codegen = codegen; |
src/stage1/ir_print.hpp+3-3| ... | @@ -12,11 +12,11 @@ | ... | @@ -12,11 +12,11 @@ |
| 12 | 12 | ||
| 13 | #include <stdio.h> | 13 | #include <stdio.h> |
| 14 | 14 | ||
| 15 | void ir_print_src(CodeGen *codegen, FILE *f, IrExecutableSrc *executable, int indent_size); | 15 | void ir_print_src(CodeGen *codegen, FILE *f, Stage1Zir *executable, int indent_size); |
| 16 | void ir_print_gen(CodeGen *codegen, FILE *f, IrExecutableGen *executable, int indent_size); | 16 | void ir_print_gen(CodeGen *codegen, FILE *f, Stage1Air *executable, int indent_size); |
| 17 | void ir_print_inst_src(CodeGen *codegen, FILE *f, IrInstSrc *inst, int indent_size); | 17 | void ir_print_inst_src(CodeGen *codegen, FILE *f, IrInstSrc *inst, int indent_size); |
| 18 | void ir_print_inst_gen(CodeGen *codegen, FILE *f, IrInstGen *inst, int indent_size); | 18 | void ir_print_inst_gen(CodeGen *codegen, FILE *f, IrInstGen *inst, int indent_size); |
| 19 | void ir_print_basic_block_src(CodeGen *codegen, FILE *f, IrBasicBlockSrc *bb, int indent_size); | 19 | void ir_print_basic_block_src(CodeGen *codegen, FILE *f, Stage1ZirBasicBlock *bb, int indent_size); |
| 20 | void ir_print_basic_block_gen(CodeGen *codegen, FILE *f, IrBasicBlockGen *bb, int indent_size); | 20 | void ir_print_basic_block_gen(CodeGen *codegen, FILE *f, IrBasicBlockGen *bb, int indent_size); |
| 21 | 21 | ||
| 22 | const char* ir_inst_src_type_str(IrInstSrcId id); | 22 | const char* ir_inst_src_type_str(IrInstSrcId id); |
src/stage1/parser.cpp+921-593| ... | @@ -16,28 +16,34 @@ | ... | @@ -16,28 +16,34 @@ |
| 16 | 16 | ||
| 17 | struct ParseContext { | 17 | struct ParseContext { |
| 18 | Buf *buf; | 18 | Buf *buf; |
| 19 | size_t current_token; | 19 | // Shortcut to `owner->data.structure.root_struct->token_ids`. |
| 20 | ZigList<Token> *tokens; | 20 | TokenId *token_ids; |
| 21 | // Shortcut to `owner->data.structure.root_struct->token_locs`. | ||
| 22 | TokenLoc *token_locs; | ||
| 21 | ZigType *owner; | 23 | ZigType *owner; |
| 24 | TokenIndex current_token; | ||
| 22 | ErrColor err_color; | 25 | ErrColor err_color; |
| 26 | // Shortcut to `owner->data.structure.root_struct->token_count`. | ||
| 27 | uint32_t token_count; | ||
| 23 | }; | 28 | }; |
| 24 | 29 | ||
| 25 | struct PtrPayload { | 30 | struct PtrPayload { |
| 26 | Token *asterisk; | 31 | TokenIndex asterisk; |
| 27 | Token *payload; | 32 | TokenIndex payload; |
| 28 | }; | 33 | }; |
| 29 | 34 | ||
| 30 | struct PtrIndexPayload { | 35 | struct PtrIndexPayload { |
| 31 | Token *asterisk; | 36 | TokenIndex asterisk; |
| 32 | Token *payload; | 37 | TokenIndex payload; |
| 33 | Token *index; | 38 | TokenIndex index; |
| 34 | }; | 39 | }; |
| 35 | 40 | ||
| 36 | static AstNode *ast_parse_root(ParseContext *pc); | 41 | static AstNode *ast_parse_root(ParseContext *pc); |
| 37 | static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc); | 42 | static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc); |
| 38 | static AstNode *ast_parse_test_decl(ParseContext *pc); | 43 | static AstNode *ast_parse_test_decl(ParseContext *pc); |
| 39 | static AstNode *ast_parse_top_level_comptime(ParseContext *pc); | 44 | static AstNode *ast_parse_top_level_comptime(ParseContext *pc); |
| 40 | static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, Buf *doc_comments); | 45 | static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, |
| 46 | TokenIndex doc_comments); | ||
| 41 | static AstNode *ast_parse_fn_proto(ParseContext *pc); | 47 | static AstNode *ast_parse_fn_proto(ParseContext *pc); |
| 42 | static AstNode *ast_parse_var_decl(ParseContext *pc); | 48 | static AstNode *ast_parse_var_decl(ParseContext *pc); |
| 43 | static AstNode *ast_parse_container_field(ParseContext *pc); | 49 | static AstNode *ast_parse_container_field(ParseContext *pc); |
| ... | @@ -87,8 +93,8 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc); | ... | @@ -87,8 +93,8 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc); |
| 87 | static AstNode *ast_parse_asm_input(ParseContext *pc); | 93 | static AstNode *ast_parse_asm_input(ParseContext *pc); |
| 88 | static AsmInput *ast_parse_asm_input_item(ParseContext *pc); | 94 | static AsmInput *ast_parse_asm_input_item(ParseContext *pc); |
| 89 | static AstNode *ast_parse_asm_clobbers(ParseContext *pc); | 95 | static AstNode *ast_parse_asm_clobbers(ParseContext *pc); |
| 90 | static Token *ast_parse_break_label(ParseContext *pc); | 96 | static TokenIndex ast_parse_break_label(ParseContext *pc); |
| 91 | static Token *ast_parse_block_label(ParseContext *pc); | 97 | static TokenIndex ast_parse_block_label(ParseContext *pc); |
| 92 | static AstNode *ast_parse_field_init(ParseContext *pc); | 98 | static AstNode *ast_parse_field_init(ParseContext *pc); |
| 93 | static AstNode *ast_parse_while_continue_expr(ParseContext *pc); | 99 | static AstNode *ast_parse_while_continue_expr(ParseContext *pc); |
| 94 | static AstNode *ast_parse_link_section(ParseContext *pc); | 100 | static AstNode *ast_parse_link_section(ParseContext *pc); |
| ... | @@ -98,7 +104,7 @@ static AstNode *ast_parse_param_type(ParseContext *pc); | ... | @@ -98,7 +104,7 @@ static AstNode *ast_parse_param_type(ParseContext *pc); |
| 98 | static AstNode *ast_parse_if_prefix(ParseContext *pc); | 104 | static AstNode *ast_parse_if_prefix(ParseContext *pc); |
| 99 | static AstNode *ast_parse_while_prefix(ParseContext *pc); | 105 | static AstNode *ast_parse_while_prefix(ParseContext *pc); |
| 100 | static AstNode *ast_parse_for_prefix(ParseContext *pc); | 106 | static AstNode *ast_parse_for_prefix(ParseContext *pc); |
| 101 | static Token *ast_parse_payload(ParseContext *pc); | 107 | static TokenIndex ast_parse_payload(ParseContext *pc); |
| 102 | static Optional<PtrPayload> ast_parse_ptr_payload(ParseContext *pc); | 108 | static Optional<PtrPayload> ast_parse_ptr_payload(ParseContext *pc); |
| 103 | static Optional<PtrIndexPayload> ast_parse_ptr_index_payload(ParseContext *pc); | 109 | static Optional<PtrIndexPayload> ast_parse_ptr_index_payload(ParseContext *pc); |
| 104 | static AstNode *ast_parse_switch_prong(ParseContext *pc); | 110 | static AstNode *ast_parse_switch_prong(ParseContext *pc); |
| ... | @@ -120,29 +126,34 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc); | ... | @@ -120,29 +126,34 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc); |
| 120 | static AstNode *ast_parse_container_decl_type(ParseContext *pc); | 126 | static AstNode *ast_parse_container_decl_type(ParseContext *pc); |
| 121 | static AstNode *ast_parse_byte_align(ParseContext *pc); | 127 | static AstNode *ast_parse_byte_align(ParseContext *pc); |
| 122 | 128 | ||
| 129 | ATTRIBUTE_NORETURN | ||
| 130 | static void ast_error_offset(RootStruct *root_struct, ErrColor err_color, | ||
| 131 | TokenIndex token, size_t bad_index, Buf *msg) | ||
| 132 | { | ||
| 133 | assert(token < root_struct->token_count); | ||
| 134 | uint32_t byte_offset = root_struct->token_locs[token].offset; | ||
| 135 | ErrorMsg *err = err_msg_create_with_offset(root_struct->path, | ||
| 136 | byte_offset + bad_index, buf_ptr(root_struct->source_code), msg); | ||
| 137 | |||
| 138 | print_err_msg(err, err_color); | ||
| 139 | exit(EXIT_FAILURE); | ||
| 140 | } | ||
| 141 | |||
| 123 | ATTRIBUTE_PRINTF(3, 4) | 142 | ATTRIBUTE_PRINTF(3, 4) |
| 124 | ATTRIBUTE_NORETURN | 143 | ATTRIBUTE_NORETURN |
| 125 | static void ast_error(ParseContext *pc, Token *token, const char *format, ...) { | 144 | static void ast_error(ParseContext *pc, TokenIndex token, const char *format, ...) { |
| 126 | va_list ap; | 145 | va_list ap; |
| 127 | va_start(ap, format); | 146 | va_start(ap, format); |
| 128 | Buf *msg = buf_vprintf(format, ap); | 147 | Buf *msg = buf_vprintf(format, ap); |
| 129 | va_end(ap); | 148 | va_end(ap); |
| 130 | 149 | ||
| 131 | 150 | RootStruct *root_struct = pc->owner->data.structure.root_struct; | |
| 132 | ErrorMsg *err = err_msg_create_with_line(pc->owner->data.structure.root_struct->path, | 151 | ast_error_offset(root_struct, pc->err_color, token, 0, msg); |
| 133 | token->start_line, token->start_column, | ||
| 134 | pc->owner->data.structure.root_struct->source_code, | ||
| 135 | pc->owner->data.structure.root_struct->line_offsets, msg); | ||
| 136 | err->line_start = token->start_line; | ||
| 137 | err->column_start = token->start_column; | ||
| 138 | |||
| 139 | print_err_msg(err, pc->err_color); | ||
| 140 | exit(EXIT_FAILURE); | ||
| 141 | } | 152 | } |
| 142 | 153 | ||
| 143 | ATTRIBUTE_NORETURN | 154 | ATTRIBUTE_NORETURN |
| 144 | static void ast_invalid_token_error(ParseContext *pc, Token *token) { | 155 | static void ast_invalid_token_error(ParseContext *pc, TokenIndex token) { |
| 145 | ast_error(pc, token, "invalid token: '%s'", token_name(token->id)); | 156 | ast_error(pc, token, "invalid token: '%s'", token_name(pc->token_ids[token])); |
| 146 | } | 157 | } |
| 147 | 158 | ||
| 148 | static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) { | 159 | static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) { |
| ... | @@ -152,48 +163,44 @@ static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) { | ... | @@ -152,48 +163,44 @@ static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) { |
| 152 | return node; | 163 | return node; |
| 153 | } | 164 | } |
| 154 | 165 | ||
| 155 | static AstNode *ast_create_node(ParseContext *pc, NodeType type, Token *first_token) { | 166 | static AstNode *ast_create_node(ParseContext *pc, NodeType type, TokenIndex first_token) { |
| 156 | assert(first_token); | 167 | assert(first_token); |
| 157 | AstNode *node = ast_create_node_no_line_info(pc, type); | 168 | AstNode *node = ast_create_node_no_line_info(pc, type); |
| 158 | node->line = first_token->start_line; | 169 | node->main_token = first_token; |
| 159 | node->column = first_token->start_column; | ||
| 160 | return node; | 170 | return node; |
| 161 | } | 171 | } |
| 162 | 172 | ||
| 163 | static AstNode *ast_create_node_copy_line_info(ParseContext *pc, NodeType type, AstNode *from) { | 173 | static AstNode *ast_create_node_copy_line_info(ParseContext *pc, NodeType type, AstNode *from) { |
| 164 | assert(from); | 174 | assert(from); |
| 165 | AstNode *node = ast_create_node_no_line_info(pc, type); | 175 | AstNode *node = ast_create_node_no_line_info(pc, type); |
| 166 | node->line = from->line; | 176 | node->main_token = from->main_token; |
| 167 | node->column = from->column; | ||
| 168 | return node; | 177 | return node; |
| 169 | } | 178 | } |
| 170 | 179 | ||
| 171 | static Token *peek_token_i(ParseContext *pc, size_t i) { | 180 | static TokenIndex peek_token(ParseContext *pc) { |
| 172 | return &pc->tokens->at(pc->current_token + i); | 181 | return pc->current_token; |
| 173 | } | ||
| 174 | |||
| 175 | static Token *peek_token(ParseContext *pc) { | ||
| 176 | return peek_token_i(pc, 0); | ||
| 177 | } | 182 | } |
| 178 | 183 | ||
| 179 | static Token *eat_token(ParseContext *pc) { | 184 | static TokenIndex eat_token(ParseContext *pc) { |
| 180 | Token *res = peek_token(pc); | 185 | TokenIndex res = peek_token(pc); |
| 181 | pc->current_token += 1; | 186 | pc->current_token += 1; |
| 182 | return res; | 187 | return res; |
| 183 | } | 188 | } |
| 184 | 189 | ||
| 185 | static Token *eat_token_if(ParseContext *pc, TokenId id) { | 190 | static TokenIndex eat_token_if(ParseContext *pc, TokenId id) { |
| 186 | Token *res = peek_token(pc); | 191 | TokenIndex res = peek_token(pc); |
| 187 | if (res->id == id) | 192 | if (pc->token_ids[res] == id) { |
| 188 | return eat_token(pc); | 193 | return eat_token(pc); |
| 194 | } | ||
| 189 | 195 | ||
| 190 | return nullptr; | 196 | return 0; |
| 191 | } | 197 | } |
| 192 | 198 | ||
| 193 | static Token *expect_token(ParseContext *pc, TokenId id) { | 199 | static TokenIndex expect_token(ParseContext *pc, TokenId id) { |
| 194 | Token *res = eat_token(pc); | 200 | TokenIndex res = eat_token(pc); |
| 195 | if (res->id != id) | 201 | TokenId actual_id = pc->token_ids[res]; |
| 196 | ast_error(pc, res, "expected token '%s', found '%s'", token_name(id), token_name(res->id)); | 202 | if (actual_id != id) |
| 203 | ast_error(pc, res, "expected token '%s', found '%s'", token_name(id), token_name(actual_id)); | ||
| 197 | 204 | ||
| 198 | return res; | 205 | return res; |
| 199 | } | 206 | } |
| ... | @@ -202,23 +209,34 @@ static void put_back_token(ParseContext *pc) { | ... | @@ -202,23 +209,34 @@ static void put_back_token(ParseContext *pc) { |
| 202 | pc->current_token -= 1; | 209 | pc->current_token -= 1; |
| 203 | } | 210 | } |
| 204 | 211 | ||
| 205 | static Buf *token_buf(Token *token) { | 212 | static Buf *token_buf(ParseContext *pc, TokenIndex token) { |
| 206 | if (token == nullptr) | 213 | Error err; |
| 214 | |||
| 215 | if (token == 0) | ||
| 207 | return nullptr; | 216 | return nullptr; |
| 208 | assert(token->id == TokenIdStringLiteral || token->id == TokenIdMultilineStringLiteral || token->id == TokenIdSymbol); | ||
| 209 | return &token->data.str_lit.str; | ||
| 210 | } | ||
| 211 | 217 | ||
| 212 | static BigInt *token_bigint(Token *token) { | 218 | RootStruct *root_struct = pc->owner->data.structure.root_struct; |
| 213 | assert(token->id == TokenIdIntLiteral); | 219 | if (root_struct->token_ids[token] == TokenIdIdentifier) { |
| 214 | return &token->data.int_lit.bigint; | 220 | return token_identifier_buf(root_struct, token); |
| 221 | } else if (root_struct->token_ids[token] == TokenIdStringLiteral) { | ||
| 222 | assert(root_struct->token_ids[token] == TokenIdStringLiteral); | ||
| 223 | const char *source = buf_ptr(root_struct->source_code); | ||
| 224 | size_t byte_offset = root_struct->token_locs[token].offset; | ||
| 225 | size_t bad_index; | ||
| 226 | Buf *str = buf_alloc(); | ||
| 227 | if ((err = source_string_literal_buf(source + byte_offset, str, &bad_index))) { | ||
| 228 | ast_error_offset(root_struct, pc->err_color, token, bad_index, | ||
| 229 | buf_create_from_str("invalid string literal character")); | ||
| 230 | } | ||
| 231 | return str; | ||
| 232 | } else { | ||
| 233 | zig_unreachable(); | ||
| 234 | } | ||
| 215 | } | 235 | } |
| 216 | 236 | ||
| 217 | static AstNode *token_symbol(ParseContext *pc, Token *token) { | 237 | static AstNode *token_identifier(ParseContext *pc, TokenIndex token) { |
| 218 | assert(token->id == TokenIdSymbol); | 238 | assert(pc->token_ids[token] == TokenIdIdentifier); |
| 219 | AstNode *res = ast_create_node(pc, NodeTypeSymbol, token); | 239 | return ast_create_node(pc, NodeTypeIdentifier, token); |
| 220 | res->data.symbol_expr.symbol = token_buf(token); | ||
| 221 | return res; | ||
| 222 | } | 240 | } |
| 223 | 241 | ||
| 224 | // (Rule SEP)* Rule? | 242 | // (Rule SEP)* Rule? |
| ... | @@ -231,7 +249,7 @@ static ZigList<T *> ast_parse_list(ParseContext *pc, TokenId sep, T *(*parser)(P | ... | @@ -231,7 +249,7 @@ static ZigList<T *> ast_parse_list(ParseContext *pc, TokenId sep, T *(*parser)(P |
| 231 | break; | 249 | break; |
| 232 | 250 | ||
| 233 | res.append(curr); | 251 | res.append(curr); |
| 234 | if (eat_token_if(pc, sep) == nullptr) | 252 | if (eat_token_if(pc, sep) == 0) |
| 235 | break; | 253 | break; |
| 236 | } | 254 | } |
| 237 | 255 | ||
| ... | @@ -355,22 +373,22 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse | ... | @@ -355,22 +373,22 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse |
| 355 | return nullptr; | 373 | return nullptr; |
| 356 | 374 | ||
| 357 | AstNode *body = ast_expect(pc, body_parser); | 375 | AstNode *body = ast_expect(pc, body_parser); |
| 358 | Token *err_payload = nullptr; | 376 | TokenIndex err_payload = 0; |
| 359 | AstNode *else_body = nullptr; | 377 | AstNode *else_body = nullptr; |
| 360 | if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) { | 378 | if (eat_token_if(pc, TokenIdKeywordElse) != 0) { |
| 361 | err_payload = ast_parse_payload(pc); | 379 | err_payload = ast_parse_payload(pc); |
| 362 | else_body = ast_expect(pc, body_parser); | 380 | else_body = ast_expect(pc, body_parser); |
| 363 | } | 381 | } |
| 364 | 382 | ||
| 365 | assert(res->type == NodeTypeIfOptional); | 383 | assert(res->type == NodeTypeIfOptional); |
| 366 | if (err_payload != nullptr) { | 384 | if (err_payload != 0) { |
| 367 | AstNodeTestExpr old = res->data.test_expr; | 385 | AstNodeTestExpr old = res->data.test_expr; |
| 368 | res->type = NodeTypeIfErrorExpr; | 386 | res->type = NodeTypeIfErrorExpr; |
| 369 | res->data.if_err_expr.target_node = old.target_node; | 387 | res->data.if_err_expr.target_node = old.target_node; |
| 370 | res->data.if_err_expr.var_is_ptr = old.var_is_ptr; | 388 | res->data.if_err_expr.var_is_ptr = old.var_is_ptr; |
| 371 | res->data.if_err_expr.var_symbol = old.var_symbol; | 389 | res->data.if_err_expr.var_symbol = old.var_symbol; |
| 372 | res->data.if_err_expr.then_node = body; | 390 | res->data.if_err_expr.then_node = body; |
| 373 | res->data.if_err_expr.err_symbol = token_buf(err_payload); | 391 | res->data.if_err_expr.err_symbol = token_buf(pc, err_payload); |
| 374 | res->data.if_err_expr.else_node = else_body; | 392 | res->data.if_err_expr.else_node = else_body; |
| 375 | return res; | 393 | return res; |
| 376 | } | 394 | } |
| ... | @@ -395,22 +413,22 @@ static AstNode *ast_parse_loop_expr_helper( | ... | @@ -395,22 +413,22 @@ static AstNode *ast_parse_loop_expr_helper( |
| 395 | AstNode *(*for_parser)(ParseContext *), | 413 | AstNode *(*for_parser)(ParseContext *), |
| 396 | AstNode *(*while_parser)(ParseContext *) | 414 | AstNode *(*while_parser)(ParseContext *) |
| 397 | ) { | 415 | ) { |
| 398 | Token *inline_token = eat_token_if(pc, TokenIdKeywordInline); | 416 | TokenIndex inline_token = eat_token_if(pc, TokenIdKeywordInline); |
| 399 | AstNode *for_expr = for_parser(pc); | 417 | AstNode *for_expr = for_parser(pc); |
| 400 | if (for_expr != nullptr) { | 418 | if (for_expr != nullptr) { |
| 401 | assert(for_expr->type == NodeTypeForExpr); | 419 | assert(for_expr->type == NodeTypeForExpr); |
| 402 | for_expr->data.for_expr.is_inline = inline_token != nullptr; | 420 | for_expr->data.for_expr.is_inline = inline_token != 0; |
| 403 | return for_expr; | 421 | return for_expr; |
| 404 | } | 422 | } |
| 405 | 423 | ||
| 406 | AstNode *while_expr = while_parser(pc); | 424 | AstNode *while_expr = while_parser(pc); |
| 407 | if (while_expr != nullptr) { | 425 | if (while_expr != nullptr) { |
| 408 | assert(while_expr->type == NodeTypeWhileExpr); | 426 | assert(while_expr->type == NodeTypeWhileExpr); |
| 409 | while_expr->data.while_expr.is_inline = inline_token != nullptr; | 427 | while_expr->data.while_expr.is_inline = inline_token != 0; |
| 410 | return while_expr; | 428 | return while_expr; |
| 411 | } | 429 | } |
| 412 | 430 | ||
| 413 | if (inline_token != nullptr) | 431 | if (inline_token != 0) |
| 414 | ast_invalid_token_error(pc, peek_token(pc)); | 432 | ast_invalid_token_error(pc, peek_token(pc)); |
| 415 | return nullptr; | 433 | return nullptr; |
| 416 | } | 434 | } |
| ... | @@ -423,7 +441,7 @@ static AstNode *ast_parse_for_expr_helper(ParseContext *pc, AstNode *(*body_pars | ... | @@ -423,7 +441,7 @@ static AstNode *ast_parse_for_expr_helper(ParseContext *pc, AstNode *(*body_pars |
| 423 | 441 | ||
| 424 | AstNode *body = ast_expect(pc, body_parser); | 442 | AstNode *body = ast_expect(pc, body_parser); |
| 425 | AstNode *else_body = nullptr; | 443 | AstNode *else_body = nullptr; |
| 426 | if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) | 444 | if (eat_token_if(pc, TokenIdKeywordElse) != 0) |
| 427 | else_body = ast_expect(pc, body_parser); | 445 | else_body = ast_expect(pc, body_parser); |
| 428 | 446 | ||
| 429 | assert(res->type == NodeTypeForExpr); | 447 | assert(res->type == NodeTypeForExpr); |
| ... | @@ -439,24 +457,24 @@ static AstNode *ast_parse_while_expr_helper(ParseContext *pc, AstNode *(*body_pa | ... | @@ -439,24 +457,24 @@ static AstNode *ast_parse_while_expr_helper(ParseContext *pc, AstNode *(*body_pa |
| 439 | return nullptr; | 457 | return nullptr; |
| 440 | 458 | ||
| 441 | AstNode *body = ast_expect(pc, body_parser); | 459 | AstNode *body = ast_expect(pc, body_parser); |
| 442 | Token *err_payload = nullptr; | 460 | TokenIndex err_payload = 0; |
| 443 | AstNode *else_body = nullptr; | 461 | AstNode *else_body = nullptr; |
| 444 | if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) { | 462 | if (eat_token_if(pc, TokenIdKeywordElse) != 0) { |
| 445 | err_payload = ast_parse_payload(pc); | 463 | err_payload = ast_parse_payload(pc); |
| 446 | else_body = ast_expect(pc, body_parser); | 464 | else_body = ast_expect(pc, body_parser); |
| 447 | } | 465 | } |
| 448 | 466 | ||
| 449 | assert(res->type == NodeTypeWhileExpr); | 467 | assert(res->type == NodeTypeWhileExpr); |
| 450 | res->data.while_expr.body = body; | 468 | res->data.while_expr.body = body; |
| 451 | res->data.while_expr.err_symbol = token_buf(err_payload); | 469 | res->data.while_expr.err_symbol = token_buf(pc, err_payload); |
| 452 | res->data.while_expr.else_node = else_body; | 470 | res->data.while_expr.else_node = else_body; |
| 453 | return res; | 471 | return res; |
| 454 | } | 472 | } |
| 455 | 473 | ||
| 456 | template<TokenId id, BinOpType op> | 474 | template<TokenId id, BinOpType op> |
| 457 | AstNode *ast_parse_bin_op_simple(ParseContext *pc) { | 475 | AstNode *ast_parse_bin_op_simple(ParseContext *pc) { |
| 458 | Token *op_token = eat_token_if(pc, id); | 476 | TokenIndex op_token = eat_token_if(pc, id); |
| 459 | if (op_token == nullptr) | 477 | if (op_token == 0) |
| 460 | return nullptr; | 478 | return nullptr; |
| 461 | 479 | ||
| 462 | AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); | 480 | AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); |
| ... | @@ -464,20 +482,25 @@ AstNode *ast_parse_bin_op_simple(ParseContext *pc) { | ... | @@ -464,20 +482,25 @@ AstNode *ast_parse_bin_op_simple(ParseContext *pc) { |
| 464 | return res; | 482 | return res; |
| 465 | } | 483 | } |
| 466 | 484 | ||
| 467 | AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens, ZigType *owner, ErrColor err_color) { | 485 | AstNode *ast_parse(Buf *buf, ZigType *owner, ErrColor err_color) { |
| 486 | RootStruct *root_struct = owner->data.structure.root_struct; | ||
| 487 | |||
| 468 | ParseContext pc = {}; | 488 | ParseContext pc = {}; |
| 469 | pc.err_color = err_color; | 489 | pc.err_color = err_color; |
| 470 | pc.owner = owner; | 490 | pc.owner = owner; |
| 471 | pc.buf = buf; | 491 | pc.buf = buf; |
| 472 | pc.tokens = tokens; | 492 | pc.token_ids = root_struct->token_ids; |
| 493 | pc.token_locs = root_struct->token_locs; | ||
| 494 | pc.token_count = root_struct->token_count; | ||
| 495 | pc.current_token = 1; // Skip over the first (invalid) token. | ||
| 473 | return ast_parse_root(&pc); | 496 | return ast_parse_root(&pc); |
| 474 | } | 497 | } |
| 475 | 498 | ||
| 476 | // Root <- skip ContainerMembers eof | 499 | // Root <- skip ContainerMembers eof |
| 477 | static AstNode *ast_parse_root(ParseContext *pc) { | 500 | static AstNode *ast_parse_root(ParseContext *pc) { |
| 478 | Token *first = peek_token(pc); | 501 | TokenIndex first = peek_token(pc); |
| 479 | AstNodeContainerDecl members = ast_parse_container_members(pc); | 502 | AstNodeContainerDecl members = ast_parse_container_members(pc); |
| 480 | if (pc->current_token != pc->tokens->length - 1) | 503 | if (pc->current_token != pc->token_count - 1) |
| 481 | ast_invalid_token_error(pc, peek_token(pc)); | 504 | ast_invalid_token_error(pc, peek_token(pc)); |
| 482 | 505 | ||
| 483 | AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first); | 506 | AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first); |
| ... | @@ -486,70 +509,26 @@ static AstNode *ast_parse_root(ParseContext *pc) { | ... | @@ -486,70 +509,26 @@ static AstNode *ast_parse_root(ParseContext *pc) { |
| 486 | node->data.container_decl.layout = ContainerLayoutAuto; | 509 | node->data.container_decl.layout = ContainerLayoutAuto; |
| 487 | node->data.container_decl.kind = ContainerKindStruct; | 510 | node->data.container_decl.kind = ContainerKindStruct; |
| 488 | node->data.container_decl.is_root = true; | 511 | node->data.container_decl.is_root = true; |
| 489 | if (buf_len(&members.doc_comments) != 0) { | 512 | node->data.container_decl.doc_comments = members.doc_comments; |
| 490 | node->data.container_decl.doc_comments = members.doc_comments; | ||
| 491 | } | ||
| 492 | 513 | ||
| 493 | return node; | 514 | return node; |
| 494 | } | 515 | } |
| 495 | 516 | ||
| 496 | static Token *ast_parse_multiline_string_literal(ParseContext *pc, Buf *buf) { | 517 | static TokenIndex ast_parse_multi_tok(ParseContext *pc, TokenId token_id) { |
| 497 | Token *first_str_token = nullptr; | 518 | TokenIndex first_token = eat_token_if(pc, token_id); |
| 498 | Token *str_token = nullptr; | 519 | TokenIndex token = first_token; |
| 499 | while ((str_token = eat_token_if(pc, TokenIdMultilineStringLiteral))) { | 520 | while (token != 0) { |
| 500 | if (first_str_token == nullptr) { | 521 | token = eat_token_if(pc, token_id); |
| 501 | first_str_token = str_token; | ||
| 502 | } | ||
| 503 | if (buf->list.length == 0) { | ||
| 504 | buf_resize(buf, 0); | ||
| 505 | } | ||
| 506 | buf_append_buf(buf, token_buf(str_token)); | ||
| 507 | |||
| 508 | // Ignore inline comments | ||
| 509 | size_t cur_token = pc->current_token; | ||
| 510 | while (eat_token_if(pc, TokenIdDocComment)); | ||
| 511 | |||
| 512 | // Lookahead to see if there's another multilne string literal, | ||
| 513 | // if not, we have to revert back to before the doc comment | ||
| 514 | if (peek_token(pc)->id != TokenIdMultilineStringLiteral) { | ||
| 515 | pc->current_token = cur_token; | ||
| 516 | } else { | ||
| 517 | buf_append_char(buf, '\n'); // Add a newline between comments | ||
| 518 | } | ||
| 519 | } | 522 | } |
| 520 | return first_str_token; | 523 | return first_token; |
| 521 | } | 524 | } |
| 522 | 525 | ||
| 523 | static Token *ast_parse_doc_comments(ParseContext *pc, Buf *buf) { | 526 | static TokenIndex ast_parse_doc_comments(ParseContext *pc) { |
| 524 | Token *first_doc_token = nullptr; | 527 | return ast_parse_multi_tok(pc, TokenIdDocComment); |
| 525 | Token *doc_token = nullptr; | ||
| 526 | while ((doc_token = eat_token_if(pc, TokenIdDocComment))) { | ||
| 527 | if (first_doc_token == nullptr) { | ||
| 528 | first_doc_token = doc_token; | ||
| 529 | } | ||
| 530 | if (buf->list.length == 0) { | ||
| 531 | buf_resize(buf, 0); | ||
| 532 | } | ||
| 533 | // chops off '///' but leaves '\n' | ||
| 534 | buf_append_mem(buf, buf_ptr(pc->buf) + doc_token->start_pos + 3, | ||
| 535 | doc_token->end_pos - doc_token->start_pos - 3); | ||
| 536 | } | ||
| 537 | return first_doc_token; | ||
| 538 | } | 528 | } |
| 539 | 529 | ||
| 540 | static void ast_parse_container_doc_comments(ParseContext *pc, Buf *buf) { | 530 | static TokenIndex ast_parse_container_doc_comments(ParseContext *pc) { |
| 541 | if (buf_len(buf) != 0 && peek_token(pc)->id == TokenIdContainerDocComment) { | 531 | return ast_parse_multi_tok(pc, TokenIdContainerDocComment); |
| 542 | buf_append_char(buf, '\n'); | ||
| 543 | } | ||
| 544 | Token *doc_token = nullptr; | ||
| 545 | while ((doc_token = eat_token_if(pc, TokenIdContainerDocComment))) { | ||
| 546 | if (buf->list.length == 0) { | ||
| 547 | buf_resize(buf, 0); | ||
| 548 | } | ||
| 549 | // chops off '//!' but leaves '\n' | ||
| 550 | buf_append_mem(buf, buf_ptr(pc->buf) + doc_token->start_pos + 3, | ||
| 551 | doc_token->end_pos - doc_token->start_pos - 3); | ||
| 552 | } | ||
| 553 | } | 532 | } |
| 554 | 533 | ||
| 555 | enum ContainerFieldState { | 534 | enum ContainerFieldState { |
| ... | @@ -570,14 +549,11 @@ enum ContainerFieldState { | ... | @@ -570,14 +549,11 @@ enum ContainerFieldState { |
| 570 | // / | 549 | // / |
| 571 | static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { | 550 | static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { |
| 572 | AstNodeContainerDecl res = {}; | 551 | AstNodeContainerDecl res = {}; |
| 573 | Buf tld_doc_comment_buf = BUF_INIT; | ||
| 574 | buf_resize(&tld_doc_comment_buf, 0); | ||
| 575 | ContainerFieldState field_state = ContainerFieldStateNone; | 552 | ContainerFieldState field_state = ContainerFieldStateNone; |
| 576 | Token *first_token = nullptr; | 553 | TokenIndex first_token = 0; |
| 554 | res.doc_comments = ast_parse_container_doc_comments(pc); | ||
| 577 | for (;;) { | 555 | for (;;) { |
| 578 | ast_parse_container_doc_comments(pc, &tld_doc_comment_buf); | 556 | TokenIndex peeked_token = peek_token(pc); |
| 579 | |||
| 580 | Token *peeked_token = peek_token(pc); | ||
| 581 | 557 | ||
| 582 | AstNode *test_decl = ast_parse_test_decl(pc); | 558 | AstNode *test_decl = ast_parse_test_decl(pc); |
| 583 | if (test_decl != nullptr) { | 559 | if (test_decl != nullptr) { |
| ... | @@ -599,15 +575,14 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { | ... | @@ -599,15 +575,14 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { |
| 599 | continue; | 575 | continue; |
| 600 | } | 576 | } |
| 601 | 577 | ||
| 602 | Buf doc_comment_buf = BUF_INIT; | 578 | TokenIndex first_doc_token = ast_parse_doc_comments(pc); |
| 603 | ast_parse_doc_comments(pc, &doc_comment_buf); | ||
| 604 | 579 | ||
| 605 | peeked_token = peek_token(pc); | 580 | peeked_token = peek_token(pc); |
| 606 | 581 | ||
| 607 | Token *visib_token = eat_token_if(pc, TokenIdKeywordPub); | 582 | TokenIndex visib_token = eat_token_if(pc, TokenIdKeywordPub); |
| 608 | VisibMod visib_mod = visib_token != nullptr ? VisibModPub : VisibModPrivate; | 583 | VisibMod visib_mod = (visib_token != 0) ? VisibModPub : VisibModPrivate; |
| 609 | 584 | ||
| 610 | AstNode *top_level_decl = ast_parse_top_level_decl(pc, visib_mod, &doc_comment_buf); | 585 | AstNode *top_level_decl = ast_parse_top_level_decl(pc, visib_mod, first_doc_token); |
| 611 | if (top_level_decl != nullptr) { | 586 | if (top_level_decl != nullptr) { |
| 612 | if (field_state == ContainerFieldStateSeen) { | 587 | if (field_state == ContainerFieldStateSeen) { |
| 613 | field_state = ContainerFieldStateEnd; | 588 | field_state = ContainerFieldStateEnd; |
| ... | @@ -617,11 +592,11 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { | ... | @@ -617,11 +592,11 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { |
| 617 | continue; | 592 | continue; |
| 618 | } | 593 | } |
| 619 | 594 | ||
| 620 | if (visib_token != nullptr) { | 595 | if (visib_token != 0) { |
| 621 | ast_error(pc, peek_token(pc), "expected function or variable declaration after pub"); | 596 | ast_error(pc, peek_token(pc), "expected function or variable declaration after pub"); |
| 622 | } | 597 | } |
| 623 | 598 | ||
| 624 | Token *comptime_token = eat_token_if(pc, TokenIdKeywordCompTime); | 599 | TokenIndex comptime_token = eat_token_if(pc, TokenIdKeywordCompTime); |
| 625 | 600 | ||
| 626 | AstNode *container_field = ast_parse_container_field(pc); | 601 | AstNode *container_field = ast_parse_container_field(pc); |
| 627 | if (container_field != nullptr) { | 602 | if (container_field != nullptr) { |
| ... | @@ -636,10 +611,10 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { | ... | @@ -636,10 +611,10 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { |
| 636 | } | 611 | } |
| 637 | 612 | ||
| 638 | assert(container_field->type == NodeTypeStructField); | 613 | assert(container_field->type == NodeTypeStructField); |
| 639 | container_field->data.struct_field.doc_comments = doc_comment_buf; | 614 | container_field->data.struct_field.doc_comments = first_doc_token; |
| 640 | container_field->data.struct_field.comptime_token = comptime_token; | 615 | container_field->data.struct_field.comptime_token = comptime_token; |
| 641 | res.fields.append(container_field); | 616 | res.fields.append(container_field); |
| 642 | if (eat_token_if(pc, TokenIdComma) != nullptr) { | 617 | if (eat_token_if(pc, TokenIdComma) != 0) { |
| 643 | continue; | 618 | continue; |
| 644 | } else { | 619 | } else { |
| 645 | break; | 620 | break; |
| ... | @@ -648,33 +623,32 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { | ... | @@ -648,33 +623,32 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { |
| 648 | 623 | ||
| 649 | break; | 624 | break; |
| 650 | } | 625 | } |
| 651 | res.doc_comments = tld_doc_comment_buf; | ||
| 652 | return res; | 626 | return res; |
| 653 | } | 627 | } |
| 654 | 628 | ||
| 655 | // TestDecl <- KEYWORD_test STRINGLITERALSINGLE Block | 629 | // TestDecl <- KEYWORD_test STRINGLITERALSINGLE Block |
| 656 | static AstNode *ast_parse_test_decl(ParseContext *pc) { | 630 | static AstNode *ast_parse_test_decl(ParseContext *pc) { |
| 657 | Token *test = eat_token_if(pc, TokenIdKeywordTest); | 631 | TokenIndex test = eat_token_if(pc, TokenIdKeywordTest); |
| 658 | if (test == nullptr) | 632 | if (test == 0) |
| 659 | return nullptr; | 633 | return nullptr; |
| 660 | 634 | ||
| 661 | Token *name = eat_token_if(pc, TokenIdStringLiteral); | 635 | TokenIndex name = eat_token_if(pc, TokenIdStringLiteral); |
| 662 | AstNode *block = ast_expect(pc, ast_parse_block); | 636 | AstNode *block = ast_expect(pc, ast_parse_block); |
| 663 | AstNode *res = ast_create_node(pc, NodeTypeTestDecl, test); | 637 | AstNode *res = ast_create_node(pc, NodeTypeTestDecl, test); |
| 664 | res->data.test_decl.name = name ? token_buf(name) : nullptr; | 638 | res->data.test_decl.name = name ? token_buf(pc, name) : nullptr; |
| 665 | res->data.test_decl.body = block; | 639 | res->data.test_decl.body = block; |
| 666 | return res; | 640 | return res; |
| 667 | } | 641 | } |
| 668 | 642 | ||
| 669 | // TopLevelComptime <- KEYWORD_comptime BlockExpr | 643 | // TopLevelComptime <- KEYWORD_comptime BlockExpr |
| 670 | static AstNode *ast_parse_top_level_comptime(ParseContext *pc) { | 644 | static AstNode *ast_parse_top_level_comptime(ParseContext *pc) { |
| 671 | Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime); | 645 | TokenIndex comptime = eat_token_if(pc, TokenIdKeywordCompTime); |
| 672 | if (comptime == nullptr) | 646 | if (comptime == 0) |
| 673 | return nullptr; | 647 | return nullptr; |
| 674 | 648 | ||
| 675 | // 1 token lookahead because it could be a comptime struct field | 649 | // 1 token lookahead because it could be a comptime struct field |
| 676 | Token *lbrace = peek_token(pc); | 650 | TokenIndex lbrace = peek_token(pc); |
| 677 | if (lbrace->id != TokenIdLBrace) { | 651 | if (pc->token_ids[lbrace] != TokenIdLBrace) { |
| 678 | put_back_token(pc); | 652 | put_back_token(pc); |
| 679 | return nullptr; | 653 | return nullptr; |
| 680 | } | 654 | } |
| ... | @@ -689,39 +663,40 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) { | ... | @@ -689,39 +663,40 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) { |
| 689 | // <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) | 663 | // <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) |
| 690 | // / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl | 664 | // / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl |
| 691 | // / KEYWORD_use Expr SEMICOLON | 665 | // / KEYWORD_use Expr SEMICOLON |
| 692 | static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, Buf *doc_comments) { | 666 | static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, |
| 693 | Token *first = eat_token_if(pc, TokenIdKeywordExport); | 667 | TokenIndex doc_comments) |
| 694 | if (first == nullptr) | 668 | { |
| 669 | TokenIndex first = eat_token_if(pc, TokenIdKeywordExport); | ||
| 670 | if (first == 0) | ||
| 695 | first = eat_token_if(pc, TokenIdKeywordExtern); | 671 | first = eat_token_if(pc, TokenIdKeywordExtern); |
| 696 | if (first == nullptr) | 672 | if (first == 0) |
| 697 | first = eat_token_if(pc, TokenIdKeywordInline); | 673 | first = eat_token_if(pc, TokenIdKeywordInline); |
| 698 | if (first == nullptr) | 674 | if (first == 0) |
| 699 | first = eat_token_if(pc, TokenIdKeywordNoInline); | 675 | first = eat_token_if(pc, TokenIdKeywordNoInline); |
| 700 | if (first != nullptr) { | 676 | if (first != 0) { |
| 701 | Token *lib_name = nullptr; | 677 | TokenIndex lib_name = 0; |
| 702 | if (first->id == TokenIdKeywordExtern) | 678 | if (pc->token_ids[first] == TokenIdKeywordExtern) |
| 703 | lib_name = eat_token_if(pc, TokenIdStringLiteral); | 679 | lib_name = eat_token_if(pc, TokenIdStringLiteral); |
| 704 | 680 | ||
| 705 | if (first->id != TokenIdKeywordNoInline && first->id != TokenIdKeywordInline) { | 681 | if (pc->token_ids[first] != TokenIdKeywordNoInline && pc->token_ids[first] != TokenIdKeywordInline) { |
| 706 | Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); | 682 | TokenIndex thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); |
| 707 | AstNode *var_decl = ast_parse_var_decl(pc); | 683 | AstNode *var_decl = ast_parse_var_decl(pc); |
| 708 | if (var_decl != nullptr) { | 684 | if (var_decl != nullptr) { |
| 709 | assert(var_decl->type == NodeTypeVariableDeclaration); | 685 | assert(var_decl->type == NodeTypeVariableDeclaration); |
| 710 | if (first->id == TokenIdKeywordExtern && var_decl->data.variable_declaration.expr != nullptr) { | 686 | if (pc->token_ids[first] == TokenIdKeywordExtern && var_decl->data.variable_declaration.expr != nullptr) { |
| 711 | ast_error(pc, first, "extern variables have no initializers"); | 687 | ast_error(pc, first, "extern variables have no initializers"); |
| 712 | } | 688 | } |
| 713 | var_decl->line = first->start_line; | 689 | var_decl->main_token = first; |
| 714 | var_decl->column = first->start_column; | ||
| 715 | var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw; | 690 | var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw; |
| 716 | var_decl->data.variable_declaration.visib_mod = visib_mod; | 691 | var_decl->data.variable_declaration.visib_mod = visib_mod; |
| 717 | var_decl->data.variable_declaration.doc_comments = *doc_comments; | 692 | var_decl->data.variable_declaration.doc_comments = doc_comments; |
| 718 | var_decl->data.variable_declaration.is_extern = first->id == TokenIdKeywordExtern; | 693 | var_decl->data.variable_declaration.is_extern = pc->token_ids[first] == TokenIdKeywordExtern; |
| 719 | var_decl->data.variable_declaration.is_export = first->id == TokenIdKeywordExport; | 694 | var_decl->data.variable_declaration.is_export = pc->token_ids[first] == TokenIdKeywordExport; |
| 720 | var_decl->data.variable_declaration.lib_name = token_buf(lib_name); | 695 | var_decl->data.variable_declaration.lib_name = token_buf(pc, lib_name); |
| 721 | return var_decl; | 696 | return var_decl; |
| 722 | } | 697 | } |
| 723 | 698 | ||
| 724 | if (thread_local_kw != nullptr) | 699 | if (thread_local_kw != 0) |
| 725 | put_back_token(pc); | 700 | put_back_token(pc); |
| 726 | } | 701 | } |
| 727 | 702 | ||
| ... | @@ -732,14 +707,13 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B | ... | @@ -732,14 +707,13 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B |
| 732 | expect_token(pc, TokenIdSemicolon); | 707 | expect_token(pc, TokenIdSemicolon); |
| 733 | 708 | ||
| 734 | assert(fn_proto->type == NodeTypeFnProto); | 709 | assert(fn_proto->type == NodeTypeFnProto); |
| 735 | fn_proto->line = first->start_line; | 710 | fn_proto->main_token = first; |
| 736 | fn_proto->column = first->start_column; | ||
| 737 | fn_proto->data.fn_proto.visib_mod = visib_mod; | 711 | fn_proto->data.fn_proto.visib_mod = visib_mod; |
| 738 | fn_proto->data.fn_proto.doc_comments = *doc_comments; | 712 | fn_proto->data.fn_proto.doc_comments = doc_comments; |
| 739 | if (!fn_proto->data.fn_proto.is_extern) | 713 | if (!fn_proto->data.fn_proto.is_extern) |
| 740 | fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern; | 714 | fn_proto->data.fn_proto.is_extern = pc->token_ids[first] == TokenIdKeywordExtern; |
| 741 | fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport; | 715 | fn_proto->data.fn_proto.is_export = pc->token_ids[first] == TokenIdKeywordExport; |
| 742 | switch (first->id) { | 716 | switch (pc->token_ids[first]) { |
| 743 | case TokenIdKeywordInline: | 717 | case TokenIdKeywordInline: |
| 744 | fn_proto->data.fn_proto.fn_inline = FnInlineAlways; | 718 | fn_proto->data.fn_proto.fn_inline = FnInlineAlways; |
| 745 | break; | 719 | break; |
| ... | @@ -750,7 +724,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B | ... | @@ -750,7 +724,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B |
| 750 | fn_proto->data.fn_proto.fn_inline = FnInlineAuto; | 724 | fn_proto->data.fn_proto.fn_inline = FnInlineAuto; |
| 751 | break; | 725 | break; |
| 752 | } | 726 | } |
| 753 | fn_proto->data.fn_proto.lib_name = token_buf(lib_name); | 727 | fn_proto->data.fn_proto.lib_name = token_buf(pc, lib_name); |
| 754 | 728 | ||
| 755 | AstNode *res = fn_proto; | 729 | AstNode *res = fn_proto; |
| 756 | if (body != nullptr) { | 730 | if (body != nullptr) { |
| ... | @@ -769,17 +743,17 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B | ... | @@ -769,17 +743,17 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B |
| 769 | ast_invalid_token_error(pc, peek_token(pc)); | 743 | ast_invalid_token_error(pc, peek_token(pc)); |
| 770 | } | 744 | } |
| 771 | 745 | ||
| 772 | Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); | 746 | TokenIndex thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal); |
| 773 | AstNode *var_decl = ast_parse_var_decl(pc); | 747 | AstNode *var_decl = ast_parse_var_decl(pc); |
| 774 | if (var_decl != nullptr) { | 748 | if (var_decl != nullptr) { |
| 775 | assert(var_decl->type == NodeTypeVariableDeclaration); | 749 | assert(var_decl->type == NodeTypeVariableDeclaration); |
| 776 | var_decl->data.variable_declaration.visib_mod = visib_mod; | 750 | var_decl->data.variable_declaration.visib_mod = visib_mod; |
| 777 | var_decl->data.variable_declaration.doc_comments = *doc_comments; | 751 | var_decl->data.variable_declaration.doc_comments = doc_comments; |
| 778 | var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw; | 752 | var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw; |
| 779 | return var_decl; | 753 | return var_decl; |
| 780 | } | 754 | } |
| 781 | 755 | ||
| 782 | if (thread_local_kw != nullptr) | 756 | if (thread_local_kw != 0) |
| 783 | put_back_token(pc); | 757 | put_back_token(pc); |
| 784 | 758 | ||
| 785 | AstNode *fn_proto = ast_parse_fn_proto(pc); | 759 | AstNode *fn_proto = ast_parse_fn_proto(pc); |
| ... | @@ -790,7 +764,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B | ... | @@ -790,7 +764,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B |
| 790 | 764 | ||
| 791 | assert(fn_proto->type == NodeTypeFnProto); | 765 | assert(fn_proto->type == NodeTypeFnProto); |
| 792 | fn_proto->data.fn_proto.visib_mod = visib_mod; | 766 | fn_proto->data.fn_proto.visib_mod = visib_mod; |
| 793 | fn_proto->data.fn_proto.doc_comments = *doc_comments; | 767 | fn_proto->data.fn_proto.doc_comments = doc_comments; |
| 794 | AstNode *res = fn_proto; | 768 | AstNode *res = fn_proto; |
| 795 | if (body != nullptr) { | 769 | if (body != nullptr) { |
| 796 | res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto); | 770 | res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto); |
| ... | @@ -802,8 +776,8 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B | ... | @@ -802,8 +776,8 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B |
| 802 | return res; | 776 | return res; |
| 803 | } | 777 | } |
| 804 | 778 | ||
| 805 | Token *usingnamespace = eat_token_if(pc, TokenIdKeywordUsingNamespace); | 779 | TokenIndex usingnamespace = eat_token_if(pc, TokenIdKeywordUsingNamespace); |
| 806 | if (usingnamespace != nullptr) { | 780 | if (usingnamespace != 0) { |
| 807 | AstNode *expr = ast_expect(pc, ast_parse_expr); | 781 | AstNode *expr = ast_expect(pc, ast_parse_expr); |
| 808 | expect_token(pc, TokenIdSemicolon); | 782 | expect_token(pc, TokenIdSemicolon); |
| 809 | 783 | ||
| ... | @@ -818,12 +792,12 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B | ... | @@ -818,12 +792,12 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B |
| 818 | 792 | ||
| 819 | // FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_anytype / TypeExpr) | 793 | // FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_anytype / TypeExpr) |
| 820 | static AstNode *ast_parse_fn_proto(ParseContext *pc) { | 794 | static AstNode *ast_parse_fn_proto(ParseContext *pc) { |
| 821 | Token *first = eat_token_if(pc, TokenIdKeywordFn); | 795 | TokenIndex first = eat_token_if(pc, TokenIdKeywordFn); |
| 822 | if (first == nullptr) { | 796 | if (first == 0) { |
| 823 | return nullptr; | 797 | return nullptr; |
| 824 | } | 798 | } |
| 825 | 799 | ||
| 826 | Token *identifier = eat_token_if(pc, TokenIdSymbol); | 800 | TokenIndex identifier = eat_token_if(pc, TokenIdIdentifier); |
| 827 | expect_token(pc, TokenIdLParen); | 801 | expect_token(pc, TokenIdLParen); |
| 828 | ZigList<AstNode *> params = ast_parse_list(pc, TokenIdComma, ast_parse_param_decl); | 802 | ZigList<AstNode *> params = ast_parse_list(pc, TokenIdComma, ast_parse_param_decl); |
| 829 | expect_token(pc, TokenIdRParen); | 803 | expect_token(pc, TokenIdRParen); |
| ... | @@ -831,29 +805,29 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { | ... | @@ -831,29 +805,29 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { |
| 831 | AstNode *align_expr = ast_parse_byte_align(pc); | 805 | AstNode *align_expr = ast_parse_byte_align(pc); |
| 832 | AstNode *section_expr = ast_parse_link_section(pc); | 806 | AstNode *section_expr = ast_parse_link_section(pc); |
| 833 | AstNode *callconv_expr = ast_parse_callconv(pc); | 807 | AstNode *callconv_expr = ast_parse_callconv(pc); |
| 834 | Token *exmark = nullptr; | 808 | TokenIndex exmark = 0; |
| 835 | AstNode *return_type = nullptr; | 809 | AstNode *return_type = nullptr; |
| 836 | 810 | ||
| 837 | exmark = eat_token_if(pc, TokenIdBang); | 811 | exmark = eat_token_if(pc, TokenIdBang); |
| 838 | return_type = ast_parse_type_expr(pc); | 812 | return_type = ast_parse_type_expr(pc); |
| 839 | if (return_type == nullptr) { | 813 | if (return_type == nullptr) { |
| 840 | Token *next = peek_token(pc); | 814 | TokenIndex next = peek_token(pc); |
| 841 | ast_error( | 815 | ast_error( |
| 842 | pc, | 816 | pc, |
| 843 | next, | 817 | next, |
| 844 | "expected return type (use 'void' to return nothing), found: '%s'", | 818 | "expected return type (use 'void' to return nothing), found: '%s'", |
| 845 | token_name(next->id) | 819 | token_name(pc->token_ids[next]) |
| 846 | ); | 820 | ); |
| 847 | } | 821 | } |
| 848 | 822 | ||
| 849 | AstNode *res = ast_create_node(pc, NodeTypeFnProto, first); | 823 | AstNode *res = ast_create_node(pc, NodeTypeFnProto, first); |
| 850 | res->data.fn_proto = {}; | 824 | res->data.fn_proto = {}; |
| 851 | res->data.fn_proto.name = token_buf(identifier); | 825 | res->data.fn_proto.name = token_buf(pc, identifier); |
| 852 | res->data.fn_proto.params = params; | 826 | res->data.fn_proto.params = params; |
| 853 | res->data.fn_proto.align_expr = align_expr; | 827 | res->data.fn_proto.align_expr = align_expr; |
| 854 | res->data.fn_proto.section_expr = section_expr; | 828 | res->data.fn_proto.section_expr = section_expr; |
| 855 | res->data.fn_proto.callconv_expr = callconv_expr; | 829 | res->data.fn_proto.callconv_expr = callconv_expr; |
| 856 | res->data.fn_proto.auto_err_set = exmark != nullptr; | 830 | res->data.fn_proto.auto_err_set = exmark != 0; |
| 857 | res->data.fn_proto.return_type = return_type; | 831 | res->data.fn_proto.return_type = return_type; |
| 858 | 832 | ||
| 859 | for (size_t i = 0; i < params.length; i++) { | 833 | for (size_t i = 0; i < params.length; i++) { |
| ... | @@ -869,28 +843,28 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { | ... | @@ -869,28 +843,28 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { |
| 869 | 843 | ||
| 870 | // VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON | 844 | // VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON |
| 871 | static AstNode *ast_parse_var_decl(ParseContext *pc) { | 845 | static AstNode *ast_parse_var_decl(ParseContext *pc) { |
| 872 | Token *mut_kw = eat_token_if(pc, TokenIdKeywordConst); | 846 | TokenIndex mut_kw = eat_token_if(pc, TokenIdKeywordConst); |
| 873 | if (mut_kw == nullptr) | 847 | if (mut_kw == 0) |
| 874 | mut_kw = eat_token_if(pc, TokenIdKeywordVar); | 848 | mut_kw = eat_token_if(pc, TokenIdKeywordVar); |
| 875 | if (mut_kw == nullptr) | 849 | if (mut_kw == 0) |
| 876 | return nullptr; | 850 | return nullptr; |
| 877 | 851 | ||
| 878 | Token *identifier = expect_token(pc, TokenIdSymbol); | 852 | TokenIndex identifier = expect_token(pc, TokenIdIdentifier); |
| 879 | AstNode *type_expr = nullptr; | 853 | AstNode *type_expr = nullptr; |
| 880 | if (eat_token_if(pc, TokenIdColon) != nullptr) | 854 | if (eat_token_if(pc, TokenIdColon) != 0) |
| 881 | type_expr = ast_expect(pc, ast_parse_type_expr); | 855 | type_expr = ast_expect(pc, ast_parse_type_expr); |
| 882 | 856 | ||
| 883 | AstNode *align_expr = ast_parse_byte_align(pc); | 857 | AstNode *align_expr = ast_parse_byte_align(pc); |
| 884 | AstNode *section_expr = ast_parse_link_section(pc); | 858 | AstNode *section_expr = ast_parse_link_section(pc); |
| 885 | AstNode *expr = nullptr; | 859 | AstNode *expr = nullptr; |
| 886 | if (eat_token_if(pc, TokenIdEq) != nullptr) | 860 | if (eat_token_if(pc, TokenIdEq) != 0) |
| 887 | expr = ast_expect(pc, ast_parse_expr); | 861 | expr = ast_expect(pc, ast_parse_expr); |
| 888 | 862 | ||
| 889 | expect_token(pc, TokenIdSemicolon); | 863 | expect_token(pc, TokenIdSemicolon); |
| 890 | 864 | ||
| 891 | AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, mut_kw); | 865 | AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, mut_kw); |
| 892 | res->data.variable_declaration.is_const = mut_kw->id == TokenIdKeywordConst; | 866 | res->data.variable_declaration.is_const = pc->token_ids[mut_kw] == TokenIdKeywordConst; |
| 893 | res->data.variable_declaration.symbol = token_buf(identifier); | 867 | res->data.variable_declaration.symbol = token_buf(pc, identifier); |
| 894 | res->data.variable_declaration.type = type_expr; | 868 | res->data.variable_declaration.type = type_expr; |
| 895 | res->data.variable_declaration.align_expr = align_expr; | 869 | res->data.variable_declaration.align_expr = align_expr; |
| 896 | res->data.variable_declaration.section_expr = section_expr; | 870 | res->data.variable_declaration.section_expr = section_expr; |
| ... | @@ -900,14 +874,14 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { | ... | @@ -900,14 +874,14 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) { |
| 900 | 874 | ||
| 901 | // ContainerField <- KEYWORD_comptime? IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)? | 875 | // ContainerField <- KEYWORD_comptime? IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)? |
| 902 | static AstNode *ast_parse_container_field(ParseContext *pc) { | 876 | static AstNode *ast_parse_container_field(ParseContext *pc) { |
| 903 | Token *identifier = eat_token_if(pc, TokenIdSymbol); | 877 | TokenIndex identifier = eat_token_if(pc, TokenIdIdentifier); |
| 904 | if (identifier == nullptr) | 878 | if (identifier == 0) |
| 905 | return nullptr; | 879 | return nullptr; |
| 906 | 880 | ||
| 907 | AstNode *type_expr = nullptr; | 881 | AstNode *type_expr = nullptr; |
| 908 | if (eat_token_if(pc, TokenIdColon) != nullptr) { | 882 | if (eat_token_if(pc, TokenIdColon) != 0) { |
| 909 | Token *anytype_tok = eat_token_if(pc, TokenIdKeywordAnyType); | 883 | TokenIndex anytype_tok = eat_token_if(pc, TokenIdKeywordAnyType); |
| 910 | if (anytype_tok != nullptr) { | 884 | if (anytype_tok != 0) { |
| 911 | type_expr = ast_create_node(pc, NodeTypeAnyTypeField, anytype_tok); | 885 | type_expr = ast_create_node(pc, NodeTypeAnyTypeField, anytype_tok); |
| 912 | } else { | 886 | } else { |
| 913 | type_expr = ast_expect(pc, ast_parse_type_expr); | 887 | type_expr = ast_expect(pc, ast_parse_type_expr); |
| ... | @@ -915,11 +889,11 @@ static AstNode *ast_parse_container_field(ParseContext *pc) { | ... | @@ -915,11 +889,11 @@ static AstNode *ast_parse_container_field(ParseContext *pc) { |
| 915 | } | 889 | } |
| 916 | AstNode *align_expr = ast_parse_byte_align(pc); | 890 | AstNode *align_expr = ast_parse_byte_align(pc); |
| 917 | AstNode *expr = nullptr; | 891 | AstNode *expr = nullptr; |
| 918 | if (eat_token_if(pc, TokenIdEq) != nullptr) | 892 | if (eat_token_if(pc, TokenIdEq) != 0) |
| 919 | expr = ast_expect(pc, ast_parse_expr); | 893 | expr = ast_expect(pc, ast_parse_expr); |
| 920 | 894 | ||
| 921 | AstNode *res = ast_create_node(pc, NodeTypeStructField, identifier); | 895 | AstNode *res = ast_create_node(pc, NodeTypeStructField, identifier); |
| 922 | res->data.struct_field.name = token_buf(identifier); | 896 | res->data.struct_field.name = token_buf(pc, identifier); |
| 923 | res->data.struct_field.type = type_expr; | 897 | res->data.struct_field.type = type_expr; |
| 924 | res->data.struct_field.value = expr; | 898 | res->data.struct_field.value = expr; |
| 925 | res->data.struct_field.align_expr = align_expr; | 899 | res->data.struct_field.align_expr = align_expr; |
| ... | @@ -938,52 +912,52 @@ static AstNode *ast_parse_container_field(ParseContext *pc) { | ... | @@ -938,52 +912,52 @@ static AstNode *ast_parse_container_field(ParseContext *pc) { |
| 938 | // / SwitchExpr | 912 | // / SwitchExpr |
| 939 | // / AssignExpr SEMICOLON | 913 | // / AssignExpr SEMICOLON |
| 940 | static AstNode *ast_parse_statement(ParseContext *pc) { | 914 | static AstNode *ast_parse_statement(ParseContext *pc) { |
| 941 | Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime); | 915 | TokenIndex comptime = eat_token_if(pc, TokenIdKeywordCompTime); |
| 942 | AstNode *var_decl = ast_parse_var_decl(pc); | 916 | AstNode *var_decl = ast_parse_var_decl(pc); |
| 943 | if (var_decl != nullptr) { | 917 | if (var_decl != nullptr) { |
| 944 | assert(var_decl->type == NodeTypeVariableDeclaration); | 918 | assert(var_decl->type == NodeTypeVariableDeclaration); |
| 945 | var_decl->data.variable_declaration.is_comptime = comptime != nullptr; | 919 | var_decl->data.variable_declaration.is_comptime = comptime != 0; |
| 946 | return var_decl; | 920 | return var_decl; |
| 947 | } | 921 | } |
| 948 | 922 | ||
| 949 | if (comptime != nullptr) { | 923 | if (comptime != 0) { |
| 950 | AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement); | 924 | AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement); |
| 951 | AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime); | 925 | AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime); |
| 952 | res->data.comptime_expr.expr = statement; | 926 | res->data.comptime_expr.expr = statement; |
| 953 | return res; | 927 | return res; |
| 954 | } | 928 | } |
| 955 | 929 | ||
| 956 | Token *nosuspend = eat_token_if(pc, TokenIdKeywordNoSuspend); | 930 | TokenIndex nosuspend = eat_token_if(pc, TokenIdKeywordNoSuspend); |
| 957 | if (nosuspend != nullptr) { | 931 | if (nosuspend != 0) { |
| 958 | AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement); | 932 | AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement); |
| 959 | AstNode *res = ast_create_node(pc, NodeTypeNoSuspend, nosuspend); | 933 | AstNode *res = ast_create_node(pc, NodeTypeNoSuspend, nosuspend); |
| 960 | res->data.nosuspend_expr.expr = statement; | 934 | res->data.nosuspend_expr.expr = statement; |
| 961 | return res; | 935 | return res; |
| 962 | } | 936 | } |
| 963 | 937 | ||
| 964 | Token *suspend = eat_token_if(pc, TokenIdKeywordSuspend); | 938 | TokenIndex suspend = eat_token_if(pc, TokenIdKeywordSuspend); |
| 965 | if (suspend != nullptr) { | 939 | if (suspend != 0) { |
| 966 | AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement); | 940 | AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement); |
| 967 | AstNode *res = ast_create_node(pc, NodeTypeSuspend, suspend); | 941 | AstNode *res = ast_create_node(pc, NodeTypeSuspend, suspend); |
| 968 | res->data.suspend.block = statement; | 942 | res->data.suspend.block = statement; |
| 969 | return res; | 943 | return res; |
| 970 | } | 944 | } |
| 971 | 945 | ||
| 972 | Token *defer = eat_token_if(pc, TokenIdKeywordDefer); | 946 | TokenIndex defer = eat_token_if(pc, TokenIdKeywordDefer); |
| 973 | if (defer == nullptr) | 947 | if (defer == 0) |
| 974 | defer = eat_token_if(pc, TokenIdKeywordErrdefer); | 948 | defer = eat_token_if(pc, TokenIdKeywordErrdefer); |
| 975 | if (defer != nullptr) { | 949 | if (defer != 0) { |
| 976 | Token *payload = (defer->id == TokenIdKeywordErrdefer) ? | 950 | TokenIndex payload = (pc->token_ids[defer] == TokenIdKeywordErrdefer) ? |
| 977 | ast_parse_payload(pc) : nullptr; | 951 | ast_parse_payload(pc) : 0; |
| 978 | AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement); | 952 | AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement); |
| 979 | AstNode *res = ast_create_node(pc, NodeTypeDefer, defer); | 953 | AstNode *res = ast_create_node(pc, NodeTypeDefer, defer); |
| 980 | 954 | ||
| 981 | res->data.defer.kind = ReturnKindUnconditional; | 955 | res->data.defer.kind = ReturnKindUnconditional; |
| 982 | res->data.defer.expr = statement; | 956 | res->data.defer.expr = statement; |
| 983 | if (defer->id == TokenIdKeywordErrdefer) { | 957 | if (pc->token_ids[defer] == TokenIdKeywordErrdefer) { |
| 984 | res->data.defer.kind = ReturnKindError; | 958 | res->data.defer.kind = ReturnKindError; |
| 985 | if (payload != nullptr) | 959 | if (payload != 0) |
| 986 | res->data.defer.err_payload = token_symbol(pc, payload); | 960 | res->data.defer.err_payload = token_identifier(pc, payload); |
| 987 | } | 961 | } |
| 988 | return res; | 962 | return res; |
| 989 | } | 963 | } |
| ... | @@ -1025,13 +999,13 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) { | ... | @@ -1025,13 +999,13 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) { |
| 1025 | } | 999 | } |
| 1026 | 1000 | ||
| 1027 | if (body == nullptr) { | 1001 | if (body == nullptr) { |
| 1028 | Token *tok = eat_token(pc); | 1002 | TokenIndex tok = eat_token(pc); |
| 1029 | ast_error(pc, tok, "expected if body, found '%s'", token_name(tok->id)); | 1003 | ast_error(pc, tok, "expected if body, found '%s'", token_name(pc->token_ids[tok])); |
| 1030 | } | 1004 | } |
| 1031 | 1005 | ||
| 1032 | Token *err_payload = nullptr; | 1006 | TokenIndex err_payload = 0; |
| 1033 | AstNode *else_body = nullptr; | 1007 | AstNode *else_body = nullptr; |
| 1034 | if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) { | 1008 | if (eat_token_if(pc, TokenIdKeywordElse) != 0) { |
| 1035 | err_payload = ast_parse_payload(pc); | 1009 | err_payload = ast_parse_payload(pc); |
| 1036 | else_body = ast_expect(pc, ast_parse_statement); | 1010 | else_body = ast_expect(pc, ast_parse_statement); |
| 1037 | } | 1011 | } |
| ... | @@ -1040,14 +1014,14 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) { | ... | @@ -1040,14 +1014,14 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) { |
| 1040 | expect_token(pc, TokenIdSemicolon); | 1014 | expect_token(pc, TokenIdSemicolon); |
| 1041 | 1015 | ||
| 1042 | assert(res->type == NodeTypeIfOptional); | 1016 | assert(res->type == NodeTypeIfOptional); |
| 1043 | if (err_payload != nullptr) { | 1017 | if (err_payload != 0) { |
| 1044 | AstNodeTestExpr old = res->data.test_expr; | 1018 | AstNodeTestExpr old = res->data.test_expr; |
| 1045 | res->type = NodeTypeIfErrorExpr; | 1019 | res->type = NodeTypeIfErrorExpr; |
| 1046 | res->data.if_err_expr.target_node = old.target_node; | 1020 | res->data.if_err_expr.target_node = old.target_node; |
| 1047 | res->data.if_err_expr.var_is_ptr = old.var_is_ptr; | 1021 | res->data.if_err_expr.var_is_ptr = old.var_is_ptr; |
| 1048 | res->data.if_err_expr.var_symbol = old.var_symbol; | 1022 | res->data.if_err_expr.var_symbol = old.var_symbol; |
| 1049 | res->data.if_err_expr.then_node = body; | 1023 | res->data.if_err_expr.then_node = body; |
| 1050 | res->data.if_err_expr.err_symbol = token_buf(err_payload); | 1024 | res->data.if_err_expr.err_symbol = token_buf(pc, err_payload); |
| 1051 | res->data.if_err_expr.else_node = else_body; | 1025 | res->data.if_err_expr.else_node = else_body; |
| 1052 | return res; | 1026 | return res; |
| 1053 | } | 1027 | } |
| ... | @@ -1068,11 +1042,11 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) { | ... | @@ -1068,11 +1042,11 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) { |
| 1068 | 1042 | ||
| 1069 | // LabeledStatement <- BlockLabel? (Block / LoopStatement) | 1043 | // LabeledStatement <- BlockLabel? (Block / LoopStatement) |
| 1070 | static AstNode *ast_parse_labeled_statement(ParseContext *pc) { | 1044 | static AstNode *ast_parse_labeled_statement(ParseContext *pc) { |
| 1071 | Token *label = ast_parse_block_label(pc); | 1045 | TokenIndex label = ast_parse_block_label(pc); |
| 1072 | AstNode *block = ast_parse_block(pc); | 1046 | AstNode *block = ast_parse_block(pc); |
| 1073 | if (block != nullptr) { | 1047 | if (block != nullptr) { |
| 1074 | assert(block->type == NodeTypeBlock); | 1048 | assert(block->type == NodeTypeBlock); |
| 1075 | block->data.block.name = token_buf(label); | 1049 | block->data.block.name = token_buf(pc, label); |
| 1076 | return block; | 1050 | return block; |
| 1077 | } | 1051 | } |
| 1078 | 1052 | ||
| ... | @@ -1080,10 +1054,10 @@ static AstNode *ast_parse_labeled_statement(ParseContext *pc) { | ... | @@ -1080,10 +1054,10 @@ static AstNode *ast_parse_labeled_statement(ParseContext *pc) { |
| 1080 | if (loop != nullptr) { | 1054 | if (loop != nullptr) { |
| 1081 | switch (loop->type) { | 1055 | switch (loop->type) { |
| 1082 | case NodeTypeForExpr: | 1056 | case NodeTypeForExpr: |
| 1083 | loop->data.for_expr.name = token_buf(label); | 1057 | loop->data.for_expr.name = token_buf(pc, label); |
| 1084 | break; | 1058 | break; |
| 1085 | case NodeTypeWhileExpr: | 1059 | case NodeTypeWhileExpr: |
| 1086 | loop->data.while_expr.name = token_buf(label); | 1060 | loop->data.while_expr.name = token_buf(pc, label); |
| 1087 | break; | 1061 | break; |
| 1088 | default: | 1062 | default: |
| 1089 | zig_unreachable(); | 1063 | zig_unreachable(); |
| ... | @@ -1091,29 +1065,29 @@ static AstNode *ast_parse_labeled_statement(ParseContext *pc) { | ... | @@ -1091,29 +1065,29 @@ static AstNode *ast_parse_labeled_statement(ParseContext *pc) { |
| 1091 | return loop; | 1065 | return loop; |
| 1092 | } | 1066 | } |
| 1093 | 1067 | ||
| 1094 | if (label != nullptr) | 1068 | if (label != 0) |
| 1095 | ast_invalid_token_error(pc, peek_token(pc)); | 1069 | ast_invalid_token_error(pc, peek_token(pc)); |
| 1096 | return nullptr; | 1070 | return nullptr; |
| 1097 | } | 1071 | } |
| 1098 | 1072 | ||
| 1099 | // LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement) | 1073 | // LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement) |
| 1100 | static AstNode *ast_parse_loop_statement(ParseContext *pc) { | 1074 | static AstNode *ast_parse_loop_statement(ParseContext *pc) { |
| 1101 | Token *inline_token = eat_token_if(pc, TokenIdKeywordInline); | 1075 | TokenIndex inline_token = eat_token_if(pc, TokenIdKeywordInline); |
| 1102 | AstNode *for_statement = ast_parse_for_statement(pc); | 1076 | AstNode *for_statement = ast_parse_for_statement(pc); |
| 1103 | if (for_statement != nullptr) { | 1077 | if (for_statement != nullptr) { |
| 1104 | assert(for_statement->type == NodeTypeForExpr); | 1078 | assert(for_statement->type == NodeTypeForExpr); |
| 1105 | for_statement->data.for_expr.is_inline = inline_token != nullptr; | 1079 | for_statement->data.for_expr.is_inline = inline_token != 0; |
| 1106 | return for_statement; | 1080 | return for_statement; |
| 1107 | } | 1081 | } |
| 1108 | 1082 | ||
| 1109 | AstNode *while_statement = ast_parse_while_statement(pc); | 1083 | AstNode *while_statement = ast_parse_while_statement(pc); |
| 1110 | if (while_statement != nullptr) { | 1084 | if (while_statement != nullptr) { |
| 1111 | assert(while_statement->type == NodeTypeWhileExpr); | 1085 | assert(while_statement->type == NodeTypeWhileExpr); |
| 1112 | while_statement->data.while_expr.is_inline = inline_token != nullptr; | 1086 | while_statement->data.while_expr.is_inline = inline_token != 0; |
| 1113 | return while_statement; | 1087 | return while_statement; |
| 1114 | } | 1088 | } |
| 1115 | 1089 | ||
| 1116 | if (inline_token != nullptr) | 1090 | if (inline_token != 0) |
| 1117 | ast_invalid_token_error(pc, peek_token(pc)); | 1091 | ast_invalid_token_error(pc, peek_token(pc)); |
| 1118 | return nullptr; | 1092 | return nullptr; |
| 1119 | } | 1093 | } |
| ... | @@ -1134,12 +1108,12 @@ static AstNode *ast_parse_for_statement(ParseContext *pc) { | ... | @@ -1134,12 +1108,12 @@ static AstNode *ast_parse_for_statement(ParseContext *pc) { |
| 1134 | } | 1108 | } |
| 1135 | 1109 | ||
| 1136 | if (body == nullptr) { | 1110 | if (body == nullptr) { |
| 1137 | Token *tok = eat_token(pc); | 1111 | TokenIndex tok = eat_token(pc); |
| 1138 | ast_error(pc, tok, "expected loop body, found '%s'", token_name(tok->id)); | 1112 | ast_error(pc, tok, "expected loop body, found '%s'", token_name(pc->token_ids[tok])); |
| 1139 | } | 1113 | } |
| 1140 | 1114 | ||
| 1141 | AstNode *else_body = nullptr; | 1115 | AstNode *else_body = nullptr; |
| 1142 | if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) { | 1116 | if (eat_token_if(pc, TokenIdKeywordElse) != 0) { |
| 1143 | else_body = ast_expect(pc, ast_parse_statement); | 1117 | else_body = ast_expect(pc, ast_parse_statement); |
| 1144 | } | 1118 | } |
| 1145 | 1119 | ||
| ... | @@ -1168,13 +1142,13 @@ static AstNode *ast_parse_while_statement(ParseContext *pc) { | ... | @@ -1168,13 +1142,13 @@ static AstNode *ast_parse_while_statement(ParseContext *pc) { |
| 1168 | } | 1142 | } |
| 1169 | 1143 | ||
| 1170 | if (body == nullptr) { | 1144 | if (body == nullptr) { |
| 1171 | Token *tok = eat_token(pc); | 1145 | TokenIndex tok = eat_token(pc); |
| 1172 | ast_error(pc, tok, "expected loop body, found '%s'", token_name(tok->id)); | 1146 | ast_error(pc, tok, "expected loop body, found '%s'", token_name(pc->token_ids[tok])); |
| 1173 | } | 1147 | } |
| 1174 | 1148 | ||
| 1175 | Token *err_payload = nullptr; | 1149 | TokenIndex err_payload = 0; |
| 1176 | AstNode *else_body = nullptr; | 1150 | AstNode *else_body = nullptr; |
| 1177 | if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) { | 1151 | if (eat_token_if(pc, TokenIdKeywordElse) != 0) { |
| 1178 | err_payload = ast_parse_payload(pc); | 1152 | err_payload = ast_parse_payload(pc); |
| 1179 | else_body = ast_expect(pc, ast_parse_statement); | 1153 | else_body = ast_expect(pc, ast_parse_statement); |
| 1180 | } | 1154 | } |
| ... | @@ -1184,7 +1158,7 @@ static AstNode *ast_parse_while_statement(ParseContext *pc) { | ... | @@ -1184,7 +1158,7 @@ static AstNode *ast_parse_while_statement(ParseContext *pc) { |
| 1184 | 1158 | ||
| 1185 | assert(res->type == NodeTypeWhileExpr); | 1159 | assert(res->type == NodeTypeWhileExpr); |
| 1186 | res->data.while_expr.body = body; | 1160 | res->data.while_expr.body = body; |
| 1187 | res->data.while_expr.err_symbol = token_buf(err_payload); | 1161 | res->data.while_expr.err_symbol = token_buf(pc, err_payload); |
| 1188 | res->data.while_expr.else_node = else_body; | 1162 | res->data.while_expr.else_node = else_body; |
| 1189 | return res; | 1163 | return res; |
| 1190 | } | 1164 | } |
| ... | @@ -1209,11 +1183,11 @@ static AstNode *ast_parse_block_expr_statement(ParseContext *pc) { | ... | @@ -1209,11 +1183,11 @@ static AstNode *ast_parse_block_expr_statement(ParseContext *pc) { |
| 1209 | 1183 | ||
| 1210 | // BlockExpr <- BlockLabel? Block | 1184 | // BlockExpr <- BlockLabel? Block |
| 1211 | static AstNode *ast_parse_block_expr(ParseContext *pc) { | 1185 | static AstNode *ast_parse_block_expr(ParseContext *pc) { |
| 1212 | Token *label = ast_parse_block_label(pc); | 1186 | TokenIndex label = ast_parse_block_label(pc); |
| 1213 | if (label != nullptr) { | 1187 | if (label != 0) { |
| 1214 | AstNode *res = ast_expect(pc, ast_parse_block); | 1188 | AstNode *res = ast_expect(pc, ast_parse_block); |
| 1215 | assert(res->type == NodeTypeBlock); | 1189 | assert(res->type == NodeTypeBlock); |
| 1216 | res->data.block.name = token_buf(label); | 1190 | res->data.block.name = token_buf(pc, label); |
| 1217 | return res; | 1191 | return res; |
| 1218 | } | 1192 | } |
| 1219 | 1193 | ||
| ... | @@ -1230,8 +1204,8 @@ static AstNode *ast_parse_expr(ParseContext *pc) { | ... | @@ -1230,8 +1204,8 @@ static AstNode *ast_parse_expr(ParseContext *pc) { |
| 1230 | return ast_parse_prefix_op_expr( | 1204 | return ast_parse_prefix_op_expr( |
| 1231 | pc, | 1205 | pc, |
| 1232 | [](ParseContext *context) { | 1206 | [](ParseContext *context) { |
| 1233 | Token *try_token = eat_token_if(context, TokenIdKeywordTry); | 1207 | TokenIndex try_token = eat_token_if(context, TokenIdKeywordTry); |
| 1234 | if (try_token != nullptr) { | 1208 | if (try_token != 0) { |
| 1235 | AstNode *res = ast_create_node(context, NodeTypeReturnExpr, try_token); | 1209 | AstNode *res = ast_create_node(context, NodeTypeReturnExpr, try_token); |
| 1236 | res->data.return_expr.kind = ReturnKindError; | 1210 | res->data.return_expr.kind = ReturnKindError; |
| 1237 | return res; | 1211 | return res; |
| ... | @@ -1318,72 +1292,72 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) { | ... | @@ -1318,72 +1292,72 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) { |
| 1318 | if (if_expr != nullptr) | 1292 | if (if_expr != nullptr) |
| 1319 | return if_expr; | 1293 | return if_expr; |
| 1320 | 1294 | ||
| 1321 | Token *break_token = eat_token_if(pc, TokenIdKeywordBreak); | 1295 | TokenIndex break_token = eat_token_if(pc, TokenIdKeywordBreak); |
| 1322 | if (break_token != nullptr) { | 1296 | if (break_token != 0) { |
| 1323 | Token *label = ast_parse_break_label(pc); | 1297 | TokenIndex label = ast_parse_break_label(pc); |
| 1324 | AstNode *expr = ast_parse_expr(pc); | 1298 | AstNode *expr = ast_parse_expr(pc); |
| 1325 | 1299 | ||
| 1326 | AstNode *res = ast_create_node(pc, NodeTypeBreak, break_token); | 1300 | AstNode *res = ast_create_node(pc, NodeTypeBreak, break_token); |
| 1327 | res->data.break_expr.name = token_buf(label); | 1301 | res->data.break_expr.name = token_buf(pc, label); |
| 1328 | res->data.break_expr.expr = expr; | 1302 | res->data.break_expr.expr = expr; |
| 1329 | return res; | 1303 | return res; |
| 1330 | } | 1304 | } |
| 1331 | 1305 | ||
| 1332 | Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime); | 1306 | TokenIndex comptime = eat_token_if(pc, TokenIdKeywordCompTime); |
| 1333 | if (comptime != nullptr) { | 1307 | if (comptime != 0) { |
| 1334 | AstNode *expr = ast_expect(pc, ast_parse_expr); | 1308 | AstNode *expr = ast_expect(pc, ast_parse_expr); |
| 1335 | AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime); | 1309 | AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime); |
| 1336 | res->data.comptime_expr.expr = expr; | 1310 | res->data.comptime_expr.expr = expr; |
| 1337 | return res; | 1311 | return res; |
| 1338 | } | 1312 | } |
| 1339 | 1313 | ||
| 1340 | Token *nosuspend = eat_token_if(pc, TokenIdKeywordNoSuspend); | 1314 | TokenIndex nosuspend = eat_token_if(pc, TokenIdKeywordNoSuspend); |
| 1341 | if (nosuspend != nullptr) { | 1315 | if (nosuspend != 0) { |
| 1342 | AstNode *expr = ast_expect(pc, ast_parse_expr); | 1316 | AstNode *expr = ast_expect(pc, ast_parse_expr); |
| 1343 | AstNode *res = ast_create_node(pc, NodeTypeNoSuspend, nosuspend); | 1317 | AstNode *res = ast_create_node(pc, NodeTypeNoSuspend, nosuspend); |
| 1344 | res->data.nosuspend_expr.expr = expr; | 1318 | res->data.nosuspend_expr.expr = expr; |
| 1345 | return res; | 1319 | return res; |
| 1346 | } | 1320 | } |
| 1347 | 1321 | ||
| 1348 | Token *continue_token = eat_token_if(pc, TokenIdKeywordContinue); | 1322 | TokenIndex continue_token = eat_token_if(pc, TokenIdKeywordContinue); |
| 1349 | if (continue_token != nullptr) { | 1323 | if (continue_token != 0) { |
| 1350 | Token *label = ast_parse_break_label(pc); | 1324 | TokenIndex label = ast_parse_break_label(pc); |
| 1351 | AstNode *res = ast_create_node(pc, NodeTypeContinue, continue_token); | 1325 | AstNode *res = ast_create_node(pc, NodeTypeContinue, continue_token); |
| 1352 | res->data.continue_expr.name = token_buf(label); | 1326 | res->data.continue_expr.name = token_buf(pc, label); |
| 1353 | return res; | 1327 | return res; |
| 1354 | } | 1328 | } |
| 1355 | 1329 | ||
| 1356 | Token *resume = eat_token_if(pc, TokenIdKeywordResume); | 1330 | TokenIndex resume = eat_token_if(pc, TokenIdKeywordResume); |
| 1357 | if (resume != nullptr) { | 1331 | if (resume != 0) { |
| 1358 | AstNode *expr = ast_expect(pc, ast_parse_expr); | 1332 | AstNode *expr = ast_expect(pc, ast_parse_expr); |
| 1359 | AstNode *res = ast_create_node(pc, NodeTypeResume, resume); | 1333 | AstNode *res = ast_create_node(pc, NodeTypeResume, resume); |
| 1360 | res->data.resume_expr.expr = expr; | 1334 | res->data.resume_expr.expr = expr; |
| 1361 | return res; | 1335 | return res; |
| 1362 | } | 1336 | } |
| 1363 | 1337 | ||
| 1364 | Token *return_token = eat_token_if(pc, TokenIdKeywordReturn); | 1338 | TokenIndex return_token = eat_token_if(pc, TokenIdKeywordReturn); |
| 1365 | if (return_token != nullptr) { | 1339 | if (return_token != 0) { |
| 1366 | AstNode *expr = ast_parse_expr(pc); | 1340 | AstNode *expr = ast_parse_expr(pc); |
| 1367 | AstNode *res = ast_create_node(pc, NodeTypeReturnExpr, return_token); | 1341 | AstNode *res = ast_create_node(pc, NodeTypeReturnExpr, return_token); |
| 1368 | res->data.return_expr.expr = expr; | 1342 | res->data.return_expr.expr = expr; |
| 1369 | return res; | 1343 | return res; |
| 1370 | } | 1344 | } |
| 1371 | 1345 | ||
| 1372 | Token *label = ast_parse_block_label(pc); | 1346 | TokenIndex label = ast_parse_block_label(pc); |
| 1373 | AstNode *loop = ast_parse_loop_expr(pc); | 1347 | AstNode *loop = ast_parse_loop_expr(pc); |
| 1374 | if (loop != nullptr) { | 1348 | if (loop != nullptr) { |
| 1375 | switch (loop->type) { | 1349 | switch (loop->type) { |
| 1376 | case NodeTypeForExpr: | 1350 | case NodeTypeForExpr: |
| 1377 | loop->data.for_expr.name = token_buf(label); | 1351 | loop->data.for_expr.name = token_buf(pc, label); |
| 1378 | break; | 1352 | break; |
| 1379 | case NodeTypeWhileExpr: | 1353 | case NodeTypeWhileExpr: |
| 1380 | loop->data.while_expr.name = token_buf(label); | 1354 | loop->data.while_expr.name = token_buf(pc, label); |
| 1381 | break; | 1355 | break; |
| 1382 | default: | 1356 | default: |
| 1383 | zig_unreachable(); | 1357 | zig_unreachable(); |
| 1384 | } | 1358 | } |
| 1385 | return loop; | 1359 | return loop; |
| 1386 | } else if (label != nullptr) { | 1360 | } else if (label != 0) { |
| 1387 | // Restore the tokens that we eaten by ast_parse_block_label. | 1361 | // Restore the tokens that we eaten by ast_parse_block_label. |
| 1388 | put_back_token(pc); | 1362 | put_back_token(pc); |
| 1389 | put_back_token(pc); | 1363 | put_back_token(pc); |
| ... | @@ -1407,8 +1381,8 @@ static AstNode *ast_parse_if_expr(ParseContext *pc) { | ... | @@ -1407,8 +1381,8 @@ static AstNode *ast_parse_if_expr(ParseContext *pc) { |
| 1407 | 1381 | ||
| 1408 | // Block <- LBRACE Statement* RBRACE | 1382 | // Block <- LBRACE Statement* RBRACE |
| 1409 | static AstNode *ast_parse_block(ParseContext *pc) { | 1383 | static AstNode *ast_parse_block(ParseContext *pc) { |
| 1410 | Token *lbrace = eat_token_if(pc, TokenIdLBrace); | 1384 | TokenIndex lbrace = eat_token_if(pc, TokenIdLBrace); |
| 1411 | if (lbrace == nullptr) | 1385 | if (lbrace == 0) |
| 1412 | return nullptr; | 1386 | return nullptr; |
| 1413 | 1387 | ||
| 1414 | ZigList<AstNode *> statements = {}; | 1388 | ZigList<AstNode *> statements = {}; |
| ... | @@ -1462,8 +1436,8 @@ static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc) { | ... | @@ -1462,8 +1436,8 @@ static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc) { |
| 1462 | // / LBRACE Expr (COMMA Expr)* COMMA? RBRACE | 1436 | // / LBRACE Expr (COMMA Expr)* COMMA? RBRACE |
| 1463 | // / LBRACE RBRACE | 1437 | // / LBRACE RBRACE |
| 1464 | static AstNode *ast_parse_init_list(ParseContext *pc) { | 1438 | static AstNode *ast_parse_init_list(ParseContext *pc) { |
| 1465 | Token *lbrace = eat_token_if(pc, TokenIdLBrace); | 1439 | TokenIndex lbrace = eat_token_if(pc, TokenIdLBrace); |
| 1466 | if (lbrace == nullptr) | 1440 | if (lbrace == 0) |
| 1467 | return nullptr; | 1441 | return nullptr; |
| 1468 | 1442 | ||
| 1469 | AstNode *first = ast_parse_field_init(pc); | 1443 | AstNode *first = ast_parse_field_init(pc); |
| ... | @@ -1472,7 +1446,7 @@ static AstNode *ast_parse_init_list(ParseContext *pc) { | ... | @@ -1472,7 +1446,7 @@ static AstNode *ast_parse_init_list(ParseContext *pc) { |
| 1472 | res->data.container_init_expr.kind = ContainerInitKindStruct; | 1446 | res->data.container_init_expr.kind = ContainerInitKindStruct; |
| 1473 | res->data.container_init_expr.entries.append(first); | 1447 | res->data.container_init_expr.entries.append(first); |
| 1474 | 1448 | ||
| 1475 | while (eat_token_if(pc, TokenIdComma) != nullptr) { | 1449 | while (eat_token_if(pc, TokenIdComma) != 0) { |
| 1476 | AstNode *field_init = ast_parse_field_init(pc); | 1450 | AstNode *field_init = ast_parse_field_init(pc); |
| 1477 | if (field_init == nullptr) | 1451 | if (field_init == nullptr) |
| 1478 | break; | 1452 | break; |
| ... | @@ -1490,7 +1464,7 @@ static AstNode *ast_parse_init_list(ParseContext *pc) { | ... | @@ -1490,7 +1464,7 @@ static AstNode *ast_parse_init_list(ParseContext *pc) { |
| 1490 | if (first != nullptr) { | 1464 | if (first != nullptr) { |
| 1491 | res->data.container_init_expr.entries.append(first); | 1465 | res->data.container_init_expr.entries.append(first); |
| 1492 | 1466 | ||
| 1493 | while (eat_token_if(pc, TokenIdComma) != nullptr) { | 1467 | while (eat_token_if(pc, TokenIdComma) != 0) { |
| 1494 | AstNode *expr = ast_parse_expr(pc); | 1468 | AstNode *expr = ast_parse_expr(pc); |
| 1495 | if (expr == nullptr) | 1469 | if (expr == nullptr) |
| 1496 | break; | 1470 | break; |
| ... | @@ -1535,7 +1509,7 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) { | ... | @@ -1535,7 +1509,7 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) { |
| 1535 | // <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments | 1509 | // <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments |
| 1536 | // / PrimaryTypeExpr (SuffixOp / FnCallArguments)* | 1510 | // / PrimaryTypeExpr (SuffixOp / FnCallArguments)* |
| 1537 | static AstNode *ast_parse_suffix_expr(ParseContext *pc) { | 1511 | static AstNode *ast_parse_suffix_expr(ParseContext *pc) { |
| 1538 | Token *async_token = eat_token_if(pc, TokenIdKeywordAsync); | 1512 | TokenIndex async_token = eat_token_if(pc, TokenIdKeywordAsync); |
| 1539 | if (async_token) { | 1513 | if (async_token) { |
| 1540 | AstNode *child = ast_expect(pc, ast_parse_primary_type_expr); | 1514 | AstNode *child = ast_expect(pc, ast_parse_primary_type_expr); |
| 1541 | while (true) { | 1515 | while (true) { |
| ... | @@ -1652,43 +1626,21 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) { | ... | @@ -1652,43 +1626,21 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) { |
| 1652 | // / STRINGLITERAL | 1626 | // / STRINGLITERAL |
| 1653 | // / SwitchExpr | 1627 | // / SwitchExpr |
| 1654 | static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { | 1628 | static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { |
| 1655 | // TODO: This is not in line with the grammar. | 1629 | TokenIndex builtin_tok = eat_token_if(pc, TokenIdBuiltin); |
| 1656 | // Because the prev stage 1 tokenizer does not parse | 1630 | if (builtin_tok != 0) { |
| 1657 | // @[a-zA-Z_][a-zA-Z0-9_] as one token, it has to do a | ||
| 1658 | // hack, where it accepts '@' (IDENTIFIER / KEYWORD_export / | ||
| 1659 | // KEYWORD_extern). | ||
| 1660 | // I'd say that it's better if '@' is part of the builtin | ||
| 1661 | // identifier token. | ||
| 1662 | Token *at_sign = eat_token_if(pc, TokenIdAtSign); | ||
| 1663 | if (at_sign != nullptr) { | ||
| 1664 | Buf *name; | ||
| 1665 | Token *token; | ||
| 1666 | if ((token = eat_token_if(pc, TokenIdKeywordExport)) != nullptr) { | ||
| 1667 | name = buf_create_from_str("export"); | ||
| 1668 | } else if ((token = eat_token_if(pc, TokenIdKeywordExtern)) != nullptr) { | ||
| 1669 | name = buf_create_from_str("extern"); | ||
| 1670 | } else { | ||
| 1671 | token = expect_token(pc, TokenIdSymbol); | ||
| 1672 | name = token_buf(token); | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | AstNode *res = ast_expect(pc, ast_parse_fn_call_arguments); | 1631 | AstNode *res = ast_expect(pc, ast_parse_fn_call_arguments); |
| 1676 | AstNode *name_sym = ast_create_node(pc, NodeTypeSymbol, token); | 1632 | AstNode *name_sym = ast_create_node(pc, NodeTypeIdentifier, builtin_tok); |
| 1677 | name_sym->data.symbol_expr.symbol = name; | ||
| 1678 | 1633 | ||
| 1679 | assert(res->type == NodeTypeFnCallExpr); | 1634 | assert(res->type == NodeTypeFnCallExpr); |
| 1680 | res->line = at_sign->start_line; | 1635 | res->main_token = builtin_tok; |
| 1681 | res->column = at_sign->start_column; | ||
| 1682 | res->data.fn_call_expr.fn_ref_expr = name_sym; | 1636 | res->data.fn_call_expr.fn_ref_expr = name_sym; |
| 1683 | res->data.fn_call_expr.modifier = CallModifierBuiltin; | 1637 | res->data.fn_call_expr.modifier = CallModifierBuiltin; |
| 1684 | return res; | 1638 | return res; |
| 1685 | } | 1639 | } |
| 1686 | 1640 | ||
| 1687 | Token *char_lit = eat_token_if(pc, TokenIdCharLiteral); | 1641 | TokenIndex char_lit = eat_token_if(pc, TokenIdCharLiteral); |
| 1688 | if (char_lit != nullptr) { | 1642 | if (char_lit != 0) { |
| 1689 | AstNode *res = ast_create_node(pc, NodeTypeCharLiteral, char_lit); | 1643 | return ast_create_node(pc, NodeTypeCharLiteral, char_lit); |
| 1690 | res->data.char_literal.value = char_lit->data.char_lit.c; | ||
| 1691 | return res; | ||
| 1692 | } | 1644 | } |
| 1693 | 1645 | ||
| 1694 | AstNode *container_decl = ast_parse_container_decl(pc); | 1646 | AstNode *container_decl = ast_parse_container_decl(pc); |
| ... | @@ -1703,12 +1655,9 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { | ... | @@ -1703,12 +1655,9 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { |
| 1703 | if (error_set_decl != nullptr) | 1655 | if (error_set_decl != nullptr) |
| 1704 | return error_set_decl; | 1656 | return error_set_decl; |
| 1705 | 1657 | ||
| 1706 | Token *float_lit = eat_token_if(pc, TokenIdFloatLiteral); | 1658 | TokenIndex float_lit = eat_token_if(pc, TokenIdFloatLiteral); |
| 1707 | if (float_lit != nullptr) { | 1659 | if (float_lit != 0) { |
| 1708 | AstNode *res = ast_create_node(pc, NodeTypeFloatLiteral, float_lit); | 1660 | return ast_create_node(pc, NodeTypeFloatLiteral, float_lit); |
| 1709 | res->data.float_literal.bigfloat = &float_lit->data.float_lit.bigfloat; | ||
| 1710 | res->data.float_literal.overflow = float_lit->data.float_lit.overflow; | ||
| 1711 | return res; | ||
| 1712 | } | 1661 | } |
| 1713 | 1662 | ||
| 1714 | AstNode *fn_proto = ast_parse_fn_proto(pc); | 1663 | AstNode *fn_proto = ast_parse_fn_proto(pc); |
| ... | @@ -1723,86 +1672,77 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { | ... | @@ -1723,86 +1672,77 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { |
| 1723 | if (labeled_type_expr != nullptr) | 1672 | if (labeled_type_expr != nullptr) |
| 1724 | return labeled_type_expr; | 1673 | return labeled_type_expr; |
| 1725 | 1674 | ||
| 1726 | Token *identifier = eat_token_if(pc, TokenIdSymbol); | 1675 | TokenIndex identifier = eat_token_if(pc, TokenIdIdentifier); |
| 1727 | if (identifier != nullptr) | 1676 | if (identifier != 0) |
| 1728 | return token_symbol(pc, identifier); | 1677 | return token_identifier(pc, identifier); |
| 1729 | 1678 | ||
| 1730 | AstNode *if_type_expr = ast_parse_if_type_expr(pc); | 1679 | AstNode *if_type_expr = ast_parse_if_type_expr(pc); |
| 1731 | if (if_type_expr != nullptr) | 1680 | if (if_type_expr != nullptr) |
| 1732 | return if_type_expr; | 1681 | return if_type_expr; |
| 1733 | 1682 | ||
| 1734 | Token *int_lit = eat_token_if(pc, TokenIdIntLiteral); | 1683 | TokenIndex int_lit = eat_token_if(pc, TokenIdIntLiteral); |
| 1735 | if (int_lit != nullptr) { | 1684 | if (int_lit != 0) { |
| 1736 | AstNode *res = ast_create_node(pc, NodeTypeIntLiteral, int_lit); | 1685 | return ast_create_node(pc, NodeTypeIntLiteral, int_lit); |
| 1737 | res->data.int_literal.bigint = &int_lit->data.int_lit.bigint; | ||
| 1738 | return res; | ||
| 1739 | } | 1686 | } |
| 1740 | 1687 | ||
| 1741 | Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime); | 1688 | TokenIndex comptime = eat_token_if(pc, TokenIdKeywordCompTime); |
| 1742 | if (comptime != nullptr) { | 1689 | if (comptime != 0) { |
| 1743 | AstNode *expr = ast_expect(pc, ast_parse_type_expr); | 1690 | AstNode *expr = ast_expect(pc, ast_parse_type_expr); |
| 1744 | AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime); | 1691 | AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime); |
| 1745 | res->data.comptime_expr.expr = expr; | 1692 | res->data.comptime_expr.expr = expr; |
| 1746 | return res; | 1693 | return res; |
| 1747 | } | 1694 | } |
| 1748 | 1695 | ||
| 1749 | Token *error = eat_token_if(pc, TokenIdKeywordError); | 1696 | TokenIndex error = eat_token_if(pc, TokenIdKeywordError); |
| 1750 | if (error != nullptr) { | 1697 | if (error != 0) { |
| 1751 | Token *dot = expect_token(pc, TokenIdDot); | 1698 | TokenIndex dot = expect_token(pc, TokenIdDot); |
| 1752 | Token *name = expect_token(pc, TokenIdSymbol); | 1699 | TokenIndex name = expect_token(pc, TokenIdIdentifier); |
| 1753 | AstNode *left = ast_create_node(pc, NodeTypeErrorType, error); | 1700 | AstNode *left = ast_create_node(pc, NodeTypeErrorType, error); |
| 1754 | AstNode *res = ast_create_node(pc, NodeTypeFieldAccessExpr, dot); | 1701 | AstNode *res = ast_create_node(pc, NodeTypeFieldAccessExpr, dot); |
| 1755 | res->data.field_access_expr.struct_expr = left; | 1702 | res->data.field_access_expr.struct_expr = left; |
| 1756 | res->data.field_access_expr.field_name = token_buf(name); | 1703 | res->data.field_access_expr.field_name = token_buf(pc, name); |
| 1757 | return res; | 1704 | return res; |
| 1758 | } | 1705 | } |
| 1759 | 1706 | ||
| 1760 | Token *false_token = eat_token_if(pc, TokenIdKeywordFalse); | 1707 | TokenIndex false_token = eat_token_if(pc, TokenIdKeywordFalse); |
| 1761 | if (false_token != nullptr) { | 1708 | if (false_token != 0) { |
| 1762 | AstNode *res = ast_create_node(pc, NodeTypeBoolLiteral, false_token); | 1709 | AstNode *res = ast_create_node(pc, NodeTypeBoolLiteral, false_token); |
| 1763 | res->data.bool_literal.value = false; | 1710 | res->data.bool_literal.value = false; |
| 1764 | return res; | 1711 | return res; |
| 1765 | } | 1712 | } |
| 1766 | 1713 | ||
| 1767 | Token *null = eat_token_if(pc, TokenIdKeywordNull); | 1714 | TokenIndex null = eat_token_if(pc, TokenIdKeywordNull); |
| 1768 | if (null != nullptr) | 1715 | if (null != 0) |
| 1769 | return ast_create_node(pc, NodeTypeNullLiteral, null); | 1716 | return ast_create_node(pc, NodeTypeNullLiteral, null); |
| 1770 | 1717 | ||
| 1771 | Token *anyframe = eat_token_if(pc, TokenIdKeywordAnyFrame); | 1718 | TokenIndex anyframe = eat_token_if(pc, TokenIdKeywordAnyFrame); |
| 1772 | if (anyframe != nullptr) | 1719 | if (anyframe != 0) |
| 1773 | return ast_create_node(pc, NodeTypeAnyFrameType, anyframe); | 1720 | return ast_create_node(pc, NodeTypeAnyFrameType, anyframe); |
| 1774 | 1721 | ||
| 1775 | Token *true_token = eat_token_if(pc, TokenIdKeywordTrue); | 1722 | TokenIndex true_token = eat_token_if(pc, TokenIdKeywordTrue); |
| 1776 | if (true_token != nullptr) { | 1723 | if (true_token != 0) { |
| 1777 | AstNode *res = ast_create_node(pc, NodeTypeBoolLiteral, true_token); | 1724 | AstNode *res = ast_create_node(pc, NodeTypeBoolLiteral, true_token); |
| 1778 | res->data.bool_literal.value = true; | 1725 | res->data.bool_literal.value = true; |
| 1779 | return res; | 1726 | return res; |
| 1780 | } | 1727 | } |
| 1781 | 1728 | ||
| 1782 | Token *undefined = eat_token_if(pc, TokenIdKeywordUndefined); | 1729 | TokenIndex undefined = eat_token_if(pc, TokenIdKeywordUndefined); |
| 1783 | if (undefined != nullptr) | 1730 | if (undefined != 0) |
| 1784 | return ast_create_node(pc, NodeTypeUndefinedLiteral, undefined); | 1731 | return ast_create_node(pc, NodeTypeUndefinedLiteral, undefined); |
| 1785 | 1732 | ||
| 1786 | Token *unreachable = eat_token_if(pc, TokenIdKeywordUnreachable); | 1733 | TokenIndex unreachable = eat_token_if(pc, TokenIdKeywordUnreachable); |
| 1787 | if (unreachable != nullptr) | 1734 | if (unreachable != 0) |
| 1788 | return ast_create_node(pc, NodeTypeUnreachable, unreachable); | 1735 | return ast_create_node(pc, NodeTypeUnreachable, unreachable); |
| 1789 | 1736 | ||
| 1790 | 1737 | ||
| 1791 | Buf *string_buf; | 1738 | TokenIndex string_lit = eat_token_if(pc, TokenIdStringLiteral); |
| 1792 | Token *string_lit = eat_token_if(pc, TokenIdStringLiteral); | 1739 | if (string_lit != 0) { |
| 1793 | if (string_lit != nullptr) { | 1740 | return ast_create_node(pc, NodeTypeStringLiteral, string_lit); |
| 1794 | string_buf = token_buf(string_lit); | ||
| 1795 | } else { | ||
| 1796 | Buf multiline_string_buf = BUF_INIT; | ||
| 1797 | string_lit = ast_parse_multiline_string_literal(pc, &multiline_string_buf); | ||
| 1798 | if (string_lit != nullptr) { | ||
| 1799 | string_buf = buf_create_from_buf(&multiline_string_buf); | ||
| 1800 | } | ||
| 1801 | } | 1741 | } |
| 1802 | if (string_lit != nullptr) { | 1742 | |
| 1803 | AstNode *res = ast_create_node(pc, NodeTypeStringLiteral, string_lit); | 1743 | TokenIndex multiline_str_lit = ast_parse_multi_tok(pc, TokenIdMultilineStringLiteralLine); |
| 1804 | res->data.string_literal.buf = string_buf; | 1744 | if (multiline_str_lit != 0) { |
| 1805 | return res; | 1745 | return ast_create_node(pc, NodeTypeStringLiteral, multiline_str_lit); |
| 1806 | } | 1746 | } |
| 1807 | 1747 | ||
| 1808 | AstNode *switch_expr = ast_parse_switch_expr(pc); | 1748 | AstNode *switch_expr = ast_parse_switch_expr(pc); |
| ... | @@ -1814,22 +1754,21 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { | ... | @@ -1814,22 +1754,21 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { |
| 1814 | 1754 | ||
| 1815 | // ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto | 1755 | // ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto |
| 1816 | static AstNode *ast_parse_container_decl(ParseContext *pc) { | 1756 | static AstNode *ast_parse_container_decl(ParseContext *pc) { |
| 1817 | Token *layout_token = eat_token_if(pc, TokenIdKeywordExtern); | 1757 | TokenIndex layout_token = eat_token_if(pc, TokenIdKeywordExtern); |
| 1818 | if (layout_token == nullptr) | 1758 | if (layout_token == 0) |
| 1819 | layout_token = eat_token_if(pc, TokenIdKeywordPacked); | 1759 | layout_token = eat_token_if(pc, TokenIdKeywordPacked); |
| 1820 | 1760 | ||
| 1821 | AstNode *res = ast_parse_container_decl_auto(pc); | 1761 | AstNode *res = ast_parse_container_decl_auto(pc); |
| 1822 | if (res == nullptr) { | 1762 | if (res == nullptr) { |
| 1823 | if (layout_token != nullptr) | 1763 | if (layout_token != 0) |
| 1824 | put_back_token(pc); | 1764 | put_back_token(pc); |
| 1825 | return nullptr; | 1765 | return nullptr; |
| 1826 | } | 1766 | } |
| 1827 | 1767 | ||
| 1828 | assert(res->type == NodeTypeContainerDecl); | 1768 | assert(res->type == NodeTypeContainerDecl); |
| 1829 | if (layout_token != nullptr) { | 1769 | if (layout_token != 0) { |
| 1830 | res->line = layout_token->start_line; | 1770 | res->main_token = layout_token; |
| 1831 | res->column = layout_token->start_column; | 1771 | res->data.container_decl.layout = pc->token_ids[layout_token] == TokenIdKeywordExtern |
| 1832 | res->data.container_decl.layout = layout_token->id == TokenIdKeywordExtern | ||
| 1833 | ? ContainerLayoutExtern | 1772 | ? ContainerLayoutExtern |
| 1834 | : ContainerLayoutPacked; | 1773 | : ContainerLayoutPacked; |
| 1835 | } | 1774 | } |
| ... | @@ -1838,28 +1777,27 @@ static AstNode *ast_parse_container_decl(ParseContext *pc) { | ... | @@ -1838,28 +1777,27 @@ static AstNode *ast_parse_container_decl(ParseContext *pc) { |
| 1838 | 1777 | ||
| 1839 | // ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE | 1778 | // ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE |
| 1840 | static AstNode *ast_parse_error_set_decl(ParseContext *pc) { | 1779 | static AstNode *ast_parse_error_set_decl(ParseContext *pc) { |
| 1841 | Token *first = eat_token_if(pc, TokenIdKeywordError); | 1780 | TokenIndex first = eat_token_if(pc, TokenIdKeywordError); |
| 1842 | if (first == nullptr) | 1781 | if (first == 0) |
| 1843 | return nullptr; | 1782 | return nullptr; |
| 1844 | if (eat_token_if(pc, TokenIdLBrace) == nullptr) { | 1783 | if (eat_token_if(pc, TokenIdLBrace) == 0) { |
| 1845 | put_back_token(pc); | 1784 | put_back_token(pc); |
| 1846 | return nullptr; | 1785 | return nullptr; |
| 1847 | } | 1786 | } |
| 1848 | 1787 | ||
| 1849 | ZigList<AstNode *> decls = ast_parse_list<AstNode>(pc, TokenIdComma, [](ParseContext *context) { | 1788 | ZigList<AstNode *> decls = ast_parse_list<AstNode>(pc, TokenIdComma, [](ParseContext *context) { |
| 1850 | Buf doc_comment_buf = BUF_INIT; | 1789 | TokenIndex doc_token = ast_parse_doc_comments(context); |
| 1851 | Token *doc_token = ast_parse_doc_comments(context, &doc_comment_buf); | 1790 | TokenIndex ident = eat_token_if(context, TokenIdIdentifier); |
| 1852 | Token *ident = eat_token_if(context, TokenIdSymbol); | 1791 | if (ident == 0) |
| 1853 | if (ident == nullptr) | ||
| 1854 | return (AstNode*)nullptr; | 1792 | return (AstNode*)nullptr; |
| 1855 | 1793 | ||
| 1856 | AstNode *symbol_node = token_symbol(context, ident); | 1794 | AstNode *symbol_node = token_identifier(context, ident); |
| 1857 | if (doc_token == nullptr) | 1795 | if (doc_token == 0) |
| 1858 | return symbol_node; | 1796 | return symbol_node; |
| 1859 | 1797 | ||
| 1860 | AstNode *field_node = ast_create_node(context, NodeTypeErrorSetField, doc_token); | 1798 | AstNode *field_node = ast_create_node(context, NodeTypeErrorSetField, doc_token); |
| 1861 | field_node->data.err_set_field.field_name = symbol_node; | 1799 | field_node->data.err_set_field.field_name = symbol_node; |
| 1862 | field_node->data.err_set_field.doc_comments = doc_comment_buf; | 1800 | field_node->data.err_set_field.doc_comments = doc_token; |
| 1863 | return field_node; | 1801 | return field_node; |
| 1864 | }); | 1802 | }); |
| 1865 | expect_token(pc, TokenIdRBrace); | 1803 | expect_token(pc, TokenIdRBrace); |
| ... | @@ -1871,8 +1809,8 @@ static AstNode *ast_parse_error_set_decl(ParseContext *pc) { | ... | @@ -1871,8 +1809,8 @@ static AstNode *ast_parse_error_set_decl(ParseContext *pc) { |
| 1871 | 1809 | ||
| 1872 | // GroupedExpr <- LPAREN Expr RPAREN | 1810 | // GroupedExpr <- LPAREN Expr RPAREN |
| 1873 | static AstNode *ast_parse_grouped_expr(ParseContext *pc) { | 1811 | static AstNode *ast_parse_grouped_expr(ParseContext *pc) { |
| 1874 | Token *lparen = eat_token_if(pc, TokenIdLParen); | 1812 | TokenIndex lparen = eat_token_if(pc, TokenIdLParen); |
| 1875 | if (lparen == nullptr) | 1813 | if (lparen == 0) |
| 1876 | return nullptr; | 1814 | return nullptr; |
| 1877 | 1815 | ||
| 1878 | AstNode *expr = ast_expect(pc, ast_parse_expr); | 1816 | AstNode *expr = ast_expect(pc, ast_parse_expr); |
| ... | @@ -1892,12 +1830,12 @@ static AstNode *ast_parse_if_type_expr(ParseContext *pc) { | ... | @@ -1892,12 +1830,12 @@ static AstNode *ast_parse_if_type_expr(ParseContext *pc) { |
| 1892 | // <- BlockLabel Block | 1830 | // <- BlockLabel Block |
| 1893 | // / BlockLabel? LoopTypeExpr | 1831 | // / BlockLabel? LoopTypeExpr |
| 1894 | static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) { | 1832 | static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) { |
| 1895 | Token *label = ast_parse_block_label(pc); | 1833 | TokenIndex label = ast_parse_block_label(pc); |
| 1896 | if (label != nullptr) { | 1834 | if (label != 0) { |
| 1897 | AstNode *block = ast_parse_block(pc); | 1835 | AstNode *block = ast_parse_block(pc); |
| 1898 | if (block != nullptr) { | 1836 | if (block != nullptr) { |
| 1899 | assert(block->type == NodeTypeBlock); | 1837 | assert(block->type == NodeTypeBlock); |
| 1900 | block->data.block.name = token_buf(label); | 1838 | block->data.block.name = token_buf(pc, label); |
| 1901 | return block; | 1839 | return block; |
| 1902 | } | 1840 | } |
| 1903 | } | 1841 | } |
| ... | @@ -1906,10 +1844,10 @@ static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) { | ... | @@ -1906,10 +1844,10 @@ static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) { |
| 1906 | if (loop != nullptr) { | 1844 | if (loop != nullptr) { |
| 1907 | switch (loop->type) { | 1845 | switch (loop->type) { |
| 1908 | case NodeTypeForExpr: | 1846 | case NodeTypeForExpr: |
| 1909 | loop->data.for_expr.name = token_buf(label); | 1847 | loop->data.for_expr.name = token_buf(pc, label); |
| 1910 | break; | 1848 | break; |
| 1911 | case NodeTypeWhileExpr: | 1849 | case NodeTypeWhileExpr: |
| 1912 | loop->data.while_expr.name = token_buf(label); | 1850 | loop->data.while_expr.name = token_buf(pc, label); |
| 1913 | break; | 1851 | break; |
| 1914 | default: | 1852 | default: |
| 1915 | zig_unreachable(); | 1853 | zig_unreachable(); |
| ... | @@ -1917,7 +1855,7 @@ static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) { | ... | @@ -1917,7 +1855,7 @@ static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) { |
| 1917 | return loop; | 1855 | return loop; |
| 1918 | } | 1856 | } |
| 1919 | 1857 | ||
| 1920 | if (label != nullptr) { | 1858 | if (label != 0) { |
| 1921 | put_back_token(pc); | 1859 | put_back_token(pc); |
| 1922 | put_back_token(pc); | 1860 | put_back_token(pc); |
| 1923 | } | 1861 | } |
| ... | @@ -1945,8 +1883,8 @@ static AstNode *ast_parse_while_type_expr(ParseContext *pc) { | ... | @@ -1945,8 +1883,8 @@ static AstNode *ast_parse_while_type_expr(ParseContext *pc) { |
| 1945 | 1883 | ||
| 1946 | // SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE | 1884 | // SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE |
| 1947 | static AstNode *ast_parse_switch_expr(ParseContext *pc) { | 1885 | static AstNode *ast_parse_switch_expr(ParseContext *pc) { |
| 1948 | Token *switch_token = eat_token_if(pc, TokenIdKeywordSwitch); | 1886 | TokenIndex switch_token = eat_token_if(pc, TokenIdKeywordSwitch); |
| 1949 | if (switch_token == nullptr) | 1887 | if (switch_token == 0) |
| 1950 | return nullptr; | 1888 | return nullptr; |
| 1951 | 1889 | ||
| 1952 | expect_token(pc, TokenIdLParen); | 1890 | expect_token(pc, TokenIdLParen); |
| ... | @@ -1964,11 +1902,11 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc) { | ... | @@ -1964,11 +1902,11 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc) { |
| 1964 | 1902 | ||
| 1965 | // AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN STRINGLITERAL AsmOutput? RPAREN | 1903 | // AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN STRINGLITERAL AsmOutput? RPAREN |
| 1966 | static AstNode *ast_parse_asm_expr(ParseContext *pc) { | 1904 | static AstNode *ast_parse_asm_expr(ParseContext *pc) { |
| 1967 | Token *asm_token = eat_token_if(pc, TokenIdKeywordAsm); | 1905 | TokenIndex asm_token = eat_token_if(pc, TokenIdKeywordAsm); |
| 1968 | if (asm_token == nullptr) | 1906 | if (asm_token == 0) |
| 1969 | return nullptr; | 1907 | return nullptr; |
| 1970 | 1908 | ||
| 1971 | Token *volatile_token = eat_token_if(pc, TokenIdKeywordVolatile); | 1909 | TokenIndex volatile_token = eat_token_if(pc, TokenIdKeywordVolatile); |
| 1972 | expect_token(pc, TokenIdLParen); | 1910 | expect_token(pc, TokenIdLParen); |
| 1973 | AstNode *asm_template = ast_expect(pc, ast_parse_expr); | 1911 | AstNode *asm_template = ast_expect(pc, ast_parse_expr); |
| 1974 | AstNode *res = ast_parse_asm_output(pc); | 1912 | AstNode *res = ast_parse_asm_output(pc); |
| ... | @@ -1976,25 +1914,21 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc) { | ... | @@ -1976,25 +1914,21 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc) { |
| 1976 | res = ast_create_node_no_line_info(pc, NodeTypeAsmExpr); | 1914 | res = ast_create_node_no_line_info(pc, NodeTypeAsmExpr); |
| 1977 | expect_token(pc, TokenIdRParen); | 1915 | expect_token(pc, TokenIdRParen); |
| 1978 | 1916 | ||
| 1979 | res->line = asm_token->start_line; | 1917 | res->main_token = asm_token; |
| 1980 | res->column = asm_token->start_column; | ||
| 1981 | res->data.asm_expr.volatile_token = volatile_token; | 1918 | res->data.asm_expr.volatile_token = volatile_token; |
| 1982 | res->data.asm_expr.asm_template = asm_template; | 1919 | res->data.asm_expr.asm_template = asm_template; |
| 1983 | return res; | 1920 | return res; |
| 1984 | } | 1921 | } |
| 1985 | 1922 | ||
| 1986 | static AstNode *ast_parse_anon_lit(ParseContext *pc) { | 1923 | static AstNode *ast_parse_anon_lit(ParseContext *pc) { |
| 1987 | Token *period = eat_token_if(pc, TokenIdDot); | 1924 | TokenIndex period = eat_token_if(pc, TokenIdDot); |
| 1988 | if (period == nullptr) | 1925 | if (period == 0) |
| 1989 | return nullptr; | 1926 | return nullptr; |
| 1990 | 1927 | ||
| 1991 | // anon enum literal | 1928 | // anon enum literal |
| 1992 | Token *identifier = eat_token_if(pc, TokenIdSymbol); | 1929 | TokenIndex identifier = eat_token_if(pc, TokenIdIdentifier); |
| 1993 | if (identifier != nullptr) { | 1930 | if (identifier != 0) { |
| 1994 | AstNode *res = ast_create_node(pc, NodeTypeEnumLiteral, period); | 1931 | return ast_create_node(pc, NodeTypeEnumLiteral, period); |
| 1995 | res->data.enum_literal.period = period; | ||
| 1996 | res->data.enum_literal.identifier = identifier; | ||
| 1997 | return res; | ||
| 1998 | } | 1932 | } |
| 1999 | 1933 | ||
| 2000 | // anon container literal | 1934 | // anon container literal |
| ... | @@ -2007,7 +1941,7 @@ static AstNode *ast_parse_anon_lit(ParseContext *pc) { | ... | @@ -2007,7 +1941,7 @@ static AstNode *ast_parse_anon_lit(ParseContext *pc) { |
| 2007 | 1941 | ||
| 2008 | // AsmOutput <- COLON AsmOutputList AsmInput? | 1942 | // AsmOutput <- COLON AsmOutputList AsmInput? |
| 2009 | static AstNode *ast_parse_asm_output(ParseContext *pc) { | 1943 | static AstNode *ast_parse_asm_output(ParseContext *pc) { |
| 2010 | if (eat_token_if(pc, TokenIdColon) == nullptr) | 1944 | if (eat_token_if(pc, TokenIdColon) == 0) |
| 2011 | return nullptr; | 1945 | return nullptr; |
| 2012 | 1946 | ||
| 2013 | ZigList<AsmOutput *> output_list = ast_parse_list(pc, TokenIdComma, ast_parse_asm_output_item); | 1947 | ZigList<AsmOutput *> output_list = ast_parse_list(pc, TokenIdComma, ast_parse_asm_output_item); |
| ... | @@ -2021,20 +1955,20 @@ static AstNode *ast_parse_asm_output(ParseContext *pc) { | ... | @@ -2021,20 +1955,20 @@ static AstNode *ast_parse_asm_output(ParseContext *pc) { |
| 2021 | 1955 | ||
| 2022 | // AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN | 1956 | // AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN |
| 2023 | static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) { | 1957 | static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) { |
| 2024 | if (eat_token_if(pc, TokenIdLBracket) == nullptr) | 1958 | if (eat_token_if(pc, TokenIdLBracket) == 0) |
| 2025 | return nullptr; | 1959 | return nullptr; |
| 2026 | 1960 | ||
| 2027 | Token *sym_name = expect_token(pc, TokenIdSymbol); | 1961 | TokenIndex sym_name = expect_token(pc, TokenIdIdentifier); |
| 2028 | expect_token(pc, TokenIdRBracket); | 1962 | expect_token(pc, TokenIdRBracket); |
| 2029 | 1963 | ||
| 2030 | Token *str = eat_token_if(pc, TokenIdMultilineStringLiteral); | 1964 | TokenIndex str = ast_parse_multi_tok(pc, TokenIdMultilineStringLiteralLine); |
| 2031 | if (str == nullptr) | 1965 | if (str == 0) |
| 2032 | str = expect_token(pc, TokenIdStringLiteral); | 1966 | str = expect_token(pc, TokenIdStringLiteral); |
| 2033 | expect_token(pc, TokenIdLParen); | 1967 | expect_token(pc, TokenIdLParen); |
| 2034 | 1968 | ||
| 2035 | Token *var_name = eat_token_if(pc, TokenIdSymbol); | 1969 | TokenIndex var_name = eat_token_if(pc, TokenIdIdentifier); |
| 2036 | AstNode *return_type = nullptr; | 1970 | AstNode *return_type = nullptr; |
| 2037 | if (var_name == nullptr) { | 1971 | if (var_name == 0) { |
| 2038 | expect_token(pc, TokenIdArrow); | 1972 | expect_token(pc, TokenIdArrow); |
| 2039 | return_type = ast_expect(pc, ast_parse_type_expr); | 1973 | return_type = ast_expect(pc, ast_parse_type_expr); |
| 2040 | } | 1974 | } |
| ... | @@ -2042,16 +1976,16 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) { | ... | @@ -2042,16 +1976,16 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) { |
| 2042 | expect_token(pc, TokenIdRParen); | 1976 | expect_token(pc, TokenIdRParen); |
| 2043 | 1977 | ||
| 2044 | AsmOutput *res = heap::c_allocator.create<AsmOutput>(); | 1978 | AsmOutput *res = heap::c_allocator.create<AsmOutput>(); |
| 2045 | res->asm_symbolic_name = token_buf(sym_name); | 1979 | res->asm_symbolic_name = token_buf(pc, sym_name); |
| 2046 | res->constraint = token_buf(str); | 1980 | res->constraint = token_buf(pc, str); |
| 2047 | res->variable_name = token_buf(var_name); | 1981 | res->variable_name = token_buf(pc, var_name); |
| 2048 | res->return_type = return_type; | 1982 | res->return_type = return_type; |
| 2049 | return res; | 1983 | return res; |
| 2050 | } | 1984 | } |
| 2051 | 1985 | ||
| 2052 | // AsmInput <- COLON AsmInputList AsmClobbers? | 1986 | // AsmInput <- COLON AsmInputList AsmClobbers? |
| 2053 | static AstNode *ast_parse_asm_input(ParseContext *pc) { | 1987 | static AstNode *ast_parse_asm_input(ParseContext *pc) { |
| 2054 | if (eat_token_if(pc, TokenIdColon) == nullptr) | 1988 | if (eat_token_if(pc, TokenIdColon) == 0) |
| 2055 | return nullptr; | 1989 | return nullptr; |
| 2056 | 1990 | ||
| 2057 | ZigList<AsmInput *> input_list = ast_parse_list(pc, TokenIdComma, ast_parse_asm_input_item); | 1991 | ZigList<AsmInput *> input_list = ast_parse_list(pc, TokenIdComma, ast_parse_asm_input_item); |
| ... | @@ -2065,37 +1999,35 @@ static AstNode *ast_parse_asm_input(ParseContext *pc) { | ... | @@ -2065,37 +1999,35 @@ static AstNode *ast_parse_asm_input(ParseContext *pc) { |
| 2065 | 1999 | ||
| 2066 | // AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN | 2000 | // AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN |
| 2067 | static AsmInput *ast_parse_asm_input_item(ParseContext *pc) { | 2001 | static AsmInput *ast_parse_asm_input_item(ParseContext *pc) { |
| 2068 | if (eat_token_if(pc, TokenIdLBracket) == nullptr) | 2002 | if (eat_token_if(pc, TokenIdLBracket) == 0) |
| 2069 | return nullptr; | 2003 | return nullptr; |
| 2070 | 2004 | ||
| 2071 | Token *sym_name = expect_token(pc, TokenIdSymbol); | 2005 | TokenIndex sym_name = expect_token(pc, TokenIdIdentifier); |
| 2072 | expect_token(pc, TokenIdRBracket); | 2006 | expect_token(pc, TokenIdRBracket); |
| 2073 | 2007 | ||
| 2074 | Token *constraint = eat_token_if(pc, TokenIdMultilineStringLiteral); | 2008 | TokenIndex constraint = expect_token(pc, TokenIdStringLiteral); |
| 2075 | if (constraint == nullptr) | ||
| 2076 | constraint = expect_token(pc, TokenIdStringLiteral); | ||
| 2077 | expect_token(pc, TokenIdLParen); | 2009 | expect_token(pc, TokenIdLParen); |
| 2078 | AstNode *expr = ast_expect(pc, ast_parse_expr); | 2010 | AstNode *expr = ast_expect(pc, ast_parse_expr); |
| 2079 | expect_token(pc, TokenIdRParen); | 2011 | expect_token(pc, TokenIdRParen); |
| 2080 | 2012 | ||
| 2081 | AsmInput *res = heap::c_allocator.create<AsmInput>(); | 2013 | AsmInput *res = heap::c_allocator.create<AsmInput>(); |
| 2082 | res->asm_symbolic_name = token_buf(sym_name); | 2014 | res->asm_symbolic_name = token_buf(pc, sym_name); |
| 2083 | res->constraint = token_buf(constraint); | 2015 | res->constraint = token_buf(pc, constraint); |
| 2084 | res->expr = expr; | 2016 | res->expr = expr; |
| 2085 | return res; | 2017 | return res; |
| 2086 | } | 2018 | } |
| 2087 | 2019 | ||
| 2088 | // AsmClobbers <- COLON StringList | 2020 | // AsmClobbers <- COLON StringList |
| 2089 | static AstNode *ast_parse_asm_clobbers(ParseContext *pc) { | 2021 | static AstNode *ast_parse_asm_clobbers(ParseContext *pc) { |
| 2090 | if (eat_token_if(pc, TokenIdColon) == nullptr) | 2022 | if (eat_token_if(pc, TokenIdColon) == 0) |
| 2091 | return nullptr; | 2023 | return nullptr; |
| 2092 | 2024 | ||
| 2093 | ZigList<Buf *> clobber_list = ast_parse_list<Buf>(pc, TokenIdComma, [](ParseContext *context) { | 2025 | ZigList<Buf *> clobber_list = ast_parse_list<Buf>(pc, TokenIdComma, [](ParseContext *context) { |
| 2094 | Token *str = eat_token_if(context, TokenIdStringLiteral); | 2026 | TokenIndex str = eat_token_if(context, TokenIdStringLiteral); |
| 2095 | if (str == nullptr) | 2027 | if (str == 0) |
| 2096 | str = eat_token_if(context, TokenIdMultilineStringLiteral); | 2028 | str = ast_parse_multi_tok(context, TokenIdMultilineStringLiteralLine); |
| 2097 | if (str != nullptr) | 2029 | if (str != 0) |
| 2098 | return token_buf(str); | 2030 | return token_buf(context, str); |
| 2099 | return (Buf*)nullptr; | 2031 | return (Buf*)nullptr; |
| 2100 | }); | 2032 | }); |
| 2101 | 2033 | ||
| ... | @@ -2105,24 +2037,24 @@ static AstNode *ast_parse_asm_clobbers(ParseContext *pc) { | ... | @@ -2105,24 +2037,24 @@ static AstNode *ast_parse_asm_clobbers(ParseContext *pc) { |
| 2105 | } | 2037 | } |
| 2106 | 2038 | ||
| 2107 | // BreakLabel <- COLON IDENTIFIER | 2039 | // BreakLabel <- COLON IDENTIFIER |
| 2108 | static Token *ast_parse_break_label(ParseContext *pc) { | 2040 | static TokenIndex ast_parse_break_label(ParseContext *pc) { |
| 2109 | if (eat_token_if(pc, TokenIdColon) == nullptr) | 2041 | if (eat_token_if(pc, TokenIdColon) == 0) |
| 2110 | return nullptr; | 2042 | return 0; |
| 2111 | 2043 | ||
| 2112 | return expect_token(pc, TokenIdSymbol); | 2044 | return expect_token(pc, TokenIdIdentifier); |
| 2113 | } | 2045 | } |
| 2114 | 2046 | ||
| 2115 | // BlockLabel <- IDENTIFIER COLON | 2047 | // BlockLabel <- IDENTIFIER COLON |
| 2116 | static Token *ast_parse_block_label(ParseContext *pc) { | 2048 | static TokenIndex ast_parse_block_label(ParseContext *pc) { |
| 2117 | Token *ident = eat_token_if(pc, TokenIdSymbol); | 2049 | TokenIndex ident = eat_token_if(pc, TokenIdIdentifier); |
| 2118 | if (ident == nullptr) | 2050 | if (ident == 0) |
| 2119 | return nullptr; | 2051 | return 0; |
| 2120 | 2052 | ||
| 2121 | // We do 2 token lookahead here, as we don't want to error when | 2053 | // We do 2 token lookahead here, as we don't want to error when |
| 2122 | // parsing identifiers. | 2054 | // parsing identifiers. |
| 2123 | if (eat_token_if(pc, TokenIdColon) == nullptr) { | 2055 | if (eat_token_if(pc, TokenIdColon) == 0) { |
| 2124 | put_back_token(pc); | 2056 | put_back_token(pc); |
| 2125 | return nullptr; | 2057 | return 0; |
| 2126 | } | 2058 | } |
| 2127 | 2059 | ||
| 2128 | return ident; | 2060 | return ident; |
| ... | @@ -2130,17 +2062,17 @@ static Token *ast_parse_block_label(ParseContext *pc) { | ... | @@ -2130,17 +2062,17 @@ static Token *ast_parse_block_label(ParseContext *pc) { |
| 2130 | 2062 | ||
| 2131 | // FieldInit <- DOT IDENTIFIER EQUAL Expr | 2063 | // FieldInit <- DOT IDENTIFIER EQUAL Expr |
| 2132 | static AstNode *ast_parse_field_init(ParseContext *pc) { | 2064 | static AstNode *ast_parse_field_init(ParseContext *pc) { |
| 2133 | Token *first = eat_token_if(pc, TokenIdDot); | 2065 | TokenIndex first = eat_token_if(pc, TokenIdDot); |
| 2134 | if (first == nullptr) | 2066 | if (first == 0) |
| 2135 | return nullptr; | 2067 | return nullptr; |
| 2136 | 2068 | ||
| 2137 | Token *name = eat_token_if(pc, TokenIdSymbol); | 2069 | TokenIndex name = eat_token_if(pc, TokenIdIdentifier); |
| 2138 | if (name == nullptr) { | 2070 | if (name == 0) { |
| 2139 | // Because of anon literals ".{" is also valid. | 2071 | // Because of anon literals ".{" is also valid. |
| 2140 | put_back_token(pc); | 2072 | put_back_token(pc); |
| 2141 | return nullptr; | 2073 | return nullptr; |
| 2142 | } | 2074 | } |
| 2143 | if (eat_token_if(pc, TokenIdEq) == nullptr) { | 2075 | if (eat_token_if(pc, TokenIdEq) == 0) { |
| 2144 | // Because ".Name" can also be intepreted as an enum literal, we should put back | 2076 | // Because ".Name" can also be intepreted as an enum literal, we should put back |
| 2145 | // those two tokens again so that the parser can try to parse them as the enum | 2077 | // those two tokens again so that the parser can try to parse them as the enum |
| 2146 | // literal later. | 2078 | // literal later. |
| ... | @@ -2151,15 +2083,15 @@ static AstNode *ast_parse_field_init(ParseContext *pc) { | ... | @@ -2151,15 +2083,15 @@ static AstNode *ast_parse_field_init(ParseContext *pc) { |
| 2151 | AstNode *expr = ast_expect(pc, ast_parse_expr); | 2083 | AstNode *expr = ast_expect(pc, ast_parse_expr); |
| 2152 | 2084 | ||
| 2153 | AstNode *res = ast_create_node(pc, NodeTypeStructValueField, first); | 2085 | AstNode *res = ast_create_node(pc, NodeTypeStructValueField, first); |
| 2154 | res->data.struct_val_field.name = token_buf(name); | 2086 | res->data.struct_val_field.name = token_buf(pc, name); |
| 2155 | res->data.struct_val_field.expr = expr; | 2087 | res->data.struct_val_field.expr = expr; |
| 2156 | return res; | 2088 | return res; |
| 2157 | } | 2089 | } |
| 2158 | 2090 | ||
| 2159 | // WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN | 2091 | // WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN |
| 2160 | static AstNode *ast_parse_while_continue_expr(ParseContext *pc) { | 2092 | static AstNode *ast_parse_while_continue_expr(ParseContext *pc) { |
| 2161 | Token *first = eat_token_if(pc, TokenIdColon); | 2093 | TokenIndex first = eat_token_if(pc, TokenIdColon); |
| 2162 | if (first == nullptr) | 2094 | if (first == 0) |
| 2163 | return nullptr; | 2095 | return nullptr; |
| 2164 | 2096 | ||
| 2165 | expect_token(pc, TokenIdLParen); | 2097 | expect_token(pc, TokenIdLParen); |
| ... | @@ -2170,8 +2102,8 @@ static AstNode *ast_parse_while_continue_expr(ParseContext *pc) { | ... | @@ -2170,8 +2102,8 @@ static AstNode *ast_parse_while_continue_expr(ParseContext *pc) { |
| 2170 | 2102 | ||
| 2171 | // LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN | 2103 | // LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN |
| 2172 | static AstNode *ast_parse_link_section(ParseContext *pc) { | 2104 | static AstNode *ast_parse_link_section(ParseContext *pc) { |
| 2173 | Token *first = eat_token_if(pc, TokenIdKeywordLinkSection); | 2105 | TokenIndex first = eat_token_if(pc, TokenIdKeywordLinkSection); |
| 2174 | if (first == nullptr) | 2106 | if (first == 0) |
| 2175 | return nullptr; | 2107 | return nullptr; |
| 2176 | 2108 | ||
| 2177 | expect_token(pc, TokenIdLParen); | 2109 | expect_token(pc, TokenIdLParen); |
| ... | @@ -2182,8 +2114,8 @@ static AstNode *ast_parse_link_section(ParseContext *pc) { | ... | @@ -2182,8 +2114,8 @@ static AstNode *ast_parse_link_section(ParseContext *pc) { |
| 2182 | 2114 | ||
| 2183 | // CallConv <- KEYWORD_callconv LPAREN Expr RPAREN | 2115 | // CallConv <- KEYWORD_callconv LPAREN Expr RPAREN |
| 2184 | static AstNode *ast_parse_callconv(ParseContext *pc) { | 2116 | static AstNode *ast_parse_callconv(ParseContext *pc) { |
| 2185 | Token *first = eat_token_if(pc, TokenIdKeywordCallconv); | 2117 | TokenIndex first = eat_token_if(pc, TokenIdKeywordCallconv); |
| 2186 | if (first == nullptr) | 2118 | if (first == 0) |
| 2187 | return nullptr; | 2119 | return nullptr; |
| 2188 | 2120 | ||
| 2189 | expect_token(pc, TokenIdLParen); | 2121 | expect_token(pc, TokenIdLParen); |
| ... | @@ -2194,28 +2126,27 @@ static AstNode *ast_parse_callconv(ParseContext *pc) { | ... | @@ -2194,28 +2126,27 @@ static AstNode *ast_parse_callconv(ParseContext *pc) { |
| 2194 | 2126 | ||
| 2195 | // ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType | 2127 | // ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType |
| 2196 | static AstNode *ast_parse_param_decl(ParseContext *pc) { | 2128 | static AstNode *ast_parse_param_decl(ParseContext *pc) { |
| 2197 | Buf doc_comments = BUF_INIT; | 2129 | TokenIndex first_doc_comment = ast_parse_doc_comments(pc); |
| 2198 | ast_parse_doc_comments(pc, &doc_comments); | ||
| 2199 | 2130 | ||
| 2200 | Token *first = eat_token_if(pc, TokenIdKeywordNoAlias); | 2131 | TokenIndex first = eat_token_if(pc, TokenIdKeywordNoAlias); |
| 2201 | if (first == nullptr) | 2132 | if (first == 0) |
| 2202 | first = eat_token_if(pc, TokenIdKeywordCompTime); | 2133 | first = eat_token_if(pc, TokenIdKeywordCompTime); |
| 2203 | 2134 | ||
| 2204 | Token *name = eat_token_if(pc, TokenIdSymbol); | 2135 | TokenIndex name = eat_token_if(pc, TokenIdIdentifier); |
| 2205 | if (name != nullptr) { | 2136 | if (name != 0) { |
| 2206 | if (eat_token_if(pc, TokenIdColon) != nullptr) { | 2137 | if (eat_token_if(pc, TokenIdColon) != 0) { |
| 2207 | if (first == nullptr) | 2138 | if (first == 0) |
| 2208 | first = name; | 2139 | first = name; |
| 2209 | } else { | 2140 | } else { |
| 2210 | // We put back the ident, so it can be parsed as a ParamType | 2141 | // We put back the ident, so it can be parsed as a ParamType |
| 2211 | // later. | 2142 | // later. |
| 2212 | put_back_token(pc); | 2143 | put_back_token(pc); |
| 2213 | name = nullptr; | 2144 | name = 0; |
| 2214 | } | 2145 | } |
| 2215 | } | 2146 | } |
| 2216 | 2147 | ||
| 2217 | AstNode *res; | 2148 | AstNode *res; |
| 2218 | if (first == nullptr) { | 2149 | if (first == 0) { |
| 2219 | first = peek_token(pc); | 2150 | first = peek_token(pc); |
| 2220 | res = ast_parse_param_type(pc); | 2151 | res = ast_parse_param_type(pc); |
| 2221 | } else { | 2152 | } else { |
| ... | @@ -2226,12 +2157,11 @@ static AstNode *ast_parse_param_decl(ParseContext *pc) { | ... | @@ -2226,12 +2157,11 @@ static AstNode *ast_parse_param_decl(ParseContext *pc) { |
| 2226 | return nullptr; | 2157 | return nullptr; |
| 2227 | 2158 | ||
| 2228 | assert(res->type == NodeTypeParamDecl); | 2159 | assert(res->type == NodeTypeParamDecl); |
| 2229 | res->line = first->start_line; | 2160 | res->main_token = first; |
| 2230 | res->column = first->start_column; | 2161 | res->data.param_decl.name = token_buf(pc, name); |
| 2231 | res->data.param_decl.name = token_buf(name); | 2162 | res->data.param_decl.doc_comments = first_doc_comment; |
| 2232 | res->data.param_decl.doc_comments = doc_comments; | 2163 | res->data.param_decl.is_noalias = pc->token_ids[first] == TokenIdKeywordNoAlias; |
| 2233 | res->data.param_decl.is_noalias = first->id == TokenIdKeywordNoAlias; | 2164 | res->data.param_decl.is_comptime = pc->token_ids[first] == TokenIdKeywordCompTime; |
| 2234 | res->data.param_decl.is_comptime = first->id == TokenIdKeywordCompTime; | ||
| 2235 | return res; | 2165 | return res; |
| 2236 | } | 2166 | } |
| 2237 | 2167 | ||
| ... | @@ -2240,15 +2170,15 @@ static AstNode *ast_parse_param_decl(ParseContext *pc) { | ... | @@ -2240,15 +2170,15 @@ static AstNode *ast_parse_param_decl(ParseContext *pc) { |
| 2240 | // / DOT3 | 2170 | // / DOT3 |
| 2241 | // / TypeExpr | 2171 | // / TypeExpr |
| 2242 | static AstNode *ast_parse_param_type(ParseContext *pc) { | 2172 | static AstNode *ast_parse_param_type(ParseContext *pc) { |
| 2243 | Token *anytype_token = eat_token_if(pc, TokenIdKeywordAnyType); | 2173 | TokenIndex anytype_token = eat_token_if(pc, TokenIdKeywordAnyType); |
| 2244 | if (anytype_token != nullptr) { | 2174 | if (anytype_token != 0) { |
| 2245 | AstNode *res = ast_create_node(pc, NodeTypeParamDecl, anytype_token); | 2175 | AstNode *res = ast_create_node(pc, NodeTypeParamDecl, anytype_token); |
| 2246 | res->data.param_decl.anytype_token = anytype_token; | 2176 | res->data.param_decl.anytype_token = anytype_token; |
| 2247 | return res; | 2177 | return res; |
| 2248 | } | 2178 | } |
| 2249 | 2179 | ||
| 2250 | Token *dots = eat_token_if(pc, TokenIdEllipsis3); | 2180 | TokenIndex dots = eat_token_if(pc, TokenIdEllipsis3); |
| 2251 | if (dots != nullptr) { | 2181 | if (dots != 0) { |
| 2252 | AstNode *res = ast_create_node(pc, NodeTypeParamDecl, dots); | 2182 | AstNode *res = ast_create_node(pc, NodeTypeParamDecl, dots); |
| 2253 | res->data.param_decl.is_var_args = true; | 2183 | res->data.param_decl.is_var_args = true; |
| 2254 | return res; | 2184 | return res; |
| ... | @@ -2266,8 +2196,8 @@ static AstNode *ast_parse_param_type(ParseContext *pc) { | ... | @@ -2266,8 +2196,8 @@ static AstNode *ast_parse_param_type(ParseContext *pc) { |
| 2266 | 2196 | ||
| 2267 | // IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload? | 2197 | // IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload? |
| 2268 | static AstNode *ast_parse_if_prefix(ParseContext *pc) { | 2198 | static AstNode *ast_parse_if_prefix(ParseContext *pc) { |
| 2269 | Token *first = eat_token_if(pc, TokenIdKeywordIf); | 2199 | TokenIndex first = eat_token_if(pc, TokenIdKeywordIf); |
| 2270 | if (first == nullptr) | 2200 | if (first == 0) |
| 2271 | return nullptr; | 2201 | return nullptr; |
| 2272 | 2202 | ||
| 2273 | expect_token(pc, TokenIdLParen); | 2203 | expect_token(pc, TokenIdLParen); |
| ... | @@ -2279,16 +2209,16 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) { | ... | @@ -2279,16 +2209,16 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) { |
| 2279 | AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first); | 2209 | AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first); |
| 2280 | res->data.test_expr.target_node = condition; | 2210 | res->data.test_expr.target_node = condition; |
| 2281 | if (opt_payload.unwrap(&payload)) { | 2211 | if (opt_payload.unwrap(&payload)) { |
| 2282 | res->data.test_expr.var_symbol = token_buf(payload.payload); | 2212 | res->data.test_expr.var_symbol = token_buf(pc, payload.payload); |
| 2283 | res->data.test_expr.var_is_ptr = payload.asterisk != nullptr; | 2213 | res->data.test_expr.var_is_ptr = payload.asterisk != 0; |
| 2284 | } | 2214 | } |
| 2285 | return res; | 2215 | return res; |
| 2286 | } | 2216 | } |
| 2287 | 2217 | ||
| 2288 | // WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? | 2218 | // WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? |
| 2289 | static AstNode *ast_parse_while_prefix(ParseContext *pc) { | 2219 | static AstNode *ast_parse_while_prefix(ParseContext *pc) { |
| 2290 | Token *while_token = eat_token_if(pc, TokenIdKeywordWhile); | 2220 | TokenIndex while_token = eat_token_if(pc, TokenIdKeywordWhile); |
| 2291 | if (while_token == nullptr) | 2221 | if (while_token == 0) |
| 2292 | return nullptr; | 2222 | return nullptr; |
| 2293 | 2223 | ||
| 2294 | expect_token(pc, TokenIdLParen); | 2224 | expect_token(pc, TokenIdLParen); |
| ... | @@ -2302,8 +2232,8 @@ static AstNode *ast_parse_while_prefix(ParseContext *pc) { | ... | @@ -2302,8 +2232,8 @@ static AstNode *ast_parse_while_prefix(ParseContext *pc) { |
| 2302 | res->data.while_expr.condition = condition; | 2232 | res->data.while_expr.condition = condition; |
| 2303 | res->data.while_expr.continue_expr = continue_expr; | 2233 | res->data.while_expr.continue_expr = continue_expr; |
| 2304 | if (opt_payload.unwrap(&payload)) { | 2234 | if (opt_payload.unwrap(&payload)) { |
| 2305 | res->data.while_expr.var_symbol = token_buf(payload.payload); | 2235 | res->data.while_expr.var_symbol = token_buf(pc, payload.payload); |
| 2306 | res->data.while_expr.var_is_ptr = payload.asterisk != nullptr; | 2236 | res->data.while_expr.var_is_ptr = payload.asterisk != 0; |
| 2307 | } | 2237 | } |
| 2308 | 2238 | ||
| 2309 | return res; | 2239 | return res; |
| ... | @@ -2311,8 +2241,8 @@ static AstNode *ast_parse_while_prefix(ParseContext *pc) { | ... | @@ -2311,8 +2241,8 @@ static AstNode *ast_parse_while_prefix(ParseContext *pc) { |
| 2311 | 2241 | ||
| 2312 | // ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload | 2242 | // ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload |
| 2313 | static AstNode *ast_parse_for_prefix(ParseContext *pc) { | 2243 | static AstNode *ast_parse_for_prefix(ParseContext *pc) { |
| 2314 | Token *for_token = eat_token_if(pc, TokenIdKeywordFor); | 2244 | TokenIndex for_token = eat_token_if(pc, TokenIdKeywordFor); |
| 2315 | if (for_token == nullptr) | 2245 | if (for_token == 0) |
| 2316 | return nullptr; | 2246 | return nullptr; |
| 2317 | 2247 | ||
| 2318 | expect_token(pc, TokenIdLParen); | 2248 | expect_token(pc, TokenIdLParen); |
| ... | @@ -2324,31 +2254,31 @@ static AstNode *ast_parse_for_prefix(ParseContext *pc) { | ... | @@ -2324,31 +2254,31 @@ static AstNode *ast_parse_for_prefix(ParseContext *pc) { |
| 2324 | 2254 | ||
| 2325 | AstNode *res = ast_create_node(pc, NodeTypeForExpr, for_token); | 2255 | AstNode *res = ast_create_node(pc, NodeTypeForExpr, for_token); |
| 2326 | res->data.for_expr.array_expr = array_expr; | 2256 | res->data.for_expr.array_expr = array_expr; |
| 2327 | res->data.for_expr.elem_node = token_symbol(pc, payload.payload); | 2257 | res->data.for_expr.elem_node = token_identifier(pc, payload.payload); |
| 2328 | res->data.for_expr.elem_is_ptr = payload.asterisk != nullptr; | 2258 | res->data.for_expr.elem_is_ptr = payload.asterisk != 0; |
| 2329 | if (payload.index != nullptr) | 2259 | if (payload.index != 0) |
| 2330 | res->data.for_expr.index_node = token_symbol(pc, payload.index); | 2260 | res->data.for_expr.index_node = token_identifier(pc, payload.index); |
| 2331 | 2261 | ||
| 2332 | return res; | 2262 | return res; |
| 2333 | } | 2263 | } |
| 2334 | 2264 | ||
| 2335 | // Payload <- PIPE IDENTIFIER PIPE | 2265 | // Payload <- PIPE IDENTIFIER PIPE |
| 2336 | static Token *ast_parse_payload(ParseContext *pc) { | 2266 | static TokenIndex ast_parse_payload(ParseContext *pc) { |
| 2337 | if (eat_token_if(pc, TokenIdBinOr) == nullptr) | 2267 | if (eat_token_if(pc, TokenIdBinOr) == 0) |
| 2338 | return nullptr; | 2268 | return 0; |
| 2339 | 2269 | ||
| 2340 | Token *res = expect_token(pc, TokenIdSymbol); | 2270 | TokenIndex res = expect_token(pc, TokenIdIdentifier); |
| 2341 | expect_token(pc, TokenIdBinOr); | 2271 | expect_token(pc, TokenIdBinOr); |
| 2342 | return res; | 2272 | return res; |
| 2343 | } | 2273 | } |
| 2344 | 2274 | ||
| 2345 | // PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE | 2275 | // PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE |
| 2346 | static Optional<PtrPayload> ast_parse_ptr_payload(ParseContext *pc) { | 2276 | static Optional<PtrPayload> ast_parse_ptr_payload(ParseContext *pc) { |
| 2347 | if (eat_token_if(pc, TokenIdBinOr) == nullptr) | 2277 | if (eat_token_if(pc, TokenIdBinOr) == 0) |
| 2348 | return Optional<PtrPayload>::none(); | 2278 | return Optional<PtrPayload>::none(); |
| 2349 | 2279 | ||
| 2350 | Token *asterisk = eat_token_if(pc, TokenIdStar); | 2280 | TokenIndex asterisk = eat_token_if(pc, TokenIdStar); |
| 2351 | Token *payload = expect_token(pc, TokenIdSymbol); | 2281 | TokenIndex payload = expect_token(pc, TokenIdIdentifier); |
| 2352 | expect_token(pc, TokenIdBinOr); | 2282 | expect_token(pc, TokenIdBinOr); |
| 2353 | 2283 | ||
| 2354 | PtrPayload res; | 2284 | PtrPayload res; |
| ... | @@ -2359,14 +2289,14 @@ static Optional<PtrPayload> ast_parse_ptr_payload(ParseContext *pc) { | ... | @@ -2359,14 +2289,14 @@ static Optional<PtrPayload> ast_parse_ptr_payload(ParseContext *pc) { |
| 2359 | 2289 | ||
| 2360 | // PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE | 2290 | // PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE |
| 2361 | static Optional<PtrIndexPayload> ast_parse_ptr_index_payload(ParseContext *pc) { | 2291 | static Optional<PtrIndexPayload> ast_parse_ptr_index_payload(ParseContext *pc) { |
| 2362 | if (eat_token_if(pc, TokenIdBinOr) == nullptr) | 2292 | if (eat_token_if(pc, TokenIdBinOr) == 0) |
| 2363 | return Optional<PtrIndexPayload>::none(); | 2293 | return Optional<PtrIndexPayload>::none(); |
| 2364 | 2294 | ||
| 2365 | Token *asterisk = eat_token_if(pc, TokenIdStar); | 2295 | TokenIndex asterisk = eat_token_if(pc, TokenIdStar); |
| 2366 | Token *payload = expect_token(pc, TokenIdSymbol); | 2296 | TokenIndex payload = expect_token(pc, TokenIdIdentifier); |
| 2367 | Token *index = nullptr; | 2297 | TokenIndex index = 0; |
| 2368 | if (eat_token_if(pc, TokenIdComma) != nullptr) | 2298 | if (eat_token_if(pc, TokenIdComma) != 0) |
| 2369 | index = expect_token(pc, TokenIdSymbol); | 2299 | index = expect_token(pc, TokenIdIdentifier); |
| 2370 | expect_token(pc, TokenIdBinOr); | 2300 | expect_token(pc, TokenIdBinOr); |
| 2371 | 2301 | ||
| 2372 | PtrIndexPayload res; | 2302 | PtrIndexPayload res; |
| ... | @@ -2390,8 +2320,8 @@ static AstNode *ast_parse_switch_prong(ParseContext *pc) { | ... | @@ -2390,8 +2320,8 @@ static AstNode *ast_parse_switch_prong(ParseContext *pc) { |
| 2390 | assert(res->type == NodeTypeSwitchProng); | 2320 | assert(res->type == NodeTypeSwitchProng); |
| 2391 | res->data.switch_prong.expr = expr; | 2321 | res->data.switch_prong.expr = expr; |
| 2392 | if (opt_payload.unwrap(&payload)) { | 2322 | if (opt_payload.unwrap(&payload)) { |
| 2393 | res->data.switch_prong.var_symbol = token_symbol(pc, payload.payload); | 2323 | res->data.switch_prong.var_symbol = token_identifier(pc, payload.payload); |
| 2394 | res->data.switch_prong.var_is_ptr = payload.asterisk != nullptr; | 2324 | res->data.switch_prong.var_is_ptr = payload.asterisk != 0; |
| 2395 | } | 2325 | } |
| 2396 | 2326 | ||
| 2397 | return res; | 2327 | return res; |
| ... | @@ -2407,7 +2337,7 @@ static AstNode *ast_parse_switch_case(ParseContext *pc) { | ... | @@ -2407,7 +2337,7 @@ static AstNode *ast_parse_switch_case(ParseContext *pc) { |
| 2407 | res->data.switch_prong.items.append(first); | 2337 | res->data.switch_prong.items.append(first); |
| 2408 | res->data.switch_prong.any_items_are_range = first->type == NodeTypeSwitchRange; | 2338 | res->data.switch_prong.any_items_are_range = first->type == NodeTypeSwitchRange; |
| 2409 | 2339 | ||
| 2410 | while (eat_token_if(pc, TokenIdComma) != nullptr) { | 2340 | while (eat_token_if(pc, TokenIdComma) != 0) { |
| 2411 | AstNode *item = ast_parse_switch_item(pc); | 2341 | AstNode *item = ast_parse_switch_item(pc); |
| 2412 | if (item == nullptr) | 2342 | if (item == nullptr) |
| 2413 | break; | 2343 | break; |
| ... | @@ -2419,8 +2349,8 @@ static AstNode *ast_parse_switch_case(ParseContext *pc) { | ... | @@ -2419,8 +2349,8 @@ static AstNode *ast_parse_switch_case(ParseContext *pc) { |
| 2419 | return res; | 2349 | return res; |
| 2420 | } | 2350 | } |
| 2421 | 2351 | ||
| 2422 | Token *else_token = eat_token_if(pc, TokenIdKeywordElse); | 2352 | TokenIndex else_token = eat_token_if(pc, TokenIdKeywordElse); |
| 2423 | if (else_token != nullptr) | 2353 | if (else_token != 0) |
| 2424 | return ast_create_node(pc, NodeTypeSwitchProng, else_token); | 2354 | return ast_create_node(pc, NodeTypeSwitchProng, else_token); |
| 2425 | 2355 | ||
| 2426 | return nullptr; | 2356 | return nullptr; |
| ... | @@ -2432,8 +2362,8 @@ static AstNode *ast_parse_switch_item(ParseContext *pc) { | ... | @@ -2432,8 +2362,8 @@ static AstNode *ast_parse_switch_item(ParseContext *pc) { |
| 2432 | if (expr == nullptr) | 2362 | if (expr == nullptr) |
| 2433 | return nullptr; | 2363 | return nullptr; |
| 2434 | 2364 | ||
| 2435 | Token *dots = eat_token_if(pc, TokenIdEllipsis3); | 2365 | TokenIndex dots = eat_token_if(pc, TokenIdEllipsis3); |
| 2436 | if (dots != nullptr) { | 2366 | if (dots != 0) { |
| 2437 | AstNode *expr2 = ast_expect(pc, ast_parse_expr); | 2367 | AstNode *expr2 = ast_expect(pc, ast_parse_expr); |
| 2438 | AstNode *res = ast_create_node(pc, NodeTypeSwitchRange, dots); | 2368 | AstNode *res = ast_create_node(pc, NodeTypeSwitchRange, dots); |
| 2439 | res->data.switch_range.start = expr; | 2369 | res->data.switch_range.start = expr; |
| ... | @@ -2478,9 +2408,9 @@ static AstNode *ast_parse_assign_op(ParseContext *pc) { | ... | @@ -2478,9 +2408,9 @@ static AstNode *ast_parse_assign_op(ParseContext *pc) { |
| 2478 | table[TokenIdTimesEq] = BinOpTypeAssignTimes; | 2408 | table[TokenIdTimesEq] = BinOpTypeAssignTimes; |
| 2479 | table[TokenIdTimesPercentEq] = BinOpTypeAssignTimesWrap; | 2409 | table[TokenIdTimesPercentEq] = BinOpTypeAssignTimesWrap; |
| 2480 | 2410 | ||
| 2481 | BinOpType op = table[peek_token(pc)->id]; | 2411 | BinOpType op = table[pc->token_ids[pc->current_token]]; |
| 2482 | if (op != BinOpTypeInvalid) { | 2412 | if (op != BinOpTypeInvalid) { |
| 2483 | Token *op_token = eat_token(pc); | 2413 | TokenIndex op_token = eat_token(pc); |
| 2484 | AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); | 2414 | AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); |
| 2485 | res->data.bin_op_expr.bin_op = op; | 2415 | res->data.bin_op_expr.bin_op = op; |
| 2486 | return res; | 2416 | return res; |
| ... | @@ -2506,9 +2436,9 @@ static AstNode *ast_parse_compare_op(ParseContext *pc) { | ... | @@ -2506,9 +2436,9 @@ static AstNode *ast_parse_compare_op(ParseContext *pc) { |
| 2506 | table[TokenIdCmpLessOrEq] = BinOpTypeCmpLessOrEq; | 2436 | table[TokenIdCmpLessOrEq] = BinOpTypeCmpLessOrEq; |
| 2507 | table[TokenIdCmpGreaterOrEq] = BinOpTypeCmpGreaterOrEq; | 2437 | table[TokenIdCmpGreaterOrEq] = BinOpTypeCmpGreaterOrEq; |
| 2508 | 2438 | ||
| 2509 | BinOpType op = table[peek_token(pc)->id]; | 2439 | BinOpType op = table[pc->token_ids[pc->current_token]]; |
| 2510 | if (op != BinOpTypeInvalid) { | 2440 | if (op != BinOpTypeInvalid) { |
| 2511 | Token *op_token = eat_token(pc); | 2441 | TokenIndex op_token = eat_token(pc); |
| 2512 | AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); | 2442 | AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); |
| 2513 | res->data.bin_op_expr.bin_op = op; | 2443 | res->data.bin_op_expr.bin_op = op; |
| 2514 | return res; | 2444 | return res; |
| ... | @@ -2530,20 +2460,20 @@ static AstNode *ast_parse_bitwise_op(ParseContext *pc) { | ... | @@ -2530,20 +2460,20 @@ static AstNode *ast_parse_bitwise_op(ParseContext *pc) { |
| 2530 | table[TokenIdBinOr] = BinOpTypeBinOr; | 2460 | table[TokenIdBinOr] = BinOpTypeBinOr; |
| 2531 | table[TokenIdKeywordOrElse] = BinOpTypeUnwrapOptional; | 2461 | table[TokenIdKeywordOrElse] = BinOpTypeUnwrapOptional; |
| 2532 | 2462 | ||
| 2533 | BinOpType op = table[peek_token(pc)->id]; | 2463 | BinOpType op = table[pc->token_ids[pc->current_token]]; |
| 2534 | if (op != BinOpTypeInvalid) { | 2464 | if (op != BinOpTypeInvalid) { |
| 2535 | Token *op_token = eat_token(pc); | 2465 | TokenIndex op_token = eat_token(pc); |
| 2536 | AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); | 2466 | AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); |
| 2537 | res->data.bin_op_expr.bin_op = op; | 2467 | res->data.bin_op_expr.bin_op = op; |
| 2538 | return res; | 2468 | return res; |
| 2539 | } | 2469 | } |
| 2540 | 2470 | ||
| 2541 | Token *catch_token = eat_token_if(pc, TokenIdKeywordCatch); | 2471 | TokenIndex catch_token = eat_token_if(pc, TokenIdKeywordCatch); |
| 2542 | if (catch_token != nullptr) { | 2472 | if (catch_token != 0) { |
| 2543 | Token *payload = ast_parse_payload(pc); | 2473 | TokenIndex payload = ast_parse_payload(pc); |
| 2544 | AstNode *res = ast_create_node(pc, NodeTypeCatchExpr, catch_token); | 2474 | AstNode *res = ast_create_node(pc, NodeTypeCatchExpr, catch_token); |
| 2545 | if (payload != nullptr) | 2475 | if (payload != 0) |
| 2546 | res->data.unwrap_err_expr.symbol = token_symbol(pc, payload); | 2476 | res->data.unwrap_err_expr.symbol = token_identifier(pc, payload); |
| 2547 | 2477 | ||
| 2548 | return res; | 2478 | return res; |
| 2549 | } | 2479 | } |
| ... | @@ -2559,9 +2489,9 @@ static AstNode *ast_parse_bit_shift_op(ParseContext *pc) { | ... | @@ -2559,9 +2489,9 @@ static AstNode *ast_parse_bit_shift_op(ParseContext *pc) { |
| 2559 | table[TokenIdBitShiftLeft] = BinOpTypeBitShiftLeft; | 2489 | table[TokenIdBitShiftLeft] = BinOpTypeBitShiftLeft; |
| 2560 | table[TokenIdBitShiftRight] = BinOpTypeBitShiftRight; | 2490 | table[TokenIdBitShiftRight] = BinOpTypeBitShiftRight; |
| 2561 | 2491 | ||
| 2562 | BinOpType op = table[peek_token(pc)->id]; | 2492 | BinOpType op = table[pc->token_ids[pc->current_token]]; |
| 2563 | if (op != BinOpTypeInvalid) { | 2493 | if (op != BinOpTypeInvalid) { |
| 2564 | Token *op_token = eat_token(pc); | 2494 | TokenIndex op_token = eat_token(pc); |
| 2565 | AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); | 2495 | AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); |
| 2566 | res->data.bin_op_expr.bin_op = op; | 2496 | res->data.bin_op_expr.bin_op = op; |
| 2567 | return res; | 2497 | return res; |
| ... | @@ -2584,9 +2514,9 @@ static AstNode *ast_parse_addition_op(ParseContext *pc) { | ... | @@ -2584,9 +2514,9 @@ static AstNode *ast_parse_addition_op(ParseContext *pc) { |
| 2584 | table[TokenIdPlusPercent] = BinOpTypeAddWrap; | 2514 | table[TokenIdPlusPercent] = BinOpTypeAddWrap; |
| 2585 | table[TokenIdMinusPercent] = BinOpTypeSubWrap; | 2515 | table[TokenIdMinusPercent] = BinOpTypeSubWrap; |
| 2586 | 2516 | ||
| 2587 | BinOpType op = table[peek_token(pc)->id]; | 2517 | BinOpType op = table[pc->token_ids[pc->current_token]]; |
| 2588 | if (op != BinOpTypeInvalid) { | 2518 | if (op != BinOpTypeInvalid) { |
| 2589 | Token *op_token = eat_token(pc); | 2519 | TokenIndex op_token = eat_token(pc); |
| 2590 | AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); | 2520 | AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); |
| 2591 | res->data.bin_op_expr.bin_op = op; | 2521 | res->data.bin_op_expr.bin_op = op; |
| 2592 | return res; | 2522 | return res; |
| ... | @@ -2611,9 +2541,9 @@ static AstNode *ast_parse_multiply_op(ParseContext *pc) { | ... | @@ -2611,9 +2541,9 @@ static AstNode *ast_parse_multiply_op(ParseContext *pc) { |
| 2611 | table[TokenIdStarStar] = BinOpTypeArrayMult; | 2541 | table[TokenIdStarStar] = BinOpTypeArrayMult; |
| 2612 | table[TokenIdTimesPercent] = BinOpTypeMultWrap; | 2542 | table[TokenIdTimesPercent] = BinOpTypeMultWrap; |
| 2613 | 2543 | ||
| 2614 | BinOpType op = table[peek_token(pc)->id]; | 2544 | BinOpType op = table[pc->token_ids[pc->current_token]]; |
| 2615 | if (op != BinOpTypeInvalid) { | 2545 | if (op != BinOpTypeInvalid) { |
| 2616 | Token *op_token = eat_token(pc); | 2546 | TokenIndex op_token = eat_token(pc); |
| 2617 | AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); | 2547 | AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token); |
| 2618 | res->data.bin_op_expr.bin_op = op; | 2548 | res->data.bin_op_expr.bin_op = op; |
| 2619 | return res; | 2549 | return res; |
| ... | @@ -2638,23 +2568,23 @@ static AstNode *ast_parse_prefix_op(ParseContext *pc) { | ... | @@ -2638,23 +2568,23 @@ static AstNode *ast_parse_prefix_op(ParseContext *pc) { |
| 2638 | table[TokenIdMinusPercent] = PrefixOpNegationWrap; | 2568 | table[TokenIdMinusPercent] = PrefixOpNegationWrap; |
| 2639 | table[TokenIdAmpersand] = PrefixOpAddrOf; | 2569 | table[TokenIdAmpersand] = PrefixOpAddrOf; |
| 2640 | 2570 | ||
| 2641 | PrefixOp op = table[peek_token(pc)->id]; | 2571 | PrefixOp op = table[pc->token_ids[pc->current_token]]; |
| 2642 | if (op != PrefixOpInvalid) { | 2572 | if (op != PrefixOpInvalid) { |
| 2643 | Token *op_token = eat_token(pc); | 2573 | TokenIndex op_token = eat_token(pc); |
| 2644 | AstNode *res = ast_create_node(pc, NodeTypePrefixOpExpr, op_token); | 2574 | AstNode *res = ast_create_node(pc, NodeTypePrefixOpExpr, op_token); |
| 2645 | res->data.prefix_op_expr.prefix_op = op; | 2575 | res->data.prefix_op_expr.prefix_op = op; |
| 2646 | return res; | 2576 | return res; |
| 2647 | } | 2577 | } |
| 2648 | 2578 | ||
| 2649 | Token *try_token = eat_token_if(pc, TokenIdKeywordTry); | 2579 | TokenIndex try_token = eat_token_if(pc, TokenIdKeywordTry); |
| 2650 | if (try_token != nullptr) { | 2580 | if (try_token != 0) { |
| 2651 | AstNode *res = ast_create_node(pc, NodeTypeReturnExpr, try_token); | 2581 | AstNode *res = ast_create_node(pc, NodeTypeReturnExpr, try_token); |
| 2652 | res->data.return_expr.kind = ReturnKindError; | 2582 | res->data.return_expr.kind = ReturnKindError; |
| 2653 | return res; | 2583 | return res; |
| 2654 | } | 2584 | } |
| 2655 | 2585 | ||
| 2656 | Token *await = eat_token_if(pc, TokenIdKeywordAwait); | 2586 | TokenIndex await = eat_token_if(pc, TokenIdKeywordAwait); |
| 2657 | if (await != nullptr) { | 2587 | if (await != 0) { |
| 2658 | AstNode *res = ast_create_node(pc, NodeTypeAwaitExpr, await); | 2588 | AstNode *res = ast_create_node(pc, NodeTypeAwaitExpr, await); |
| 2659 | return res; | 2589 | return res; |
| 2660 | } | 2590 | } |
| ... | @@ -2668,16 +2598,16 @@ static AstNode *ast_parse_prefix_op(ParseContext *pc) { | ... | @@ -2668,16 +2598,16 @@ static AstNode *ast_parse_prefix_op(ParseContext *pc) { |
| 2668 | // / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile)* | 2598 | // / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile)* |
| 2669 | // / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile)* | 2599 | // / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile)* |
| 2670 | static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { | 2600 | static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { |
| 2671 | Token *questionmark = eat_token_if(pc, TokenIdQuestion); | 2601 | TokenIndex questionmark = eat_token_if(pc, TokenIdQuestion); |
| 2672 | if (questionmark != nullptr) { | 2602 | if (questionmark != 0) { |
| 2673 | AstNode *res = ast_create_node(pc, NodeTypePrefixOpExpr, questionmark); | 2603 | AstNode *res = ast_create_node(pc, NodeTypePrefixOpExpr, questionmark); |
| 2674 | res->data.prefix_op_expr.prefix_op = PrefixOpOptional; | 2604 | res->data.prefix_op_expr.prefix_op = PrefixOpOptional; |
| 2675 | return res; | 2605 | return res; |
| 2676 | } | 2606 | } |
| 2677 | 2607 | ||
| 2678 | Token *anyframe = eat_token_if(pc, TokenIdKeywordAnyFrame); | 2608 | TokenIndex anyframe = eat_token_if(pc, TokenIdKeywordAnyFrame); |
| 2679 | if (anyframe != nullptr) { | 2609 | if (anyframe != 0) { |
| 2680 | if (eat_token_if(pc, TokenIdArrow) != nullptr) { | 2610 | if (eat_token_if(pc, TokenIdArrow) != 0) { |
| 2681 | AstNode *res = ast_create_node(pc, NodeTypeAnyFrameType, anyframe); | 2611 | AstNode *res = ast_create_node(pc, NodeTypeAnyFrameType, anyframe); |
| 2682 | return res; | 2612 | return res; |
| 2683 | } | 2613 | } |
| ... | @@ -2685,18 +2615,18 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { | ... | @@ -2685,18 +2615,18 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { |
| 2685 | put_back_token(pc); | 2615 | put_back_token(pc); |
| 2686 | } | 2616 | } |
| 2687 | 2617 | ||
| 2688 | Token *arr_init_lbracket = eat_token_if(pc, TokenIdLBracket); | 2618 | TokenIndex arr_init_lbracket = eat_token_if(pc, TokenIdLBracket); |
| 2689 | if (arr_init_lbracket != nullptr) { | 2619 | if (arr_init_lbracket != 0) { |
| 2690 | Token *underscore = eat_token_if(pc, TokenIdSymbol); | 2620 | TokenIndex underscore = eat_token_if(pc, TokenIdIdentifier); |
| 2691 | if (underscore == nullptr) { | 2621 | if (underscore == 0) { |
| 2692 | put_back_token(pc); | 2622 | put_back_token(pc); |
| 2693 | } else if (!buf_eql_str(token_buf(underscore), "_")) { | 2623 | } else if (!buf_eql_str(token_buf(pc, underscore), "_")) { |
| 2694 | put_back_token(pc); | 2624 | put_back_token(pc); |
| 2695 | put_back_token(pc); | 2625 | put_back_token(pc); |
| 2696 | } else { | 2626 | } else { |
| 2697 | AstNode *sentinel = nullptr; | 2627 | AstNode *sentinel = nullptr; |
| 2698 | Token *colon = eat_token_if(pc, TokenIdColon); | 2628 | TokenIndex colon = eat_token_if(pc, TokenIdColon); |
| 2699 | if (colon != nullptr) { | 2629 | if (colon != 0) { |
| 2700 | sentinel = ast_expect(pc, ast_parse_expr); | 2630 | sentinel = ast_expect(pc, ast_parse_expr); |
| 2701 | } | 2631 | } |
| 2702 | expect_token(pc, TokenIdRBracket); | 2632 | expect_token(pc, TokenIdRBracket); |
| ... | @@ -2715,33 +2645,33 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { | ... | @@ -2715,33 +2645,33 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { |
| 2715 | if (child == nullptr) | 2645 | if (child == nullptr) |
| 2716 | child = ptr; | 2646 | child = ptr; |
| 2717 | while (true) { | 2647 | while (true) { |
| 2718 | Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero); | 2648 | TokenIndex allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero); |
| 2719 | if (allowzero_token != nullptr) { | 2649 | if (allowzero_token != 0) { |
| 2720 | child->data.pointer_type.allow_zero_token = allowzero_token; | 2650 | child->data.pointer_type.allow_zero_token = allowzero_token; |
| 2721 | continue; | 2651 | continue; |
| 2722 | } | 2652 | } |
| 2723 | 2653 | ||
| 2724 | if (eat_token_if(pc, TokenIdKeywordAlign) != nullptr) { | 2654 | if (eat_token_if(pc, TokenIdKeywordAlign) != 0) { |
| 2725 | expect_token(pc, TokenIdLParen); | 2655 | expect_token(pc, TokenIdLParen); |
| 2726 | AstNode *align_expr = ast_expect(pc, ast_parse_expr); | 2656 | AstNode *align_expr = ast_expect(pc, ast_parse_expr); |
| 2727 | child->data.pointer_type.align_expr = align_expr; | 2657 | child->data.pointer_type.align_expr = align_expr; |
| 2728 | if (eat_token_if(pc, TokenIdColon) != nullptr) { | 2658 | if (eat_token_if(pc, TokenIdColon) != 0) { |
| 2729 | Token *bit_offset_start = expect_token(pc, TokenIdIntLiteral); | 2659 | TokenIndex bit_offset_start = expect_token(pc, TokenIdIntLiteral); |
| 2730 | expect_token(pc, TokenIdColon); | 2660 | expect_token(pc, TokenIdColon); |
| 2731 | Token *host_int_bytes = expect_token(pc, TokenIdIntLiteral); | 2661 | TokenIndex host_int_bytes = expect_token(pc, TokenIdIntLiteral); |
| 2732 | child->data.pointer_type.bit_offset_start = token_bigint(bit_offset_start); | 2662 | child->data.pointer_type.bit_offset_start = bit_offset_start; |
| 2733 | child->data.pointer_type.host_int_bytes = token_bigint(host_int_bytes); | 2663 | child->data.pointer_type.host_int_bytes = host_int_bytes; |
| 2734 | } | 2664 | } |
| 2735 | expect_token(pc, TokenIdRParen); | 2665 | expect_token(pc, TokenIdRParen); |
| 2736 | continue; | 2666 | continue; |
| 2737 | } | 2667 | } |
| 2738 | 2668 | ||
| 2739 | if (eat_token_if(pc, TokenIdKeywordConst) != nullptr) { | 2669 | if (eat_token_if(pc, TokenIdKeywordConst) != 0) { |
| 2740 | child->data.pointer_type.is_const = true; | 2670 | child->data.pointer_type.is_const = true; |
| 2741 | continue; | 2671 | continue; |
| 2742 | } | 2672 | } |
| 2743 | 2673 | ||
| 2744 | if (eat_token_if(pc, TokenIdKeywordVolatile) != nullptr) { | 2674 | if (eat_token_if(pc, TokenIdKeywordVolatile) != 0) { |
| 2745 | child->data.pointer_type.is_volatile = true; | 2675 | child->data.pointer_type.is_volatile = true; |
| 2746 | continue; | 2676 | continue; |
| 2747 | } | 2677 | } |
| ... | @@ -2756,8 +2686,8 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { | ... | @@ -2756,8 +2686,8 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { |
| 2756 | if (array != nullptr) { | 2686 | if (array != nullptr) { |
| 2757 | assert(array->type == NodeTypeArrayType); | 2687 | assert(array->type == NodeTypeArrayType); |
| 2758 | while (true) { | 2688 | while (true) { |
| 2759 | Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero); | 2689 | TokenIndex allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero); |
| 2760 | if (allowzero_token != nullptr) { | 2690 | if (allowzero_token != 0) { |
| 2761 | array->data.array_type.allow_zero_token = allowzero_token; | 2691 | array->data.array_type.allow_zero_token = allowzero_token; |
| 2762 | continue; | 2692 | continue; |
| 2763 | } | 2693 | } |
| ... | @@ -2768,12 +2698,12 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { | ... | @@ -2768,12 +2698,12 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { |
| 2768 | continue; | 2698 | continue; |
| 2769 | } | 2699 | } |
| 2770 | 2700 | ||
| 2771 | if (eat_token_if(pc, TokenIdKeywordConst) != nullptr) { | 2701 | if (eat_token_if(pc, TokenIdKeywordConst) != 0) { |
| 2772 | array->data.array_type.is_const = true; | 2702 | array->data.array_type.is_const = true; |
| 2773 | continue; | 2703 | continue; |
| 2774 | } | 2704 | } |
| 2775 | 2705 | ||
| 2776 | if (eat_token_if(pc, TokenIdKeywordVolatile) != nullptr) { | 2706 | if (eat_token_if(pc, TokenIdKeywordVolatile) != 0) { |
| 2777 | array->data.array_type.is_volatile = true; | 2707 | array->data.array_type.is_volatile = true; |
| 2778 | continue; | 2708 | continue; |
| 2779 | } | 2709 | } |
| ... | @@ -2793,14 +2723,14 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { | ... | @@ -2793,14 +2723,14 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { |
| 2793 | // / DOTASTERISK | 2723 | // / DOTASTERISK |
| 2794 | // / DOTQUESTIONMARK | 2724 | // / DOTQUESTIONMARK |
| 2795 | static AstNode *ast_parse_suffix_op(ParseContext *pc) { | 2725 | static AstNode *ast_parse_suffix_op(ParseContext *pc) { |
| 2796 | Token *lbracket = eat_token_if(pc, TokenIdLBracket); | 2726 | TokenIndex lbracket = eat_token_if(pc, TokenIdLBracket); |
| 2797 | if (lbracket != nullptr) { | 2727 | if (lbracket != 0) { |
| 2798 | AstNode *start = ast_expect(pc, ast_parse_expr); | 2728 | AstNode *start = ast_expect(pc, ast_parse_expr); |
| 2799 | AstNode *end = nullptr; | 2729 | AstNode *end = nullptr; |
| 2800 | if (eat_token_if(pc, TokenIdEllipsis2) != nullptr) { | 2730 | if (eat_token_if(pc, TokenIdEllipsis2) != 0) { |
| 2801 | AstNode *sentinel = nullptr; | 2731 | AstNode *sentinel = nullptr; |
| 2802 | end = ast_parse_expr(pc); | 2732 | end = ast_parse_expr(pc); |
| 2803 | if (eat_token_if(pc, TokenIdColon) != nullptr) { | 2733 | if (eat_token_if(pc, TokenIdColon) != 0) { |
| 2804 | sentinel = ast_parse_expr(pc); | 2734 | sentinel = ast_parse_expr(pc); |
| 2805 | } | 2735 | } |
| 2806 | expect_token(pc, TokenIdRBracket); | 2736 | expect_token(pc, TokenIdRBracket); |
| ... | @@ -2819,18 +2749,18 @@ static AstNode *ast_parse_suffix_op(ParseContext *pc) { | ... | @@ -2819,18 +2749,18 @@ static AstNode *ast_parse_suffix_op(ParseContext *pc) { |
| 2819 | return res; | 2749 | return res; |
| 2820 | } | 2750 | } |
| 2821 | 2751 | ||
| 2822 | Token *dot_asterisk = eat_token_if(pc, TokenIdDotStar); | 2752 | TokenIndex dot_asterisk = eat_token_if(pc, TokenIdDotStar); |
| 2823 | if (dot_asterisk != nullptr) | 2753 | if (dot_asterisk != 0) |
| 2824 | return ast_create_node(pc, NodeTypePtrDeref, dot_asterisk); | 2754 | return ast_create_node(pc, NodeTypePtrDeref, dot_asterisk); |
| 2825 | 2755 | ||
| 2826 | Token *dot = eat_token_if(pc, TokenIdDot); | 2756 | TokenIndex dot = eat_token_if(pc, TokenIdDot); |
| 2827 | if (dot != nullptr) { | 2757 | if (dot != 0) { |
| 2828 | if (eat_token_if(pc, TokenIdQuestion) != nullptr) | 2758 | if (eat_token_if(pc, TokenIdQuestion) != 0) |
| 2829 | return ast_create_node(pc, NodeTypeUnwrapOptional, dot); | 2759 | return ast_create_node(pc, NodeTypeUnwrapOptional, dot); |
| 2830 | 2760 | ||
| 2831 | Token *ident = expect_token(pc, TokenIdSymbol); | 2761 | TokenIndex ident = expect_token(pc, TokenIdIdentifier); |
| 2832 | AstNode *res = ast_create_node(pc, NodeTypeFieldAccessExpr, dot); | 2762 | AstNode *res = ast_create_node(pc, NodeTypeFieldAccessExpr, dot); |
| 2833 | res->data.field_access_expr.field_name = token_buf(ident); | 2763 | res->data.field_access_expr.field_name = token_buf(pc, ident); |
| 2834 | return res; | 2764 | return res; |
| 2835 | } | 2765 | } |
| 2836 | 2766 | ||
| ... | @@ -2839,8 +2769,8 @@ static AstNode *ast_parse_suffix_op(ParseContext *pc) { | ... | @@ -2839,8 +2769,8 @@ static AstNode *ast_parse_suffix_op(ParseContext *pc) { |
| 2839 | 2769 | ||
| 2840 | // FnCallArguments <- LPAREN ExprList RPAREN | 2770 | // FnCallArguments <- LPAREN ExprList RPAREN |
| 2841 | static AstNode *ast_parse_fn_call_arguments(ParseContext *pc) { | 2771 | static AstNode *ast_parse_fn_call_arguments(ParseContext *pc) { |
| 2842 | Token *paren = eat_token_if(pc, TokenIdLParen); | 2772 | TokenIndex paren = eat_token_if(pc, TokenIdLParen); |
| 2843 | if (paren == nullptr) | 2773 | if (paren == 0) |
| 2844 | return nullptr; | 2774 | return nullptr; |
| 2845 | 2775 | ||
| 2846 | ZigList<AstNode *> params = ast_parse_list(pc, TokenIdComma, ast_parse_expr); | 2776 | ZigList<AstNode *> params = ast_parse_list(pc, TokenIdComma, ast_parse_expr); |
| ... | @@ -2854,14 +2784,14 @@ static AstNode *ast_parse_fn_call_arguments(ParseContext *pc) { | ... | @@ -2854,14 +2784,14 @@ static AstNode *ast_parse_fn_call_arguments(ParseContext *pc) { |
| 2854 | 2784 | ||
| 2855 | // ArrayTypeStart <- LBRACKET Expr? RBRACKET | 2785 | // ArrayTypeStart <- LBRACKET Expr? RBRACKET |
| 2856 | static AstNode *ast_parse_array_type_start(ParseContext *pc) { | 2786 | static AstNode *ast_parse_array_type_start(ParseContext *pc) { |
| 2857 | Token *lbracket = eat_token_if(pc, TokenIdLBracket); | 2787 | TokenIndex lbracket = eat_token_if(pc, TokenIdLBracket); |
| 2858 | if (lbracket == nullptr) | 2788 | if (lbracket == 0) |
| 2859 | return nullptr; | 2789 | return nullptr; |
| 2860 | 2790 | ||
| 2861 | AstNode *size = ast_parse_expr(pc); | 2791 | AstNode *size = ast_parse_expr(pc); |
| 2862 | AstNode *sentinel = nullptr; | 2792 | AstNode *sentinel = nullptr; |
| 2863 | Token *colon = eat_token_if(pc, TokenIdColon); | 2793 | TokenIndex colon = eat_token_if(pc, TokenIdColon); |
| 2864 | if (colon != nullptr) { | 2794 | if (colon != 0) { |
| 2865 | sentinel = ast_expect(pc, ast_parse_expr); | 2795 | sentinel = ast_expect(pc, ast_parse_expr); |
| 2866 | } | 2796 | } |
| 2867 | expect_token(pc, TokenIdRBracket); | 2797 | expect_token(pc, TokenIdRBracket); |
| ... | @@ -2879,10 +2809,10 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) { | ... | @@ -2879,10 +2809,10 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) { |
| 2879 | static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { | 2809 | static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { |
| 2880 | AstNode *sentinel = nullptr; | 2810 | AstNode *sentinel = nullptr; |
| 2881 | 2811 | ||
| 2882 | Token *asterisk = eat_token_if(pc, TokenIdStar); | 2812 | TokenIndex asterisk = eat_token_if(pc, TokenIdStar); |
| 2883 | if (asterisk != nullptr) { | 2813 | if (asterisk != 0) { |
| 2884 | Token *colon = eat_token_if(pc, TokenIdColon); | 2814 | TokenIndex colon = eat_token_if(pc, TokenIdColon); |
| 2885 | if (colon != nullptr) { | 2815 | if (colon != 0) { |
| 2886 | sentinel = ast_expect(pc, ast_parse_expr); | 2816 | sentinel = ast_expect(pc, ast_parse_expr); |
| 2887 | } | 2817 | } |
| 2888 | AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk); | 2818 | AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk); |
| ... | @@ -2891,10 +2821,10 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { | ... | @@ -2891,10 +2821,10 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { |
| 2891 | return res; | 2821 | return res; |
| 2892 | } | 2822 | } |
| 2893 | 2823 | ||
| 2894 | Token *asterisk2 = eat_token_if(pc, TokenIdStarStar); | 2824 | TokenIndex asterisk2 = eat_token_if(pc, TokenIdStarStar); |
| 2895 | if (asterisk2 != nullptr) { | 2825 | if (asterisk2 != 0) { |
| 2896 | Token *colon = eat_token_if(pc, TokenIdColon); | 2826 | TokenIndex colon = eat_token_if(pc, TokenIdColon); |
| 2897 | if (colon != nullptr) { | 2827 | if (colon != 0) { |
| 2898 | sentinel = ast_expect(pc, ast_parse_expr); | 2828 | sentinel = ast_expect(pc, ast_parse_expr); |
| 2899 | } | 2829 | } |
| 2900 | AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk2); | 2830 | AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk2); |
| ... | @@ -2906,15 +2836,15 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { | ... | @@ -2906,15 +2836,15 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { |
| 2906 | return res; | 2836 | return res; |
| 2907 | } | 2837 | } |
| 2908 | 2838 | ||
| 2909 | Token *lbracket = eat_token_if(pc, TokenIdLBracket); | 2839 | TokenIndex lbracket = eat_token_if(pc, TokenIdLBracket); |
| 2910 | if (lbracket != nullptr) { | 2840 | if (lbracket != 0) { |
| 2911 | Token *star = eat_token_if(pc, TokenIdStar); | 2841 | TokenIndex star = eat_token_if(pc, TokenIdStar); |
| 2912 | if (star == nullptr) { | 2842 | if (star == 0) { |
| 2913 | put_back_token(pc); | 2843 | put_back_token(pc); |
| 2914 | } else { | 2844 | } else { |
| 2915 | Token *c_tok = eat_token_if(pc, TokenIdSymbol); | 2845 | TokenIndex c_tok = eat_token_if(pc, TokenIdIdentifier); |
| 2916 | if (c_tok != nullptr) { | 2846 | if (c_tok != 0) { |
| 2917 | if (!buf_eql_str(token_buf(c_tok), "c")) { | 2847 | if (!buf_eql_str(token_buf(pc, c_tok), "c")) { |
| 2918 | put_back_token(pc); // c symbol | 2848 | put_back_token(pc); // c symbol |
| 2919 | } else { | 2849 | } else { |
| 2920 | expect_token(pc, TokenIdRBracket); | 2850 | expect_token(pc, TokenIdRBracket); |
| ... | @@ -2924,8 +2854,8 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { | ... | @@ -2924,8 +2854,8 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { |
| 2924 | } | 2854 | } |
| 2925 | } | 2855 | } |
| 2926 | 2856 | ||
| 2927 | Token *colon = eat_token_if(pc, TokenIdColon); | 2857 | TokenIndex colon = eat_token_if(pc, TokenIdColon); |
| 2928 | if (colon != nullptr) { | 2858 | if (colon != 0) { |
| 2929 | sentinel = ast_expect(pc, ast_parse_expr); | 2859 | sentinel = ast_expect(pc, ast_parse_expr); |
| 2930 | } | 2860 | } |
| 2931 | expect_token(pc, TokenIdRBracket); | 2861 | expect_token(pc, TokenIdRBracket); |
| ... | @@ -2951,9 +2881,7 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) { | ... | @@ -2951,9 +2881,7 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) { |
| 2951 | 2881 | ||
| 2952 | res->data.container_decl.fields = members.fields; | 2882 | res->data.container_decl.fields = members.fields; |
| 2953 | res->data.container_decl.decls = members.decls; | 2883 | res->data.container_decl.decls = members.decls; |
| 2954 | if (buf_len(&members.doc_comments) != 0) { | 2884 | res->data.container_decl.doc_comments = members.doc_comments; |
| 2955 | res->data.container_decl.doc_comments = members.doc_comments; | ||
| 2956 | } | ||
| 2957 | return res; | 2885 | return res; |
| 2958 | } | 2886 | } |
| 2959 | 2887 | ||
| ... | @@ -2963,8 +2891,8 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) { | ... | @@ -2963,8 +2891,8 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) { |
| 2963 | // / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? | 2891 | // / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? |
| 2964 | // / KEYWORD_opaque | 2892 | // / KEYWORD_opaque |
| 2965 | static AstNode *ast_parse_container_decl_type(ParseContext *pc) { | 2893 | static AstNode *ast_parse_container_decl_type(ParseContext *pc) { |
| 2966 | Token *first = eat_token_if(pc, TokenIdKeywordStruct); | 2894 | TokenIndex first = eat_token_if(pc, TokenIdKeywordStruct); |
| 2967 | if (first != nullptr) { | 2895 | if (first != 0) { |
| 2968 | AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first); | 2896 | AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first); |
| 2969 | res->data.container_decl.init_arg_expr = nullptr; | 2897 | res->data.container_decl.init_arg_expr = nullptr; |
| 2970 | res->data.container_decl.kind = ContainerKindStruct; | 2898 | res->data.container_decl.kind = ContainerKindStruct; |
| ... | @@ -2972,7 +2900,7 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { | ... | @@ -2972,7 +2900,7 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { |
| 2972 | } | 2900 | } |
| 2973 | 2901 | ||
| 2974 | first = eat_token_if(pc, TokenIdKeywordOpaque); | 2902 | first = eat_token_if(pc, TokenIdKeywordOpaque); |
| 2975 | if (first != nullptr) { | 2903 | if (first != 0) { |
| 2976 | AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first); | 2904 | AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first); |
| 2977 | res->data.container_decl.init_arg_expr = nullptr; | 2905 | res->data.container_decl.init_arg_expr = nullptr; |
| 2978 | res->data.container_decl.kind = ContainerKindOpaque; | 2906 | res->data.container_decl.kind = ContainerKindOpaque; |
| ... | @@ -2980,9 +2908,9 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { | ... | @@ -2980,9 +2908,9 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { |
| 2980 | } | 2908 | } |
| 2981 | 2909 | ||
| 2982 | first = eat_token_if(pc, TokenIdKeywordEnum); | 2910 | first = eat_token_if(pc, TokenIdKeywordEnum); |
| 2983 | if (first != nullptr) { | 2911 | if (first != 0) { |
| 2984 | AstNode *init_arg_expr = nullptr; | 2912 | AstNode *init_arg_expr = nullptr; |
| 2985 | if (eat_token_if(pc, TokenIdLParen) != nullptr) { | 2913 | if (eat_token_if(pc, TokenIdLParen) != 0) { |
| 2986 | init_arg_expr = ast_expect(pc, ast_parse_expr); | 2914 | init_arg_expr = ast_expect(pc, ast_parse_expr); |
| 2987 | expect_token(pc, TokenIdRParen); | 2915 | expect_token(pc, TokenIdRParen); |
| 2988 | } | 2916 | } |
| ... | @@ -2993,13 +2921,13 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { | ... | @@ -2993,13 +2921,13 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { |
| 2993 | } | 2921 | } |
| 2994 | 2922 | ||
| 2995 | first = eat_token_if(pc, TokenIdKeywordUnion); | 2923 | first = eat_token_if(pc, TokenIdKeywordUnion); |
| 2996 | if (first != nullptr) { | 2924 | if (first != 0) { |
| 2997 | AstNode *init_arg_expr = nullptr; | 2925 | AstNode *init_arg_expr = nullptr; |
| 2998 | bool auto_enum = false; | 2926 | bool auto_enum = false; |
| 2999 | if (eat_token_if(pc, TokenIdLParen) != nullptr) { | 2927 | if (eat_token_if(pc, TokenIdLParen) != 0) { |
| 3000 | if (eat_token_if(pc, TokenIdKeywordEnum) != nullptr) { | 2928 | if (eat_token_if(pc, TokenIdKeywordEnum) != 0) { |
| 3001 | auto_enum = true; | 2929 | auto_enum = true; |
| 3002 | if (eat_token_if(pc, TokenIdLParen) != nullptr) { | 2930 | if (eat_token_if(pc, TokenIdLParen) != 0) { |
| 3003 | init_arg_expr = ast_expect(pc, ast_parse_expr); | 2931 | init_arg_expr = ast_expect(pc, ast_parse_expr); |
| 3004 | expect_token(pc, TokenIdRParen); | 2932 | expect_token(pc, TokenIdRParen); |
| 3005 | } | 2933 | } |
| ... | @@ -3022,7 +2950,7 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { | ... | @@ -3022,7 +2950,7 @@ static AstNode *ast_parse_container_decl_type(ParseContext *pc) { |
| 3022 | 2950 | ||
| 3023 | // ByteAlign <- KEYWORD_align LPAREN Expr RPAREN | 2951 | // ByteAlign <- KEYWORD_align LPAREN Expr RPAREN |
| 3024 | static AstNode *ast_parse_byte_align(ParseContext *pc) { | 2952 | static AstNode *ast_parse_byte_align(ParseContext *pc) { |
| 3025 | if (eat_token_if(pc, TokenIdKeywordAlign) == nullptr) | 2953 | if (eat_token_if(pc, TokenIdKeywordAlign) == 0) |
| 3026 | return nullptr; | 2954 | return nullptr; |
| 3027 | 2955 | ||
| 3028 | expect_token(pc, TokenIdLParen); | 2956 | expect_token(pc, TokenIdLParen); |
| ... | @@ -3103,7 +3031,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont | ... | @@ -3103,7 +3031,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 3103 | case NodeTypeCharLiteral: | 3031 | case NodeTypeCharLiteral: |
| 3104 | // none | 3032 | // none |
| 3105 | break; | 3033 | break; |
| 3106 | case NodeTypeSymbol: | 3034 | case NodeTypeIdentifier: |
| 3107 | // none | 3035 | // none |
| 3108 | break; | 3036 | break; |
| 3109 | case NodeTypePrefixOpExpr: | 3037 | case NodeTypePrefixOpExpr: |
| ... | @@ -3264,3 +3192,403 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont | ... | @@ -3264,3 +3192,403 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 3264 | break; | 3192 | break; |
| 3265 | } | 3193 | } |
| 3266 | } | 3194 | } |
| 3195 | |||
| 3196 | Error source_string_literal_buf(const char *source, Buf *out, size_t *bad_index) { | ||
| 3197 | size_t byte_offset = 0; | ||
| 3198 | |||
| 3199 | assert(source[byte_offset] == '"'); | ||
| 3200 | byte_offset += 1; | ||
| 3201 | |||
| 3202 | buf_resize(out, 0); | ||
| 3203 | |||
| 3204 | uint32_t codepoint; | ||
| 3205 | |||
| 3206 | enum { | ||
| 3207 | StateStart, | ||
| 3208 | StateBackslash, | ||
| 3209 | StateUnicodeLBrace, | ||
| 3210 | StateUnicodeDigit, | ||
| 3211 | } state = StateStart; | ||
| 3212 | for (;;byte_offset += 1) { | ||
| 3213 | switch (state) { | ||
| 3214 | case StateStart: switch (source[byte_offset]) { | ||
| 3215 | case '\\': | ||
| 3216 | state = StateBackslash; | ||
| 3217 | continue; | ||
| 3218 | case '\n': | ||
| 3219 | *bad_index = byte_offset; | ||
| 3220 | return ErrorInvalidCharacter; | ||
| 3221 | case '"': | ||
| 3222 | return ErrorNone; | ||
| 3223 | default: | ||
| 3224 | buf_append_char(out, source[byte_offset]); | ||
| 3225 | continue; | ||
| 3226 | } | ||
| 3227 | case StateBackslash: switch (source[byte_offset]) { | ||
| 3228 | case 'n': | ||
| 3229 | buf_append_char(out, '\n'); | ||
| 3230 | state = StateStart; | ||
| 3231 | continue; | ||
| 3232 | case 'r': | ||
| 3233 | buf_append_char(out, '\r'); | ||
| 3234 | state = StateStart; | ||
| 3235 | continue; | ||
| 3236 | case '\\': | ||
| 3237 | buf_append_char(out, '\\'); | ||
| 3238 | state = StateStart; | ||
| 3239 | continue; | ||
| 3240 | case 't': | ||
| 3241 | buf_append_char(out, '\t'); | ||
| 3242 | state = StateStart; | ||
| 3243 | continue; | ||
| 3244 | case '\'': | ||
| 3245 | buf_append_char(out, '\''); | ||
| 3246 | state = StateStart; | ||
| 3247 | continue; | ||
| 3248 | case '"': | ||
| 3249 | buf_append_char(out, '"'); | ||
| 3250 | state = StateStart; | ||
| 3251 | continue; | ||
| 3252 | case 'x': { | ||
| 3253 | byte_offset += 1; | ||
| 3254 | uint8_t digit1; | ||
| 3255 | if (source[byte_offset] >= '0' && source[byte_offset] <= '9') { | ||
| 3256 | digit1 = source[byte_offset] - '0'; | ||
| 3257 | } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') { | ||
| 3258 | digit1 = source[byte_offset] - 'a' + 10; | ||
| 3259 | } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') { | ||
| 3260 | digit1 = source[byte_offset] - 'A' + 10; | ||
| 3261 | } else { | ||
| 3262 | *bad_index = byte_offset; | ||
| 3263 | return ErrorInvalidCharacter; | ||
| 3264 | } | ||
| 3265 | |||
| 3266 | byte_offset += 1; | ||
| 3267 | uint8_t digit0; | ||
| 3268 | if (source[byte_offset] >= '0' && source[byte_offset] <= '9') { | ||
| 3269 | digit0 = source[byte_offset] - '0'; | ||
| 3270 | } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') { | ||
| 3271 | digit0 = source[byte_offset] - 'a' + 10; | ||
| 3272 | } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') { | ||
| 3273 | digit0 = source[byte_offset] - 'A' + 10; | ||
| 3274 | } else { | ||
| 3275 | *bad_index = byte_offset; | ||
| 3276 | return ErrorInvalidCharacter; | ||
| 3277 | } | ||
| 3278 | |||
| 3279 | buf_append_char(out, digit1 * 16 + digit0); | ||
| 3280 | state = StateStart; | ||
| 3281 | continue; | ||
| 3282 | } | ||
| 3283 | case 'u': | ||
| 3284 | state = StateUnicodeLBrace; | ||
| 3285 | continue; | ||
| 3286 | default: | ||
| 3287 | *bad_index = byte_offset; | ||
| 3288 | return ErrorInvalidCharacter; | ||
| 3289 | } | ||
| 3290 | case StateUnicodeLBrace: switch (source[byte_offset]) { | ||
| 3291 | case '{': | ||
| 3292 | state = StateUnicodeDigit; | ||
| 3293 | codepoint = 0; | ||
| 3294 | continue; | ||
| 3295 | default: | ||
| 3296 | *bad_index = byte_offset; | ||
| 3297 | return ErrorInvalidCharacter; | ||
| 3298 | } | ||
| 3299 | case StateUnicodeDigit: { | ||
| 3300 | uint8_t digit; | ||
| 3301 | if (source[byte_offset] >= '0' && source[byte_offset] <= '9') { | ||
| 3302 | digit = source[byte_offset] - '0'; | ||
| 3303 | } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') { | ||
| 3304 | digit = source[byte_offset] - 'a' + 10; | ||
| 3305 | } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') { | ||
| 3306 | digit = source[byte_offset] - 'A' + 10; | ||
| 3307 | } else if (source[byte_offset] == '}') { | ||
| 3308 | if (codepoint < 0x80) { | ||
| 3309 | buf_append_char(out, codepoint); | ||
| 3310 | } else if (codepoint < 0x800) { | ||
| 3311 | buf_append_char(out, 0xc0 | (codepoint >> 6)); | ||
| 3312 | buf_append_char(out, 0x80 | (codepoint & 0x3f)); | ||
| 3313 | } else if (codepoint < 0x10000) { | ||
| 3314 | buf_append_char(out, 0xe0 | (codepoint >> 12)); | ||
| 3315 | buf_append_char(out, 0x80 | ((codepoint >> 6) & 0x3f)); | ||
| 3316 | buf_append_char(out, 0x80 | (codepoint & 0x3f)); | ||
| 3317 | } else if (codepoint < 0x110000) { | ||
| 3318 | buf_append_char(out, 0xf0 | (codepoint >> 18)); | ||
| 3319 | buf_append_char(out, 0x80 | ((codepoint >> 12) & 0x3f)); | ||
| 3320 | buf_append_char(out, 0x80 | ((codepoint >> 6) & 0x3f)); | ||
| 3321 | buf_append_char(out, 0x80 | (codepoint & 0x3f)); | ||
| 3322 | } else { | ||
| 3323 | *bad_index = byte_offset; | ||
| 3324 | return ErrorUnicodePointTooLarge; | ||
| 3325 | } | ||
| 3326 | state = StateStart; | ||
| 3327 | continue; | ||
| 3328 | } else { | ||
| 3329 | *bad_index = byte_offset; | ||
| 3330 | return ErrorInvalidCharacter; | ||
| 3331 | } | ||
| 3332 | codepoint = codepoint * 16 + digit; | ||
| 3333 | continue; | ||
| 3334 | } | ||
| 3335 | } | ||
| 3336 | } | ||
| 3337 | zig_unreachable(); | ||
| 3338 | } | ||
| 3339 | |||
| 3340 | static uint32_t utf8_code_point(const uint8_t *bytes) { | ||
| 3341 | if (bytes[0] <= 0x7f) { | ||
| 3342 | return bytes[0]; | ||
| 3343 | } else if (bytes[0] >= 0xc0 && bytes[0] <= 0xdf) { | ||
| 3344 | uint32_t result = bytes[0] & 0x1f; | ||
| 3345 | result <<= 6; | ||
| 3346 | result |= bytes[1] & 0x3f; | ||
| 3347 | return result; | ||
| 3348 | } else if (bytes[0] >= 0xe0 && bytes[0] <= 0xef) { | ||
| 3349 | uint32_t result = bytes[0] & 0xf; | ||
| 3350 | |||
| 3351 | result <<= 6; | ||
| 3352 | result |= bytes[1] & 0x3f; | ||
| 3353 | |||
| 3354 | result <<= 6; | ||
| 3355 | result |= bytes[2] & 0x3f; | ||
| 3356 | |||
| 3357 | return result; | ||
| 3358 | } else if (bytes[0] >= 0xf0 && bytes[0] <= 0xf7) { | ||
| 3359 | uint32_t result = bytes[0] & 0x7; | ||
| 3360 | |||
| 3361 | result <<= 6; | ||
| 3362 | result |= bytes[1] & 0x3f; | ||
| 3363 | |||
| 3364 | result <<= 6; | ||
| 3365 | result |= bytes[2] & 0x3f; | ||
| 3366 | |||
| 3367 | result <<= 6; | ||
| 3368 | result |= bytes[3] & 0x3f; | ||
| 3369 | |||
| 3370 | return result; | ||
| 3371 | } else { | ||
| 3372 | zig_unreachable(); | ||
| 3373 | } | ||
| 3374 | } | ||
| 3375 | |||
| 3376 | Error source_char_literal(const char *source, uint32_t *result, size_t *bad_index) { | ||
| 3377 | if (source[0] != '\\') { | ||
| 3378 | *result = utf8_code_point((const uint8_t *)source); | ||
| 3379 | return ErrorNone; | ||
| 3380 | } | ||
| 3381 | |||
| 3382 | uint32_t byte_offset = 1; | ||
| 3383 | uint32_t codepoint; | ||
| 3384 | |||
| 3385 | enum State { | ||
| 3386 | StateBackslash, | ||
| 3387 | StateUnicodeLBrace, | ||
| 3388 | StateUnicodeDigit, | ||
| 3389 | } state = StateBackslash; | ||
| 3390 | |||
| 3391 | for (;;byte_offset += 1) { | ||
| 3392 | switch (state) { | ||
| 3393 | case StateBackslash: switch (source[byte_offset]) { | ||
| 3394 | case 'n': | ||
| 3395 | *result = '\n'; | ||
| 3396 | return ErrorNone; | ||
| 3397 | case 'r': | ||
| 3398 | *result = '\r'; | ||
| 3399 | return ErrorNone; | ||
| 3400 | case '\\': | ||
| 3401 | *result = '\\'; | ||
| 3402 | return ErrorNone; | ||
| 3403 | case 't': | ||
| 3404 | *result = '\t'; | ||
| 3405 | return ErrorNone; | ||
| 3406 | case '\'': | ||
| 3407 | *result = '\''; | ||
| 3408 | return ErrorNone; | ||
| 3409 | case '"': | ||
| 3410 | *result = '"'; | ||
| 3411 | return ErrorNone; | ||
| 3412 | case 'x': { | ||
| 3413 | byte_offset += 1; | ||
| 3414 | uint8_t digit1; | ||
| 3415 | if (source[byte_offset] >= '0' && source[byte_offset] <= '9') { | ||
| 3416 | digit1 = source[byte_offset] - '0'; | ||
| 3417 | } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') { | ||
| 3418 | digit1 = source[byte_offset] - 'a' + 10; | ||
| 3419 | } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') { | ||
| 3420 | digit1 = source[byte_offset] - 'A' + 10; | ||
| 3421 | } else { | ||
| 3422 | *bad_index = byte_offset; | ||
| 3423 | return ErrorInvalidCharacter; | ||
| 3424 | } | ||
| 3425 | |||
| 3426 | byte_offset += 1; | ||
| 3427 | uint8_t digit0; | ||
| 3428 | if (source[byte_offset] >= '0' && source[byte_offset] <= '9') { | ||
| 3429 | digit0 = source[byte_offset] - '0'; | ||
| 3430 | } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') { | ||
| 3431 | digit0 = source[byte_offset] - 'a' + 10; | ||
| 3432 | } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') { | ||
| 3433 | digit0 = source[byte_offset] - 'A' + 10; | ||
| 3434 | } else { | ||
| 3435 | *bad_index = byte_offset; | ||
| 3436 | return ErrorInvalidCharacter; | ||
| 3437 | } | ||
| 3438 | |||
| 3439 | *result = digit1 * 16 + digit0; | ||
| 3440 | return ErrorNone; | ||
| 3441 | } | ||
| 3442 | case 'u': | ||
| 3443 | state = StateUnicodeLBrace; | ||
| 3444 | continue; | ||
| 3445 | default: | ||
| 3446 | *bad_index = byte_offset; | ||
| 3447 | return ErrorInvalidCharacter; | ||
| 3448 | } | ||
| 3449 | case StateUnicodeLBrace: switch (source[byte_offset]) { | ||
| 3450 | case '{': | ||
| 3451 | state = StateUnicodeDigit; | ||
| 3452 | codepoint = 0; | ||
| 3453 | continue; | ||
| 3454 | default: | ||
| 3455 | *bad_index = byte_offset; | ||
| 3456 | return ErrorInvalidCharacter; | ||
| 3457 | } | ||
| 3458 | case StateUnicodeDigit: { | ||
| 3459 | uint8_t digit; | ||
| 3460 | if (source[byte_offset] >= '0' && source[byte_offset] <= '9') { | ||
| 3461 | digit = source[byte_offset] - '0'; | ||
| 3462 | } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') { | ||
| 3463 | digit = source[byte_offset] - 'a' + 10; | ||
| 3464 | } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') { | ||
| 3465 | digit = source[byte_offset] - 'A' + 10; | ||
| 3466 | } else if (source[byte_offset] == '}') { | ||
| 3467 | if (codepoint < 0x110000) { | ||
| 3468 | *result = codepoint; | ||
| 3469 | return ErrorNone; | ||
| 3470 | } else { | ||
| 3471 | *bad_index = byte_offset; | ||
| 3472 | return ErrorUnicodePointTooLarge; | ||
| 3473 | } | ||
| 3474 | } else { | ||
| 3475 | *bad_index = byte_offset; | ||
| 3476 | return ErrorInvalidCharacter; | ||
| 3477 | } | ||
| 3478 | codepoint = codepoint * 16 + digit; | ||
| 3479 | continue; | ||
| 3480 | } | ||
| 3481 | } | ||
| 3482 | } | ||
| 3483 | } | ||
| 3484 | |||
| 3485 | |||
| 3486 | Buf *token_identifier_buf(RootStruct *root_struct, TokenIndex token) { | ||
| 3487 | Error err; | ||
| 3488 | const char *source = buf_ptr(root_struct->source_code); | ||
| 3489 | size_t byte_offset = root_struct->token_locs[token].offset; | ||
| 3490 | if (root_struct->token_ids[token] == TokenIdBuiltin) { | ||
| 3491 | byte_offset += 1; | ||
| 3492 | } else { | ||
| 3493 | assert(root_struct->token_ids[token] == TokenIdIdentifier); | ||
| 3494 | } | ||
| 3495 | assert(source[byte_offset] != '.'); // wrong token index | ||
| 3496 | |||
| 3497 | if (source[byte_offset] == '@') { | ||
| 3498 | size_t bad_index; | ||
| 3499 | Buf *str = buf_alloc(); | ||
| 3500 | if ((err = source_string_literal_buf(source + byte_offset + 1, str, &bad_index))) { | ||
| 3501 | ast_error_offset(root_struct, ErrColorAuto, token, bad_index + 1, | ||
| 3502 | buf_create_from_str("invalid string literal character")); | ||
| 3503 | } | ||
| 3504 | return str; | ||
| 3505 | } else { | ||
| 3506 | size_t start = byte_offset; | ||
| 3507 | for (;; byte_offset += 1) { | ||
| 3508 | if (source[byte_offset] == 0) break; | ||
| 3509 | if ((source[byte_offset] >= 'a' && source[byte_offset] <= 'z') || | ||
| 3510 | (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') || | ||
| 3511 | (source[byte_offset] >= '0' && source[byte_offset] <= '9') || | ||
| 3512 | source[byte_offset] == '_') | ||
| 3513 | { | ||
| 3514 | continue; | ||
| 3515 | } | ||
| 3516 | break; | ||
| 3517 | } | ||
| 3518 | return buf_create_from_mem(source + start, byte_offset - start); | ||
| 3519 | } | ||
| 3520 | } | ||
| 3521 | |||
| 3522 | Buf *node_identifier_buf(AstNode *node) { | ||
| 3523 | assert(node->type == NodeTypeIdentifier); | ||
| 3524 | // Currently, stage1 runs astgen for every comptime function call, | ||
| 3525 | // resulting the allocation here wasting memory. As a workaround until | ||
| 3526 | // the code is adjusted to make astgen run only once per source node, | ||
| 3527 | // we memoize the result into the AST here. | ||
| 3528 | if (node->data.identifier.name == nullptr) { | ||
| 3529 | RootStruct *root_struct = node->owner->data.structure.root_struct; | ||
| 3530 | node->data.identifier.name = token_identifier_buf(root_struct, node->main_token); | ||
| 3531 | } | ||
| 3532 | return node->data.identifier.name; | ||
| 3533 | } | ||
| 3534 | |||
| 3535 | void token_number_literal_bigint(RootStruct *root_struct, BigInt *result, TokenIndex token) { | ||
| 3536 | const char *source = buf_ptr(root_struct->source_code); | ||
| 3537 | uint32_t byte_offset = root_struct->token_locs[token].offset; | ||
| 3538 | |||
| 3539 | bigint_init_unsigned(result, 0); | ||
| 3540 | BigInt radix_bi; | ||
| 3541 | |||
| 3542 | if (source[byte_offset] == '0') { | ||
| 3543 | byte_offset += 1; | ||
| 3544 | switch (source[byte_offset]) { | ||
| 3545 | case 'b': | ||
| 3546 | byte_offset += 1; | ||
| 3547 | bigint_init_unsigned(&radix_bi, 2); | ||
| 3548 | break; | ||
| 3549 | case 'o': | ||
| 3550 | byte_offset += 1; | ||
| 3551 | bigint_init_unsigned(&radix_bi, 8); | ||
| 3552 | break; | ||
| 3553 | case 'x': | ||
| 3554 | byte_offset += 1; | ||
| 3555 | bigint_init_unsigned(&radix_bi, 16); | ||
| 3556 | break; | ||
| 3557 | default: | ||
| 3558 | bigint_init_unsigned(&radix_bi, 10); | ||
| 3559 | break; | ||
| 3560 | } | ||
| 3561 | } else { | ||
| 3562 | bigint_init_unsigned(&radix_bi, 10); | ||
| 3563 | } | ||
| 3564 | |||
| 3565 | BigInt digit_value_bi = {}; | ||
| 3566 | BigInt multiplied = {}; | ||
| 3567 | |||
| 3568 | for (;source[byte_offset] != 0; byte_offset += 1) { | ||
| 3569 | uint8_t digit; | ||
| 3570 | if (source[byte_offset] >= '0' && source[byte_offset] <= '9') { | ||
| 3571 | digit = source[byte_offset] - '0'; | ||
| 3572 | } else if (source[byte_offset] >= 'a' && source[byte_offset] <= 'z') { | ||
| 3573 | digit = source[byte_offset] - 'a' + 10; | ||
| 3574 | } else if (source[byte_offset] >= 'A' && source[byte_offset] <= 'Z') { | ||
| 3575 | digit = source[byte_offset] - 'A' + 10; | ||
| 3576 | } else if (source[byte_offset] == '_') { | ||
| 3577 | continue; | ||
| 3578 | } else { | ||
| 3579 | break; | ||
| 3580 | } | ||
| 3581 | bigint_deinit(&digit_value_bi); | ||
| 3582 | bigint_init_unsigned(&digit_value_bi, digit); | ||
| 3583 | |||
| 3584 | bigint_deinit(&multiplied); | ||
| 3585 | bigint_mul(&multiplied, result, &radix_bi); | ||
| 3586 | |||
| 3587 | bigint_add(result, &multiplied, &digit_value_bi); | ||
| 3588 | } | ||
| 3589 | |||
| 3590 | bigint_deinit(&digit_value_bi); | ||
| 3591 | bigint_deinit(&multiplied); | ||
| 3592 | bigint_deinit(&radix_bi); | ||
| 3593 | } | ||
| 3594 |
src/stage1/parser.hpp+10-5| ... | @@ -12,14 +12,19 @@ | ... | @@ -12,14 +12,19 @@ |
| 12 | #include "tokenizer.hpp" | 12 | #include "tokenizer.hpp" |
| 13 | #include "errmsg.hpp" | 13 | #include "errmsg.hpp" |
| 14 | 14 | ||
| 15 | ATTRIBUTE_PRINTF(2, 3) | 15 | AstNode * ast_parse(Buf *buf, ZigType *owner, ErrColor err_color); |
| 16 | void ast_token_error(Token *token, const char *format, ...); | ||
| 17 | |||
| 18 | |||
| 19 | AstNode * ast_parse(Buf *buf, ZigList<Token> *tokens, ZigType *owner, ErrColor err_color); | ||
| 20 | 16 | ||
| 21 | void ast_print(AstNode *node, int indent); | 17 | void ast_print(AstNode *node, int indent); |
| 22 | 18 | ||
| 23 | void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context); | 19 | void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context); |
| 24 | 20 | ||
| 21 | Buf *node_identifier_buf(AstNode *node); | ||
| 22 | |||
| 23 | Buf *token_identifier_buf(RootStruct *root_struct, TokenIndex token); | ||
| 24 | |||
| 25 | void token_number_literal_bigint(RootStruct *root_struct, BigInt *result, TokenIndex token); | ||
| 26 | |||
| 27 | Error source_string_literal_buf(const char *source, Buf *out, size_t *bad_index); | ||
| 28 | Error source_char_literal(const char *source, uint32_t *out, size_t *bad_index); | ||
| 29 | |||
| 25 | #endif | 30 | #endif |
src/stage1/stage2.h+2| ... | @@ -112,6 +112,8 @@ enum Error { | ... | @@ -112,6 +112,8 @@ enum Error { |
| 112 | ErrorZigIsTheCCompiler, | 112 | ErrorZigIsTheCCompiler, |
| 113 | ErrorFileBusy, | 113 | ErrorFileBusy, |
| 114 | ErrorLocked, | 114 | ErrorLocked, |
| 115 | ErrorInvalidCharacter, | ||
| 116 | ErrorUnicodePointTooLarge, | ||
| 115 | }; | 117 | }; |
| 116 | 118 | ||
| 117 | // ABI warning | 119 | // ABI warning |
src/stage1/tokenizer.cpp+867-979| ... | @@ -30,18 +30,28 @@ | ... | @@ -30,18 +30,28 @@ |
| 30 | case '7': \ | 30 | case '7': \ |
| 31 | case '8': \ | 31 | case '8': \ |
| 32 | case '9' | 32 | case '9' |
| 33 | |||
| 33 | #define DIGIT \ | 34 | #define DIGIT \ |
| 34 | '0': \ | 35 | '0': \ |
| 35 | case DIGIT_NON_ZERO | 36 | case DIGIT_NON_ZERO |
| 36 | 37 | ||
| 37 | #define ALPHA \ | 38 | #define HEXDIGIT \ |
| 38 | 'a': \ | 39 | 'a': \ |
| 39 | case 'b': \ | 40 | case 'b': \ |
| 40 | case 'c': \ | 41 | case 'c': \ |
| 41 | case 'd': \ | 42 | case 'd': \ |
| 42 | case 'e': \ | 43 | case 'e': \ |
| 43 | case 'f': \ | 44 | case 'f': \ |
| 44 | case 'g': \ | 45 | case 'A': \ |
| 46 | case 'B': \ | ||
| 47 | case 'C': \ | ||
| 48 | case 'D': \ | ||
| 49 | case 'E': \ | ||
| 50 | case 'F': \ | ||
| 51 | case DIGIT | ||
| 52 | |||
| 53 | #define ALPHA_EXCEPT_HEX_P_O_X \ | ||
| 54 | 'g': \ | ||
| 45 | case 'h': \ | 55 | case 'h': \ |
| 46 | case 'i': \ | 56 | case 'i': \ |
| 47 | case 'j': \ | 57 | case 'j': \ |
| ... | @@ -49,8 +59,6 @@ | ... | @@ -49,8 +59,6 @@ |
| 49 | case 'l': \ | 59 | case 'l': \ |
| 50 | case 'm': \ | 60 | case 'm': \ |
| 51 | case 'n': \ | 61 | case 'n': \ |
| 52 | case 'o': \ | ||
| 53 | case 'p': \ | ||
| 54 | case 'q': \ | 62 | case 'q': \ |
| 55 | case 'r': \ | 63 | case 'r': \ |
| 56 | case 's': \ | 64 | case 's': \ |
| ... | @@ -58,15 +66,8 @@ | ... | @@ -58,15 +66,8 @@ |
| 58 | case 'u': \ | 66 | case 'u': \ |
| 59 | case 'v': \ | 67 | case 'v': \ |
| 60 | case 'w': \ | 68 | case 'w': \ |
| 61 | case 'x': \ | ||
| 62 | case 'y': \ | 69 | case 'y': \ |
| 63 | case 'z': \ | 70 | case 'z': \ |
| 64 | case 'A': \ | ||
| 65 | case 'B': \ | ||
| 66 | case 'C': \ | ||
| 67 | case 'D': \ | ||
| 68 | case 'E': \ | ||
| 69 | case 'F': \ | ||
| 70 | case 'G': \ | 71 | case 'G': \ |
| 71 | case 'H': \ | 72 | case 'H': \ |
| 72 | case 'I': \ | 73 | case 'I': \ |
| ... | @@ -76,7 +77,6 @@ | ... | @@ -76,7 +77,6 @@ |
| 76 | case 'M': \ | 77 | case 'M': \ |
| 77 | case 'N': \ | 78 | case 'N': \ |
| 78 | case 'O': \ | 79 | case 'O': \ |
| 79 | case 'P': \ | ||
| 80 | case 'Q': \ | 80 | case 'Q': \ |
| 81 | case 'R': \ | 81 | case 'R': \ |
| 82 | case 'S': \ | 82 | case 'S': \ |
| ... | @@ -88,7 +88,46 @@ | ... | @@ -88,7 +88,46 @@ |
| 88 | case 'Y': \ | 88 | case 'Y': \ |
| 89 | case 'Z' | 89 | case 'Z' |
| 90 | 90 | ||
| 91 | #define SYMBOL_CHAR \ | 91 | #define ALPHA_EXCEPT_E_B_O_X \ |
| 92 | ALPHA_EXCEPT_HEX_P_O_X: \ | ||
| 93 | case 'a': \ | ||
| 94 | case 'c': \ | ||
| 95 | case 'd': \ | ||
| 96 | case 'f': \ | ||
| 97 | case 'A': \ | ||
| 98 | case 'B': \ | ||
| 99 | case 'C': \ | ||
| 100 | case 'D': \ | ||
| 101 | case 'F': \ | ||
| 102 | case 'p': \ | ||
| 103 | case 'P' | ||
| 104 | |||
| 105 | #define ALPHA_EXCEPT_HEX_AND_P \ | ||
| 106 | ALPHA_EXCEPT_HEX_P_O_X: \ | ||
| 107 | case 'o': \ | ||
| 108 | case 'x' | ||
| 109 | |||
| 110 | #define ALPHA_EXCEPT_E \ | ||
| 111 | ALPHA_EXCEPT_HEX_AND_P: \ | ||
| 112 | case 'a': \ | ||
| 113 | case 'b': \ | ||
| 114 | case 'c': \ | ||
| 115 | case 'd': \ | ||
| 116 | case 'f': \ | ||
| 117 | case 'A': \ | ||
| 118 | case 'B': \ | ||
| 119 | case 'C': \ | ||
| 120 | case 'D': \ | ||
| 121 | case 'F': \ | ||
| 122 | case 'p': \ | ||
| 123 | case 'P' | ||
| 124 | |||
| 125 | #define ALPHA \ | ||
| 126 | ALPHA_EXCEPT_E: \ | ||
| 127 | case 'e': \ | ||
| 128 | case 'E' | ||
| 129 | |||
| 130 | #define IDENTIFIER_CHAR \ | ||
| 92 | ALPHA: \ | 131 | ALPHA: \ |
| 93 | case DIGIT: \ | 132 | case DIGIT: \ |
| 94 | case '_' | 133 | case '_' |
| ... | @@ -157,101 +196,92 @@ static const struct ZigKeyword zig_keywords[] = { | ... | @@ -157,101 +196,92 @@ static const struct ZigKeyword zig_keywords[] = { |
| 157 | {"while", TokenIdKeywordWhile}, | 196 | {"while", TokenIdKeywordWhile}, |
| 158 | }; | 197 | }; |
| 159 | 198 | ||
| 160 | bool is_zig_keyword(Buf *buf) { | 199 | // Returns TokenIdIdentifier if it is not a keyword. |
| 200 | static TokenId zig_keyword_token(const char *name_ptr, size_t name_len) { | ||
| 161 | for (size_t i = 0; i < array_length(zig_keywords); i += 1) { | 201 | for (size_t i = 0; i < array_length(zig_keywords); i += 1) { |
| 162 | if (buf_eql_str(buf, zig_keywords[i].text)) { | 202 | if (mem_eql_str(name_ptr, name_len, zig_keywords[i].text)) { |
| 163 | return true; | 203 | return zig_keywords[i].token_id; |
| 164 | } | 204 | } |
| 165 | } | 205 | } |
| 166 | return false; | 206 | return TokenIdIdentifier; |
| 167 | } | ||
| 168 | |||
| 169 | static bool is_symbol_char(uint8_t c) { | ||
| 170 | switch (c) { | ||
| 171 | case SYMBOL_CHAR: | ||
| 172 | return true; | ||
| 173 | default: | ||
| 174 | return false; | ||
| 175 | } | ||
| 176 | } | 207 | } |
| 177 | 208 | ||
| 178 | enum TokenizeState { | 209 | enum TokenizeState { |
| 179 | TokenizeStateStart, | 210 | TokenizeState_start, |
| 180 | TokenizeStateSymbol, | 211 | TokenizeState_identifier, |
| 181 | TokenizeStateZero, // "0", which might lead to "0x" | 212 | TokenizeState_builtin, |
| 182 | TokenizeStateNumber, // "123", "0x123" | 213 | TokenizeState_string_literal, |
| 183 | TokenizeStateNumberNoUnderscore, // "12_", "0x12_" next char must be digit | 214 | TokenizeState_string_literal_backslash, |
| 184 | TokenizeStateNumberDot, | 215 | TokenizeState_multiline_string_literal_line, |
| 185 | TokenizeStateFloatFraction, // "123.456", "0x123.456" | 216 | TokenizeState_char_literal, |
| 186 | TokenizeStateFloatFractionNoUnderscore, // "123.45_", "0x123.45_" | 217 | TokenizeState_char_literal_backslash, |
| 187 | TokenizeStateFloatExponentUnsigned, // "123.456e", "123e", "0x123p" | 218 | TokenizeState_char_literal_hex_escape, |
| 188 | TokenizeStateFloatExponentNumber, // "123.456e7", "123.456e+7", "123.456e-7" | 219 | TokenizeState_char_literal_unicode_escape_saw_u, |
| 189 | TokenizeStateFloatExponentNumberNoUnderscore, // "123.456e7_", "123.456e+7_", "123.456e-7_" | 220 | TokenizeState_char_literal_unicode_escape, |
| 190 | TokenizeStateString, | 221 | TokenizeState_char_literal_unicode, |
| 191 | TokenizeStateStringEscape, | 222 | TokenizeState_char_literal_end, |
| 192 | TokenizeStateStringEscapeUnicodeStart, | 223 | TokenizeState_backslash, |
| 193 | TokenizeStateCharLiteral, | 224 | TokenizeState_equal, |
| 194 | TokenizeStateCharLiteralEnd, | 225 | TokenizeState_bang, |
| 195 | TokenizeStateCharLiteralUnicode, | 226 | TokenizeState_pipe, |
| 196 | TokenizeStateSawStar, | 227 | TokenizeState_minus, |
| 197 | TokenizeStateSawStarPercent, | 228 | TokenizeState_minus_percent, |
| 198 | TokenizeStateSawSlash, | 229 | TokenizeState_asterisk, |
| 199 | TokenizeStateSawSlash2, | 230 | TokenizeState_asterisk_percent, |
| 200 | TokenizeStateSawSlash3, | 231 | TokenizeState_slash, |
| 201 | TokenizeStateSawSlashBang, | 232 | TokenizeState_line_comment_start, |
| 202 | TokenizeStateSawBackslash, | 233 | TokenizeState_line_comment, |
| 203 | TokenizeStateSawPercent, | 234 | TokenizeState_doc_comment_start, |
| 204 | TokenizeStateSawPlus, | 235 | TokenizeState_doc_comment, |
| 205 | TokenizeStateSawPlusPercent, | 236 | TokenizeState_container_doc_comment, |
| 206 | TokenizeStateSawDash, | 237 | TokenizeState_zero, |
| 207 | TokenizeStateSawMinusPercent, | 238 | TokenizeState_int_literal_dec, |
| 208 | TokenizeStateSawAmpersand, | 239 | TokenizeState_int_literal_dec_no_underscore, |
| 209 | TokenizeStateSawCaret, | 240 | TokenizeState_int_literal_bin, |
| 210 | TokenizeStateSawBar, | 241 | TokenizeState_int_literal_bin_no_underscore, |
| 211 | TokenizeStateDocComment, | 242 | TokenizeState_int_literal_oct, |
| 212 | TokenizeStateContainerDocComment, | 243 | TokenizeState_int_literal_oct_no_underscore, |
| 213 | TokenizeStateLineComment, | 244 | TokenizeState_int_literal_hex, |
| 214 | TokenizeStateLineString, | 245 | TokenizeState_int_literal_hex_no_underscore, |
| 215 | TokenizeStateLineStringEnd, | 246 | TokenizeState_num_dot_dec, |
| 216 | TokenizeStateLineStringContinue, | 247 | TokenizeState_num_dot_hex, |
| 217 | TokenizeStateSawEq, | 248 | TokenizeState_float_fraction_dec, |
| 218 | TokenizeStateSawBang, | 249 | TokenizeState_float_fraction_dec_no_underscore, |
| 219 | TokenizeStateSawLessThan, | 250 | TokenizeState_float_fraction_hex, |
| 220 | TokenizeStateSawLessThanLessThan, | 251 | TokenizeState_float_fraction_hex_no_underscore, |
| 221 | TokenizeStateSawGreaterThan, | 252 | TokenizeState_float_exponent_unsigned, |
| 222 | TokenizeStateSawGreaterThanGreaterThan, | 253 | TokenizeState_float_exponent_num, |
| 223 | TokenizeStateSawDot, | 254 | TokenizeState_float_exponent_num_no_underscore, |
| 224 | TokenizeStateSawDotDot, | 255 | TokenizeState_ampersand, |
| 225 | TokenizeStateSawDotStar, | 256 | TokenizeState_caret, |
| 226 | TokenizeStateSawAtSign, | 257 | TokenizeState_percent, |
| 227 | TokenizeStateCharCode, | 258 | TokenizeState_plus, |
| 228 | TokenizeStateError, | 259 | TokenizeState_plus_percent, |
| 260 | TokenizeState_angle_bracket_left, | ||
| 261 | TokenizeState_angle_bracket_angle_bracket_left, | ||
| 262 | TokenizeState_angle_bracket_right, | ||
| 263 | TokenizeState_angle_bracket_angle_bracket_right, | ||
| 264 | TokenizeState_period, | ||
| 265 | TokenizeState_period_2, | ||
| 266 | TokenizeState_period_asterisk, | ||
| 267 | TokenizeState_saw_at_sign, | ||
| 268 | TokenizeState_error, | ||
| 229 | }; | 269 | }; |
| 230 | 270 | ||
| 231 | 271 | ||
| 232 | struct Tokenize { | 272 | struct Tokenize { |
| 233 | Buf *buf; | 273 | Tokenization *out; |
| 234 | size_t pos; | 274 | size_t pos; |
| 235 | TokenizeState state; | 275 | TokenizeState state; |
| 236 | ZigList<Token> *tokens; | 276 | uint32_t line; |
| 237 | int line; | 277 | uint32_t column; |
| 238 | int column; | ||
| 239 | Token *cur_tok; | ||
| 240 | Tokenization *out; | ||
| 241 | uint32_t radix; | ||
| 242 | bool is_trailing_underscore; | ||
| 243 | size_t char_code_index; | ||
| 244 | bool unicode; | ||
| 245 | uint32_t char_code; | ||
| 246 | size_t remaining_code_units; | ||
| 247 | }; | 278 | }; |
| 248 | 279 | ||
| 249 | ATTRIBUTE_PRINTF(2, 3) | 280 | ATTRIBUTE_PRINTF(2, 3) |
| 250 | static void tokenize_error(Tokenize *t, const char *format, ...) { | 281 | static void tokenize_error(Tokenize *t, const char *format, ...) { |
| 251 | t->state = TokenizeStateError; | 282 | t->state = TokenizeState_error; |
| 252 | 283 | ||
| 253 | t->out->err_line = t->line; | 284 | t->out->err_byte_offset = t->pos; |
| 254 | t->out->err_column = t->column; | ||
| 255 | 285 | ||
| 256 | va_list ap; | 286 | va_list ap; |
| 257 | va_start(ap, format); | 287 | va_start(ap, format); |
| ... | @@ -259,98 +289,18 @@ static void tokenize_error(Tokenize *t, const char *format, ...) { | ... | @@ -259,98 +289,18 @@ static void tokenize_error(Tokenize *t, const char *format, ...) { |
| 259 | va_end(ap); | 289 | va_end(ap); |
| 260 | } | 290 | } |
| 261 | 291 | ||
| 262 | static void set_token_id(Tokenize *t, Token *token, TokenId id) { | ||
| 263 | token->id = id; | ||
| 264 | |||
| 265 | if (id == TokenIdIntLiteral) { | ||
| 266 | bigint_init_unsigned(&token->data.int_lit.bigint, 0); | ||
| 267 | } else if (id == TokenIdFloatLiteral) { | ||
| 268 | bigfloat_init_32(&token->data.float_lit.bigfloat, 0.0f); | ||
| 269 | token->data.float_lit.overflow = false; | ||
| 270 | } else if (id == TokenIdStringLiteral || id == TokenIdMultilineStringLiteral || id == TokenIdSymbol) { | ||
| 271 | memset(&token->data.str_lit.str, 0, sizeof(Buf)); | ||
| 272 | buf_resize(&token->data.str_lit.str, 0); | ||
| 273 | } | ||
| 274 | } | ||
| 275 | |||
| 276 | static void begin_token(Tokenize *t, TokenId id) { | 292 | static void begin_token(Tokenize *t, TokenId id) { |
| 277 | assert(!t->cur_tok); | 293 | t->out->ids.append(id); |
| 278 | t->tokens->add_one(); | 294 | TokenLoc tok_loc; |
| 279 | Token *token = &t->tokens->last(); | 295 | tok_loc.offset = (uint32_t) t->pos; |
| 280 | token->start_line = t->line; | 296 | tok_loc.line = t->line; |
| 281 | token->start_column = t->column; | 297 | tok_loc.column = t->column; |
| 282 | token->start_pos = t->pos; | 298 | t->out->locs.append(tok_loc); |
| 283 | |||
| 284 | set_token_id(t, token, id); | ||
| 285 | |||
| 286 | t->cur_tok = token; | ||
| 287 | } | 299 | } |
| 288 | 300 | ||
| 289 | static void cancel_token(Tokenize *t) { | 301 | static void cancel_token(Tokenize *t) { |
| 290 | t->tokens->pop(); | 302 | t->out->ids.pop(); |
| 291 | t->cur_tok = nullptr; | 303 | t->out->locs.pop(); |
| 292 | } | ||
| 293 | |||
| 294 | static void end_float_token(Tokenize *t) { | ||
| 295 | uint8_t *ptr_buf = (uint8_t*)buf_ptr(t->buf) + t->cur_tok->start_pos; | ||
| 296 | size_t buf_len = t->cur_tok->end_pos - t->cur_tok->start_pos; | ||
| 297 | if (bigfloat_init_buf(&t->cur_tok->data.float_lit.bigfloat, ptr_buf, buf_len)) { | ||
| 298 | t->cur_tok->data.float_lit.overflow = true; | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 302 | static void end_token(Tokenize *t) { | ||
| 303 | assert(t->cur_tok); | ||
| 304 | t->cur_tok->end_pos = t->pos + 1; | ||
| 305 | |||
| 306 | if (t->cur_tok->id == TokenIdFloatLiteral) { | ||
| 307 | end_float_token(t); | ||
| 308 | } else if (t->cur_tok->id == TokenIdSymbol) { | ||
| 309 | char *token_mem = buf_ptr(t->buf) + t->cur_tok->start_pos; | ||
| 310 | int token_len = (int)(t->cur_tok->end_pos - t->cur_tok->start_pos); | ||
| 311 | |||
| 312 | for (size_t i = 0; i < array_length(zig_keywords); i += 1) { | ||
| 313 | if (mem_eql_str(token_mem, token_len, zig_keywords[i].text)) { | ||
| 314 | t->cur_tok->id = zig_keywords[i].token_id; | ||
| 315 | break; | ||
| 316 | } | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | t->cur_tok = nullptr; | ||
| 321 | } | ||
| 322 | |||
| 323 | static bool is_exponent_signifier(uint8_t c, int radix) { | ||
| 324 | if (radix == 16) { | ||
| 325 | return c == 'p' || c == 'P'; | ||
| 326 | } else { | ||
| 327 | return c == 'e' || c == 'E'; | ||
| 328 | } | ||
| 329 | } | ||
| 330 | |||
| 331 | static uint32_t get_digit_value(uint8_t c) { | ||
| 332 | if ('0' <= c && c <= '9') { | ||
| 333 | return c - '0'; | ||
| 334 | } | ||
| 335 | if ('A' <= c && c <= 'Z') { | ||
| 336 | return c - 'A' + 10; | ||
| 337 | } | ||
| 338 | if ('a' <= c && c <= 'z') { | ||
| 339 | return c - 'a' + 10; | ||
| 340 | } | ||
| 341 | return UINT32_MAX; | ||
| 342 | } | ||
| 343 | |||
| 344 | static void handle_string_escape(Tokenize *t, uint8_t c) { | ||
| 345 | if (t->cur_tok->id == TokenIdCharLiteral) { | ||
| 346 | t->cur_tok->data.char_lit.c = c; | ||
| 347 | t->state = TokenizeStateCharLiteralEnd; | ||
| 348 | } else if (t->cur_tok->id == TokenIdStringLiteral || t->cur_tok->id == TokenIdSymbol) { | ||
| 349 | buf_append_char(&t->cur_tok->data.str_lit.str, c); | ||
| 350 | t->state = TokenizeStateString; | ||
| 351 | } else { | ||
| 352 | zig_unreachable(); | ||
| 353 | } | ||
| 354 | } | 304 | } |
| 355 | 305 | ||
| 356 | static const char* get_escape_shorthand(uint8_t c) { | 306 | static const char* get_escape_shorthand(uint8_t c) { |
| ... | @@ -376,7 +326,15 @@ static const char* get_escape_shorthand(uint8_t c) { | ... | @@ -376,7 +326,15 @@ static const char* get_escape_shorthand(uint8_t c) { |
| 376 | } | 326 | } |
| 377 | } | 327 | } |
| 378 | 328 | ||
| 329 | static void invalid_eof(Tokenize *t) { | ||
| 330 | return tokenize_error(t, "unexpected End-Of-File"); | ||
| 331 | } | ||
| 332 | |||
| 379 | static void invalid_char_error(Tokenize *t, uint8_t c) { | 333 | static void invalid_char_error(Tokenize *t, uint8_t c) { |
| 334 | if (c == 0) { | ||
| 335 | return invalid_eof(t); | ||
| 336 | } | ||
| 337 | |||
| 380 | if (c == '\r') { | 338 | if (c == '\r') { |
| 381 | tokenize_error(t, "invalid carriage return, only '\\n' line endings are supported"); | 339 | tokenize_error(t, "invalid carriage return, only '\\n' line endings are supported"); |
| 382 | return; | 340 | return; |
| ... | @@ -396,1139 +354,1089 @@ static void invalid_char_error(Tokenize *t, uint8_t c) { | ... | @@ -396,1139 +354,1089 @@ static void invalid_char_error(Tokenize *t, uint8_t c) { |
| 396 | tokenize_error(t, "invalid character: '\\x%02x'", c); | 354 | tokenize_error(t, "invalid character: '\\x%02x'", c); |
| 397 | } | 355 | } |
| 398 | 356 | ||
| 399 | void tokenize(Buf *buf, Tokenization *out) { | 357 | void tokenize(const char *source, Tokenization *out) { |
| 400 | Tokenize t = {0}; | 358 | Tokenize t = {0}; |
| 401 | t.out = out; | 359 | t.out = out; |
| 402 | t.tokens = out->tokens = heap::c_allocator.create<ZigList<Token>>(); | ||
| 403 | t.buf = buf; | ||
| 404 | 360 | ||
| 405 | out->line_offsets = heap::c_allocator.create<ZigList<size_t>>(); | 361 | size_t remaining_code_units; |
| 406 | out->line_offsets->append(0); | 362 | size_t seen_escape_digits; |
| 407 | 363 | ||
| 408 | // Skip the UTF-8 BOM if present | 364 | // Skip the UTF-8 BOM if present. |
| 409 | if (buf_starts_with_mem(buf, "\xEF\xBB\xBF", 3)) { | 365 | if (source[0] == (char)0xef && |
| 366 | source[1] == (char)0xbb && | ||
| 367 | source[2] == (char)0xbf) | ||
| 368 | { | ||
| 410 | t.pos += 3; | 369 | t.pos += 3; |
| 411 | } | 370 | } |
| 412 | 371 | ||
| 413 | for (; t.pos < buf_len(t.buf); t.pos += 1) { | 372 | // Invalid token takes up index 0 so that index 0 can mean "none". |
| 414 | uint8_t c = buf_ptr(t.buf)[t.pos]; | 373 | begin_token(&t, TokenIdCount); |
| 374 | |||
| 375 | for (;;) { | ||
| 376 | uint8_t c = source[t.pos]; | ||
| 415 | switch (t.state) { | 377 | switch (t.state) { |
| 416 | case TokenizeStateError: | 378 | case TokenizeState_error: |
| 417 | break; | 379 | goto eof; |
| 418 | case TokenizeStateStart: | 380 | case TokenizeState_start: |
| 419 | switch (c) { | 381 | switch (c) { |
| 382 | case 0: | ||
| 383 | goto eof; | ||
| 420 | case WHITESPACE: | 384 | case WHITESPACE: |
| 421 | break; | 385 | break; |
| 386 | case '"': | ||
| 387 | begin_token(&t, TokenIdStringLiteral); | ||
| 388 | t.state = TokenizeState_string_literal; | ||
| 389 | break; | ||
| 390 | case '\'': | ||
| 391 | begin_token(&t, TokenIdCharLiteral); | ||
| 392 | t.state = TokenizeState_char_literal; | ||
| 393 | break; | ||
| 422 | case ALPHA: | 394 | case ALPHA: |
| 423 | case '_': | 395 | case '_': |
| 424 | t.state = TokenizeStateSymbol; | 396 | t.state = TokenizeState_identifier; |
| 425 | begin_token(&t, TokenIdSymbol); | 397 | begin_token(&t, TokenIdIdentifier); |
| 426 | buf_append_char(&t.cur_tok->data.str_lit.str, c); | ||
| 427 | break; | 398 | break; |
| 428 | case '0': | 399 | case '@': |
| 429 | t.state = TokenizeStateZero; | 400 | begin_token(&t, TokenIdBuiltin); |
| 430 | begin_token(&t, TokenIdIntLiteral); | 401 | t.state = TokenizeState_saw_at_sign; |
| 431 | t.is_trailing_underscore = false; | ||
| 432 | t.radix = 10; | ||
| 433 | bigint_init_unsigned(&t.cur_tok->data.int_lit.bigint, 0); | ||
| 434 | break; | 402 | break; |
| 435 | case DIGIT_NON_ZERO: | 403 | case '=': |
| 436 | t.state = TokenizeStateNumber; | 404 | begin_token(&t, TokenIdEq); |
| 437 | begin_token(&t, TokenIdIntLiteral); | 405 | t.state = TokenizeState_equal; |
| 438 | t.is_trailing_underscore = false; | ||
| 439 | t.radix = 10; | ||
| 440 | bigint_init_unsigned(&t.cur_tok->data.int_lit.bigint, get_digit_value(c)); | ||
| 441 | break; | 406 | break; |
| 442 | case '"': | 407 | case '!': |
| 443 | begin_token(&t, TokenIdStringLiteral); | 408 | begin_token(&t, TokenIdBang); |
| 444 | t.state = TokenizeStateString; | 409 | t.state = TokenizeState_bang; |
| 445 | break; | 410 | break; |
| 446 | case '\'': | 411 | case '|': |
| 447 | begin_token(&t, TokenIdCharLiteral); | 412 | begin_token(&t, TokenIdBinOr); |
| 448 | t.state = TokenizeStateCharLiteral; | 413 | t.state = TokenizeState_pipe; |
| 449 | break; | 414 | break; |
| 450 | case '(': | 415 | case '(': |
| 451 | begin_token(&t, TokenIdLParen); | 416 | begin_token(&t, TokenIdLParen); |
| 452 | end_token(&t); | ||
| 453 | break; | 417 | break; |
| 454 | case ')': | 418 | case ')': |
| 455 | begin_token(&t, TokenIdRParen); | 419 | begin_token(&t, TokenIdRParen); |
| 456 | end_token(&t); | ||
| 457 | break; | ||
| 458 | case ',': | ||
| 459 | begin_token(&t, TokenIdComma); | ||
| 460 | end_token(&t); | ||
| 461 | break; | ||
| 462 | case '?': | ||
| 463 | begin_token(&t, TokenIdQuestion); | ||
| 464 | end_token(&t); | ||
| 465 | break; | ||
| 466 | case '{': | ||
| 467 | begin_token(&t, TokenIdLBrace); | ||
| 468 | end_token(&t); | ||
| 469 | break; | ||
| 470 | case '}': | ||
| 471 | begin_token(&t, TokenIdRBrace); | ||
| 472 | end_token(&t); | ||
| 473 | break; | 420 | break; |
| 474 | case '[': | 421 | case '[': |
| 475 | begin_token(&t, TokenIdLBracket); | 422 | begin_token(&t, TokenIdLBracket); |
| 476 | end_token(&t); | ||
| 477 | break; | 423 | break; |
| 478 | case ']': | 424 | case ']': |
| 479 | begin_token(&t, TokenIdRBracket); | 425 | begin_token(&t, TokenIdRBracket); |
| 480 | end_token(&t); | ||
| 481 | break; | 426 | break; |
| 482 | case ';': | 427 | case ';': |
| 483 | begin_token(&t, TokenIdSemicolon); | 428 | begin_token(&t, TokenIdSemicolon); |
| 484 | end_token(&t); | 429 | break; |
| 430 | case ',': | ||
| 431 | begin_token(&t, TokenIdComma); | ||
| 432 | break; | ||
| 433 | case '?': | ||
| 434 | begin_token(&t, TokenIdQuestion); | ||
| 485 | break; | 435 | break; |
| 486 | case ':': | 436 | case ':': |
| 487 | begin_token(&t, TokenIdColon); | 437 | begin_token(&t, TokenIdColon); |
| 488 | end_token(&t); | ||
| 489 | break; | 438 | break; |
| 490 | case '#': | 439 | case '%': |
| 491 | begin_token(&t, TokenIdNumberSign); | 440 | begin_token(&t, TokenIdPercent); |
| 492 | end_token(&t); | 441 | t.state = TokenizeState_percent; |
| 493 | break; | 442 | break; |
| 494 | case '*': | 443 | case '*': |
| 495 | begin_token(&t, TokenIdStar); | 444 | begin_token(&t, TokenIdStar); |
| 496 | t.state = TokenizeStateSawStar; | 445 | t.state = TokenizeState_asterisk; |
| 497 | break; | 446 | break; |
| 498 | case '/': | 447 | case '+': |
| 499 | begin_token(&t, TokenIdSlash); | 448 | begin_token(&t, TokenIdPlus); |
| 500 | t.state = TokenizeStateSawSlash; | 449 | t.state = TokenizeState_plus; |
| 450 | break; | ||
| 451 | case '<': | ||
| 452 | begin_token(&t, TokenIdCmpLessThan); | ||
| 453 | t.state = TokenizeState_angle_bracket_left; | ||
| 454 | break; | ||
| 455 | case '>': | ||
| 456 | begin_token(&t, TokenIdCmpGreaterThan); | ||
| 457 | t.state = TokenizeState_angle_bracket_right; | ||
| 458 | break; | ||
| 459 | case '^': | ||
| 460 | begin_token(&t, TokenIdBinXor); | ||
| 461 | t.state = TokenizeState_caret; | ||
| 501 | break; | 462 | break; |
| 502 | case '\\': | 463 | case '\\': |
| 503 | begin_token(&t, TokenIdMultilineStringLiteral); | 464 | begin_token(&t, TokenIdMultilineStringLiteralLine); |
| 504 | t.state = TokenizeStateSawBackslash; | 465 | t.state = TokenizeState_backslash; |
| 505 | break; | 466 | break; |
| 506 | case '%': | 467 | case '{': |
| 507 | begin_token(&t, TokenIdPercent); | 468 | begin_token(&t, TokenIdLBrace); |
| 508 | t.state = TokenizeStateSawPercent; | ||
| 509 | break; | 469 | break; |
| 510 | case '+': | 470 | case '}': |
| 511 | begin_token(&t, TokenIdPlus); | 471 | begin_token(&t, TokenIdRBrace); |
| 512 | t.state = TokenizeStateSawPlus; | ||
| 513 | break; | 472 | break; |
| 514 | case '~': | 473 | case '~': |
| 515 | begin_token(&t, TokenIdTilde); | 474 | begin_token(&t, TokenIdTilde); |
| 516 | end_token(&t); | ||
| 517 | break; | 475 | break; |
| 518 | case '@': | 476 | case '.': |
| 519 | begin_token(&t, TokenIdAtSign); | 477 | begin_token(&t, TokenIdDot); |
| 520 | t.state = TokenizeStateSawAtSign; | 478 | t.state = TokenizeState_period; |
| 521 | break; | 479 | break; |
| 522 | case '-': | 480 | case '-': |
| 523 | begin_token(&t, TokenIdDash); | 481 | begin_token(&t, TokenIdDash); |
| 524 | t.state = TokenizeStateSawDash; | 482 | t.state = TokenizeState_minus; |
| 483 | break; | ||
| 484 | case '/': | ||
| 485 | begin_token(&t, TokenIdSlash); | ||
| 486 | t.state = TokenizeState_slash; | ||
| 525 | break; | 487 | break; |
| 526 | case '&': | 488 | case '&': |
| 527 | begin_token(&t, TokenIdAmpersand); | 489 | begin_token(&t, TokenIdAmpersand); |
| 528 | t.state = TokenizeStateSawAmpersand; | 490 | t.state = TokenizeState_ampersand; |
| 529 | break; | 491 | break; |
| 530 | case '^': | 492 | case '0': |
| 531 | begin_token(&t, TokenIdBinXor); | 493 | t.state = TokenizeState_zero; |
| 532 | t.state = TokenizeStateSawCaret; | 494 | begin_token(&t, TokenIdIntLiteral); |
| 533 | break; | ||
| 534 | case '|': | ||
| 535 | begin_token(&t, TokenIdBinOr); | ||
| 536 | t.state = TokenizeStateSawBar; | ||
| 537 | break; | 495 | break; |
| 538 | case '=': | 496 | case DIGIT_NON_ZERO: |
| 539 | begin_token(&t, TokenIdEq); | 497 | t.state = TokenizeState_int_literal_dec; |
| 540 | t.state = TokenizeStateSawEq; | 498 | begin_token(&t, TokenIdIntLiteral); |
| 541 | break; | 499 | break; |
| 542 | case '!': | 500 | default: |
| 543 | begin_token(&t, TokenIdBang); | 501 | invalid_char_error(&t, c); |
| 544 | t.state = TokenizeStateSawBang; | 502 | } |
| 503 | break; | ||
| 504 | case TokenizeState_saw_at_sign: | ||
| 505 | switch (c) { | ||
| 506 | case 0: | ||
| 507 | invalid_eof(&t); | ||
| 508 | goto eof; | ||
| 509 | case '"': | ||
| 510 | t.out->ids.last() = TokenIdIdentifier; | ||
| 511 | t.state = TokenizeState_string_literal; | ||
| 545 | break; | 512 | break; |
| 546 | case '<': | 513 | case IDENTIFIER_CHAR: |
| 547 | begin_token(&t, TokenIdCmpLessThan); | 514 | t.state = TokenizeState_builtin; |
| 548 | t.state = TokenizeStateSawLessThan; | ||
| 549 | break; | 515 | break; |
| 550 | case '>': | 516 | default: |
| 551 | begin_token(&t, TokenIdCmpGreaterThan); | 517 | invalid_char_error(&t, c); |
| 552 | t.state = TokenizeStateSawGreaterThan; | 518 | } |
| 519 | break; | ||
| 520 | case TokenizeState_ampersand: | ||
| 521 | switch (c) { | ||
| 522 | case 0: | ||
| 523 | goto eof; | ||
| 524 | case '&': | ||
| 525 | tokenize_error(&t, "`&&` is invalid. Note that `and` is boolean AND"); | ||
| 553 | break; | 526 | break; |
| 554 | case '.': | 527 | case '=': |
| 555 | begin_token(&t, TokenIdDot); | 528 | t.out->ids.last() = TokenIdBitAndEq; |
| 556 | t.state = TokenizeStateSawDot; | 529 | t.state = TokenizeState_start; |
| 557 | break; | 530 | break; |
| 558 | default: | 531 | default: |
| 559 | invalid_char_error(&t, c); | 532 | t.state = TokenizeState_start; |
| 533 | continue; | ||
| 560 | } | 534 | } |
| 561 | break; | 535 | break; |
| 562 | case TokenizeStateSawDot: | 536 | case TokenizeState_asterisk: |
| 563 | switch (c) { | 537 | switch (c) { |
| 564 | case '.': | 538 | case 0: |
| 565 | t.state = TokenizeStateSawDotDot; | 539 | goto eof; |
| 566 | set_token_id(&t, t.cur_tok, TokenIdEllipsis2); | 540 | case '=': |
| 541 | t.out->ids.last() = TokenIdTimesEq; | ||
| 542 | t.state = TokenizeState_start; | ||
| 567 | break; | 543 | break; |
| 568 | case '*': | 544 | case '*': |
| 569 | t.state = TokenizeStateSawDotStar; | 545 | t.out->ids.last() = TokenIdStarStar; |
| 570 | set_token_id(&t, t.cur_tok, TokenIdDotStar); | 546 | t.state = TokenizeState_start; |
| 547 | break; | ||
| 548 | case '%': | ||
| 549 | t.state = TokenizeState_asterisk_percent; | ||
| 571 | break; | 550 | break; |
| 572 | default: | 551 | default: |
| 573 | t.pos -= 1; | 552 | t.state = TokenizeState_start; |
| 574 | end_token(&t); | ||
| 575 | t.state = TokenizeStateStart; | ||
| 576 | continue; | 553 | continue; |
| 577 | } | 554 | } |
| 578 | break; | 555 | break; |
| 579 | case TokenizeStateSawDotDot: | 556 | case TokenizeState_asterisk_percent: |
| 580 | switch (c) { | 557 | switch (c) { |
| 581 | case '.': | 558 | case 0: |
| 582 | t.state = TokenizeStateStart; | 559 | t.out->ids.last() = TokenIdTimesPercent; |
| 583 | set_token_id(&t, t.cur_tok, TokenIdEllipsis3); | 560 | goto eof; |
| 584 | end_token(&t); | 561 | case '=': |
| 562 | t.out->ids.last() = TokenIdTimesPercentEq; | ||
| 563 | t.state = TokenizeState_start; | ||
| 585 | break; | 564 | break; |
| 586 | default: | 565 | default: |
| 587 | t.pos -= 1; | 566 | t.out->ids.last() = TokenIdTimesPercent; |
| 588 | end_token(&t); | 567 | t.state = TokenizeState_start; |
| 589 | t.state = TokenizeStateStart; | ||
| 590 | continue; | 568 | continue; |
| 591 | } | 569 | } |
| 592 | break; | 570 | break; |
| 593 | case TokenizeStateSawDotStar: | 571 | case TokenizeState_percent: |
| 594 | switch (c) { | 572 | switch (c) { |
| 595 | case '*': | 573 | case 0: |
| 596 | tokenize_error(&t, "`.*` can't be followed by `*`. Are you missing a space?"); | 574 | goto eof; |
| 575 | case '=': | ||
| 576 | t.out->ids.last() = TokenIdModEq; | ||
| 577 | t.state = TokenizeState_start; | ||
| 597 | break; | 578 | break; |
| 598 | default: | 579 | default: |
| 599 | t.pos -= 1; | 580 | t.state = TokenizeState_start; |
| 600 | end_token(&t); | ||
| 601 | t.state = TokenizeStateStart; | ||
| 602 | continue; | 581 | continue; |
| 603 | } | 582 | } |
| 604 | break; | 583 | break; |
| 605 | case TokenizeStateSawGreaterThan: | 584 | case TokenizeState_plus: |
| 606 | switch (c) { | 585 | switch (c) { |
| 586 | case 0: | ||
| 587 | goto eof; | ||
| 607 | case '=': | 588 | case '=': |
| 608 | set_token_id(&t, t.cur_tok, TokenIdCmpGreaterOrEq); | 589 | t.out->ids.last() = TokenIdPlusEq; |
| 609 | end_token(&t); | 590 | t.state = TokenizeState_start; |
| 610 | t.state = TokenizeStateStart; | ||
| 611 | break; | 591 | break; |
| 612 | case '>': | 592 | case '+': |
| 613 | set_token_id(&t, t.cur_tok, TokenIdBitShiftRight); | 593 | t.out->ids.last() = TokenIdPlusPlus; |
| 614 | t.state = TokenizeStateSawGreaterThanGreaterThan; | 594 | t.state = TokenizeState_start; |
| 595 | break; | ||
| 596 | case '%': | ||
| 597 | t.state = TokenizeState_plus_percent; | ||
| 615 | break; | 598 | break; |
| 616 | default: | 599 | default: |
| 617 | t.pos -= 1; | 600 | t.state = TokenizeState_start; |
| 618 | end_token(&t); | ||
| 619 | t.state = TokenizeStateStart; | ||
| 620 | continue; | 601 | continue; |
| 621 | } | 602 | } |
| 622 | break; | 603 | break; |
| 623 | case TokenizeStateSawGreaterThanGreaterThan: | 604 | case TokenizeState_plus_percent: |
| 624 | switch (c) { | 605 | switch (c) { |
| 606 | case 0: | ||
| 607 | t.out->ids.last() = TokenIdPlusPercent; | ||
| 608 | goto eof; | ||
| 625 | case '=': | 609 | case '=': |
| 626 | set_token_id(&t, t.cur_tok, TokenIdBitShiftRightEq); | 610 | t.out->ids.last() = TokenIdPlusPercentEq; |
| 627 | end_token(&t); | 611 | t.state = TokenizeState_start; |
| 628 | t.state = TokenizeStateStart; | ||
| 629 | break; | 612 | break; |
| 630 | default: | 613 | default: |
| 631 | t.pos -= 1; | 614 | t.out->ids.last() = TokenIdPlusPercent; |
| 632 | end_token(&t); | 615 | t.state = TokenizeState_start; |
| 633 | t.state = TokenizeStateStart; | ||
| 634 | continue; | 616 | continue; |
| 635 | } | 617 | } |
| 636 | break; | 618 | break; |
| 637 | case TokenizeStateSawLessThan: | 619 | case TokenizeState_caret: |
| 638 | switch (c) { | 620 | switch (c) { |
| 621 | case 0: | ||
| 622 | goto eof; | ||
| 639 | case '=': | 623 | case '=': |
| 640 | set_token_id(&t, t.cur_tok, TokenIdCmpLessOrEq); | 624 | t.out->ids.last() = TokenIdBitXorEq; |
| 641 | end_token(&t); | 625 | t.state = TokenizeState_start; |
| 642 | t.state = TokenizeStateStart; | ||
| 643 | break; | 626 | break; |
| 644 | case '<': | 627 | default: |
| 645 | set_token_id(&t, t.cur_tok, TokenIdBitShiftLeft); | 628 | t.state = TokenizeState_start; |
| 646 | t.state = TokenizeStateSawLessThanLessThan; | 629 | continue; |
| 630 | } | ||
| 631 | break; | ||
| 632 | case TokenizeState_identifier: | ||
| 633 | switch (c) { | ||
| 634 | case 0: { | ||
| 635 | uint32_t start_pos = t.out->locs.last().offset; | ||
| 636 | t.out->ids.last() = zig_keyword_token( | ||
| 637 | source + start_pos, t.pos - start_pos); | ||
| 638 | goto eof; | ||
| 639 | } | ||
| 640 | case IDENTIFIER_CHAR: | ||
| 641 | break; | ||
| 642 | default: { | ||
| 643 | uint32_t start_pos = t.out->locs.last().offset; | ||
| 644 | t.out->ids.last() = zig_keyword_token( | ||
| 645 | source + start_pos, t.pos - start_pos); | ||
| 646 | |||
| 647 | t.state = TokenizeState_start; | ||
| 648 | continue; | ||
| 649 | } | ||
| 650 | } | ||
| 651 | break; | ||
| 652 | case TokenizeState_builtin: | ||
| 653 | switch (c) { | ||
| 654 | case 0: | ||
| 655 | goto eof; | ||
| 656 | case IDENTIFIER_CHAR: | ||
| 647 | break; | 657 | break; |
| 648 | default: | 658 | default: |
| 649 | t.pos -= 1; | 659 | t.state = TokenizeState_start; |
| 650 | end_token(&t); | ||
| 651 | t.state = TokenizeStateStart; | ||
| 652 | continue; | 660 | continue; |
| 653 | } | 661 | } |
| 654 | break; | 662 | break; |
| 655 | case TokenizeStateSawLessThanLessThan: | 663 | case TokenizeState_backslash: |
| 664 | switch (c) { | ||
| 665 | case '\\': | ||
| 666 | t.state = TokenizeState_multiline_string_literal_line; | ||
| 667 | break; | ||
| 668 | default: | ||
| 669 | invalid_char_error(&t, c); | ||
| 670 | break; | ||
| 671 | } | ||
| 672 | break; | ||
| 673 | case TokenizeState_string_literal: | ||
| 674 | switch (c) { | ||
| 675 | case 0: | ||
| 676 | invalid_eof(&t); | ||
| 677 | goto eof; | ||
| 678 | case '\\': | ||
| 679 | t.state = TokenizeState_string_literal_backslash; | ||
| 680 | break; | ||
| 681 | case '"': | ||
| 682 | t.state = TokenizeState_start; | ||
| 683 | break; | ||
| 684 | case '\n': | ||
| 685 | case '\r': | ||
| 686 | tokenize_error(&t, "newline not allowed in string literal"); | ||
| 687 | break; | ||
| 688 | default: | ||
| 689 | break; | ||
| 690 | } | ||
| 691 | break; | ||
| 692 | case TokenizeState_string_literal_backslash: | ||
| 693 | switch (c) { | ||
| 694 | case 0: | ||
| 695 | invalid_eof(&t); | ||
| 696 | goto eof; | ||
| 697 | case '\n': | ||
| 698 | case '\r': | ||
| 699 | tokenize_error(&t, "newline not allowed in string literal"); | ||
| 700 | break; | ||
| 701 | default: | ||
| 702 | t.state = TokenizeState_string_literal; | ||
| 703 | break; | ||
| 704 | } | ||
| 705 | break; | ||
| 706 | case TokenizeState_char_literal: | ||
| 707 | if (c == 0) { | ||
| 708 | invalid_eof(&t); | ||
| 709 | goto eof; | ||
| 710 | } else if (c == '\\') { | ||
| 711 | t.state = TokenizeState_char_literal_backslash; | ||
| 712 | } else if (c == '\'') { | ||
| 713 | tokenize_error(&t, "expected character"); | ||
| 714 | } else if ((c >= 0x80 && c <= 0xbf) || c >= 0xf8) { | ||
| 715 | // 10xxxxxx | ||
| 716 | // 11111xxx | ||
| 717 | invalid_char_error(&t, c); | ||
| 718 | } else if (c >= 0xc0 && c <= 0xdf) { | ||
| 719 | // 110xxxxx | ||
| 720 | remaining_code_units = 1; | ||
| 721 | t.state = TokenizeState_char_literal_unicode; | ||
| 722 | } else if (c >= 0xe0 && c <= 0xef) { | ||
| 723 | // 1110xxxx | ||
| 724 | remaining_code_units = 2; | ||
| 725 | t.state = TokenizeState_char_literal_unicode; | ||
| 726 | } else if (c >= 0xf0 && c <= 0xf7) { | ||
| 727 | // 11110xxx | ||
| 728 | remaining_code_units = 3; | ||
| 729 | t.state = TokenizeState_char_literal_unicode; | ||
| 730 | } else { | ||
| 731 | t.state = TokenizeState_char_literal_end; | ||
| 732 | } | ||
| 733 | break; | ||
| 734 | case TokenizeState_char_literal_backslash: | ||
| 735 | switch (c) { | ||
| 736 | case 0: | ||
| 737 | invalid_eof(&t); | ||
| 738 | goto eof; | ||
| 739 | case '\n': | ||
| 740 | case '\r': | ||
| 741 | tokenize_error(&t, "newline not allowed in character literal"); | ||
| 742 | break; | ||
| 743 | case 'x': | ||
| 744 | t.state = TokenizeState_char_literal_hex_escape; | ||
| 745 | seen_escape_digits = 0; | ||
| 746 | break; | ||
| 747 | case 'u': | ||
| 748 | t.state = TokenizeState_char_literal_unicode_escape_saw_u; | ||
| 749 | break; | ||
| 750 | case 'U': | ||
| 751 | invalid_char_error(&t, c); | ||
| 752 | break; | ||
| 753 | default: | ||
| 754 | t.state = TokenizeState_char_literal_end; | ||
| 755 | break; | ||
| 756 | } | ||
| 757 | break; | ||
| 758 | case TokenizeState_char_literal_hex_escape: | ||
| 759 | switch (c) { | ||
| 760 | case ALPHA: | ||
| 761 | case DIGIT: | ||
| 762 | seen_escape_digits += 1; | ||
| 763 | if (seen_escape_digits == 2) { | ||
| 764 | t.state = TokenizeState_char_literal_end; | ||
| 765 | } | ||
| 766 | break; | ||
| 767 | default: | ||
| 768 | tokenize_error(&t, "expected hex digit"); | ||
| 769 | break; | ||
| 770 | } | ||
| 771 | break; | ||
| 772 | case TokenizeState_char_literal_unicode_escape_saw_u: | ||
| 773 | switch (c) { | ||
| 774 | case '{': | ||
| 775 | t.state = TokenizeState_char_literal_unicode_escape; | ||
| 776 | seen_escape_digits = 0; | ||
| 777 | break; | ||
| 778 | default: | ||
| 779 | tokenize_error(&t, "expected '{' to begin unicode escape sequence"); | ||
| 780 | break; | ||
| 781 | } | ||
| 782 | break; | ||
| 783 | case TokenizeState_char_literal_unicode_escape: | ||
| 656 | switch (c) { | 784 | switch (c) { |
| 785 | case ALPHA: | ||
| 786 | case DIGIT: | ||
| 787 | seen_escape_digits += 1; | ||
| 788 | break; | ||
| 789 | case '}': | ||
| 790 | if (seen_escape_digits == 0) { | ||
| 791 | tokenize_error(&t, "empty unicode escape sequence"); | ||
| 792 | break; | ||
| 793 | } | ||
| 794 | t.state = TokenizeState_char_literal_end; | ||
| 795 | break; | ||
| 796 | default: | ||
| 797 | tokenize_error(&t, "expected hex digit"); | ||
| 798 | break; | ||
| 799 | } | ||
| 800 | break; | ||
| 801 | case TokenizeState_char_literal_end: | ||
| 802 | switch (c) { | ||
| 803 | case '\'': | ||
| 804 | t.state = TokenizeState_start; | ||
| 805 | break; | ||
| 806 | default: | ||
| 807 | invalid_char_error(&t, c); | ||
| 808 | break; | ||
| 809 | } | ||
| 810 | break; | ||
| 811 | case TokenizeState_char_literal_unicode: | ||
| 812 | if (c >= 0x80 && c <= 0xbf) { | ||
| 813 | remaining_code_units -= 1; | ||
| 814 | if (remaining_code_units == 0) { | ||
| 815 | t.state = TokenizeState_char_literal_end; | ||
| 816 | } | ||
| 817 | } else { | ||
| 818 | invalid_char_error(&t, c); | ||
| 819 | } | ||
| 820 | break; | ||
| 821 | case TokenizeState_multiline_string_literal_line: | ||
| 822 | switch (c) { | ||
| 823 | case 0: | ||
| 824 | goto eof; | ||
| 825 | case '\n': | ||
| 826 | t.state = TokenizeState_start; | ||
| 827 | break; | ||
| 828 | default: | ||
| 829 | break; | ||
| 830 | } | ||
| 831 | break; | ||
| 832 | case TokenizeState_bang: | ||
| 833 | switch (c) { | ||
| 834 | case 0: | ||
| 835 | goto eof; | ||
| 657 | case '=': | 836 | case '=': |
| 658 | set_token_id(&t, t.cur_tok, TokenIdBitShiftLeftEq); | 837 | t.out->ids.last() = TokenIdCmpNotEq; |
| 659 | end_token(&t); | 838 | t.state = TokenizeState_start; |
| 660 | t.state = TokenizeStateStart; | ||
| 661 | break; | 839 | break; |
| 662 | default: | 840 | default: |
| 663 | t.pos -= 1; | 841 | t.state = TokenizeState_start; |
| 664 | end_token(&t); | ||
| 665 | t.state = TokenizeStateStart; | ||
| 666 | continue; | 842 | continue; |
| 667 | } | 843 | } |
| 668 | break; | 844 | break; |
| 669 | case TokenizeStateSawBang: | 845 | case TokenizeState_pipe: |
| 670 | switch (c) { | 846 | switch (c) { |
| 847 | case 0: | ||
| 848 | goto eof; | ||
| 671 | case '=': | 849 | case '=': |
| 672 | set_token_id(&t, t.cur_tok, TokenIdCmpNotEq); | 850 | t.out->ids.last() = TokenIdBitOrEq; |
| 673 | end_token(&t); | 851 | t.state = TokenizeState_start; |
| 674 | t.state = TokenizeStateStart; | 852 | break; |
| 853 | case '|': | ||
| 854 | t.out->ids.last() = TokenIdBarBar; | ||
| 855 | t.state = TokenizeState_start; | ||
| 675 | break; | 856 | break; |
| 676 | default: | 857 | default: |
| 677 | t.pos -= 1; | 858 | t.state = TokenizeState_start; |
| 678 | end_token(&t); | ||
| 679 | t.state = TokenizeStateStart; | ||
| 680 | continue; | 859 | continue; |
| 681 | } | 860 | } |
| 682 | break; | 861 | break; |
| 683 | case TokenizeStateSawEq: | 862 | case TokenizeState_equal: |
| 684 | switch (c) { | 863 | switch (c) { |
| 864 | case 0: | ||
| 865 | goto eof; | ||
| 685 | case '=': | 866 | case '=': |
| 686 | set_token_id(&t, t.cur_tok, TokenIdCmpEq); | 867 | t.out->ids.last() = TokenIdCmpEq; |
| 687 | end_token(&t); | 868 | t.state = TokenizeState_start; |
| 688 | t.state = TokenizeStateStart; | ||
| 689 | break; | 869 | break; |
| 690 | case '>': | 870 | case '>': |
| 691 | set_token_id(&t, t.cur_tok, TokenIdFatArrow); | 871 | t.out->ids.last() = TokenIdFatArrow; |
| 692 | end_token(&t); | 872 | t.state = TokenizeState_start; |
| 693 | t.state = TokenizeStateStart; | ||
| 694 | break; | 873 | break; |
| 695 | default: | 874 | default: |
| 696 | t.pos -= 1; | 875 | t.state = TokenizeState_start; |
| 697 | end_token(&t); | ||
| 698 | t.state = TokenizeStateStart; | ||
| 699 | continue; | 876 | continue; |
| 700 | } | 877 | } |
| 701 | break; | 878 | break; |
| 702 | case TokenizeStateSawStar: | 879 | case TokenizeState_minus: |
| 703 | switch (c) { | 880 | switch (c) { |
| 704 | case '=': | 881 | case 0: |
| 705 | set_token_id(&t, t.cur_tok, TokenIdTimesEq); | 882 | goto eof; |
| 706 | end_token(&t); | 883 | case '>': |
| 707 | t.state = TokenizeStateStart; | 884 | t.out->ids.last() = TokenIdArrow; |
| 885 | t.state = TokenizeState_start; | ||
| 708 | break; | 886 | break; |
| 709 | case '*': | 887 | case '=': |
| 710 | set_token_id(&t, t.cur_tok, TokenIdStarStar); | 888 | t.out->ids.last() = TokenIdMinusEq; |
| 711 | end_token(&t); | 889 | t.state = TokenizeState_start; |
| 712 | t.state = TokenizeStateStart; | ||
| 713 | break; | 890 | break; |
| 714 | case '%': | 891 | case '%': |
| 715 | set_token_id(&t, t.cur_tok, TokenIdTimesPercent); | 892 | t.state = TokenizeState_minus_percent; |
| 716 | t.state = TokenizeStateSawStarPercent; | ||
| 717 | break; | 893 | break; |
| 718 | default: | 894 | default: |
| 719 | t.pos -= 1; | 895 | t.state = TokenizeState_start; |
| 720 | end_token(&t); | ||
| 721 | t.state = TokenizeStateStart; | ||
| 722 | continue; | 896 | continue; |
| 723 | } | 897 | } |
| 724 | break; | 898 | break; |
| 725 | case TokenizeStateSawStarPercent: | 899 | case TokenizeState_minus_percent: |
| 726 | switch (c) { | 900 | switch (c) { |
| 901 | case 0: | ||
| 902 | t.out->ids.last() = TokenIdMinusPercent; | ||
| 903 | goto eof; | ||
| 727 | case '=': | 904 | case '=': |
| 728 | set_token_id(&t, t.cur_tok, TokenIdTimesPercentEq); | 905 | t.out->ids.last() = TokenIdMinusPercentEq; |
| 729 | end_token(&t); | 906 | t.state = TokenizeState_start; |
| 730 | t.state = TokenizeStateStart; | ||
| 731 | break; | 907 | break; |
| 732 | default: | 908 | default: |
| 733 | t.pos -= 1; | 909 | t.out->ids.last() = TokenIdMinusPercent; |
| 734 | end_token(&t); | 910 | t.state = TokenizeState_start; |
| 735 | t.state = TokenizeStateStart; | ||
| 736 | continue; | 911 | continue; |
| 737 | } | 912 | } |
| 738 | break; | 913 | break; |
| 739 | case TokenizeStateSawPercent: | 914 | case TokenizeState_angle_bracket_left: |
| 740 | switch (c) { | 915 | switch (c) { |
| 916 | case 0: | ||
| 917 | goto eof; | ||
| 741 | case '=': | 918 | case '=': |
| 742 | set_token_id(&t, t.cur_tok, TokenIdModEq); | 919 | t.out->ids.last() = TokenIdCmpLessOrEq; |
| 743 | end_token(&t); | 920 | t.state = TokenizeState_start; |
| 744 | t.state = TokenizeStateStart; | ||
| 745 | break; | 921 | break; |
| 746 | case '.': | 922 | case '<': |
| 747 | set_token_id(&t, t.cur_tok, TokenIdPercentDot); | 923 | t.state = TokenizeState_angle_bracket_angle_bracket_left; |
| 748 | end_token(&t); | ||
| 749 | t.state = TokenizeStateStart; | ||
| 750 | break; | 924 | break; |
| 751 | default: | 925 | default: |
| 752 | t.pos -= 1; | 926 | t.state = TokenizeState_start; |
| 753 | end_token(&t); | ||
| 754 | t.state = TokenizeStateStart; | ||
| 755 | continue; | 927 | continue; |
| 756 | } | 928 | } |
| 757 | break; | 929 | break; |
| 758 | case TokenizeStateSawPlus: | 930 | case TokenizeState_angle_bracket_angle_bracket_left: |
| 759 | switch (c) { | 931 | switch (c) { |
| 932 | case 0: | ||
| 933 | t.out->ids.last() = TokenIdBitShiftLeft; | ||
| 934 | goto eof; | ||
| 760 | case '=': | 935 | case '=': |
| 761 | set_token_id(&t, t.cur_tok, TokenIdPlusEq); | 936 | t.out->ids.last() = TokenIdBitShiftLeftEq; |
| 762 | end_token(&t); | 937 | t.state = TokenizeState_start; |
| 763 | t.state = TokenizeStateStart; | ||
| 764 | break; | 938 | break; |
| 765 | case '+': | 939 | default: |
| 766 | set_token_id(&t, t.cur_tok, TokenIdPlusPlus); | 940 | t.out->ids.last() = TokenIdBitShiftLeft; |
| 767 | end_token(&t); | 941 | t.state = TokenizeState_start; |
| 768 | t.state = TokenizeStateStart; | 942 | continue; |
| 943 | } | ||
| 944 | break; | ||
| 945 | case TokenizeState_angle_bracket_right: | ||
| 946 | switch (c) { | ||
| 947 | case 0: | ||
| 948 | goto eof; | ||
| 949 | case '=': | ||
| 950 | t.out->ids.last() = TokenIdCmpGreaterOrEq; | ||
| 951 | t.state = TokenizeState_start; | ||
| 769 | break; | 952 | break; |
| 770 | case '%': | 953 | case '>': |
| 771 | set_token_id(&t, t.cur_tok, TokenIdPlusPercent); | 954 | t.state = TokenizeState_angle_bracket_angle_bracket_right; |
| 772 | t.state = TokenizeStateSawPlusPercent; | ||
| 773 | break; | 955 | break; |
| 774 | default: | 956 | default: |
| 775 | t.pos -= 1; | 957 | t.state = TokenizeState_start; |
| 776 | end_token(&t); | ||
| 777 | t.state = TokenizeStateStart; | ||
| 778 | continue; | 958 | continue; |
| 779 | } | 959 | } |
| 780 | break; | 960 | break; |
| 781 | case TokenizeStateSawPlusPercent: | 961 | case TokenizeState_angle_bracket_angle_bracket_right: |
| 782 | switch (c) { | 962 | switch (c) { |
| 963 | case 0: | ||
| 964 | t.out->ids.last() = TokenIdBitShiftRight; | ||
| 965 | goto eof; | ||
| 783 | case '=': | 966 | case '=': |
| 784 | set_token_id(&t, t.cur_tok, TokenIdPlusPercentEq); | 967 | t.out->ids.last() = TokenIdBitShiftRightEq; |
| 785 | end_token(&t); | 968 | t.state = TokenizeState_start; |
| 786 | t.state = TokenizeStateStart; | ||
| 787 | break; | 969 | break; |
| 788 | default: | 970 | default: |
| 789 | t.pos -= 1; | 971 | t.out->ids.last() = TokenIdBitShiftRight; |
| 790 | end_token(&t); | 972 | t.state = TokenizeState_start; |
| 791 | t.state = TokenizeStateStart; | ||
| 792 | continue; | 973 | continue; |
| 793 | } | 974 | } |
| 794 | break; | 975 | break; |
| 795 | case TokenizeStateSawAmpersand: | 976 | case TokenizeState_period: |
| 796 | switch (c) { | 977 | switch (c) { |
| 797 | case '&': | 978 | case 0: |
| 798 | tokenize_error(&t, "`&&` is invalid. Note that `and` is boolean AND"); | 979 | goto eof; |
| 980 | case '.': | ||
| 981 | t.state = TokenizeState_period_2; | ||
| 799 | break; | 982 | break; |
| 800 | case '=': | 983 | case '*': |
| 801 | set_token_id(&t, t.cur_tok, TokenIdBitAndEq); | 984 | t.state = TokenizeState_period_asterisk; |
| 802 | end_token(&t); | ||
| 803 | t.state = TokenizeStateStart; | ||
| 804 | break; | 985 | break; |
| 805 | default: | 986 | default: |
| 806 | t.pos -= 1; | 987 | t.state = TokenizeState_start; |
| 807 | end_token(&t); | ||
| 808 | t.state = TokenizeStateStart; | ||
| 809 | continue; | 988 | continue; |
| 810 | } | 989 | } |
| 811 | break; | 990 | break; |
| 812 | case TokenizeStateSawCaret: | 991 | case TokenizeState_period_2: |
| 813 | switch (c) { | 992 | switch (c) { |
| 814 | case '=': | 993 | case 0: |
| 815 | set_token_id(&t, t.cur_tok, TokenIdBitXorEq); | 994 | t.out->ids.last() = TokenIdEllipsis2; |
| 816 | end_token(&t); | 995 | goto eof; |
| 817 | t.state = TokenizeStateStart; | 996 | case '.': |
| 997 | t.out->ids.last() = TokenIdEllipsis3; | ||
| 998 | t.state = TokenizeState_start; | ||
| 818 | break; | 999 | break; |
| 819 | default: | 1000 | default: |
| 820 | t.pos -= 1; | 1001 | t.out->ids.last() = TokenIdEllipsis2; |
| 821 | end_token(&t); | 1002 | t.state = TokenizeState_start; |
| 822 | t.state = TokenizeStateStart; | ||
| 823 | continue; | 1003 | continue; |
| 824 | } | 1004 | } |
| 825 | break; | 1005 | break; |
| 826 | case TokenizeStateSawBar: | 1006 | case TokenizeState_period_asterisk: |
| 827 | switch (c) { | 1007 | switch (c) { |
| 828 | case '=': | 1008 | case 0: |
| 829 | set_token_id(&t, t.cur_tok, TokenIdBitOrEq); | 1009 | t.out->ids.last() = TokenIdDotStar; |
| 830 | end_token(&t); | 1010 | goto eof; |
| 831 | t.state = TokenizeStateStart; | 1011 | case '*': |
| 832 | break; | 1012 | tokenize_error(&t, "`.*` cannot be followed by `*`. Are you missing a space?"); |
| 833 | case '|': | ||
| 834 | set_token_id(&t, t.cur_tok, TokenIdBarBar); | ||
| 835 | end_token(&t); | ||
| 836 | t.state = TokenizeStateStart; | ||
| 837 | break; | 1013 | break; |
| 838 | default: | 1014 | default: |
| 839 | t.pos -= 1; | 1015 | t.out->ids.last() = TokenIdDotStar; |
| 840 | end_token(&t); | 1016 | t.state = TokenizeState_start; |
| 841 | t.state = TokenizeStateStart; | ||
| 842 | continue; | 1017 | continue; |
| 843 | } | 1018 | } |
| 844 | break; | 1019 | break; |
| 845 | case TokenizeStateSawSlash: | 1020 | case TokenizeState_slash: |
| 846 | switch (c) { | 1021 | switch (c) { |
| 1022 | case 0: | ||
| 1023 | goto eof; | ||
| 847 | case '/': | 1024 | case '/': |
| 848 | t.state = TokenizeStateSawSlash2; | 1025 | t.state = TokenizeState_line_comment_start; |
| 849 | break; | 1026 | break; |
| 850 | case '=': | 1027 | case '=': |
| 851 | set_token_id(&t, t.cur_tok, TokenIdDivEq); | 1028 | t.out->ids.last() = TokenIdDivEq; |
| 852 | end_token(&t); | 1029 | t.state = TokenizeState_start; |
| 853 | t.state = TokenizeStateStart; | ||
| 854 | break; | 1030 | break; |
| 855 | default: | 1031 | default: |
| 856 | t.pos -= 1; | 1032 | t.state = TokenizeState_start; |
| 857 | end_token(&t); | ||
| 858 | t.state = TokenizeStateStart; | ||
| 859 | continue; | 1033 | continue; |
| 860 | } | 1034 | } |
| 861 | break; | 1035 | break; |
| 862 | case TokenizeStateSawSlash2: | 1036 | case TokenizeState_line_comment_start: |
| 863 | switch (c) { | 1037 | switch (c) { |
| 1038 | case 0: | ||
| 1039 | goto eof; | ||
| 864 | case '/': | 1040 | case '/': |
| 865 | t.state = TokenizeStateSawSlash3; | 1041 | t.state = TokenizeState_doc_comment_start; |
| 866 | break; | 1042 | break; |
| 867 | case '!': | 1043 | case '!': |
| 868 | t.state = TokenizeStateSawSlashBang; | 1044 | t.out->ids.last() = TokenIdContainerDocComment; |
| 1045 | t.state = TokenizeState_container_doc_comment; | ||
| 869 | break; | 1046 | break; |
| 870 | case '\n': | 1047 | case '\n': |
| 871 | cancel_token(&t); | 1048 | cancel_token(&t); |
| 872 | t.state = TokenizeStateStart; | 1049 | t.state = TokenizeState_start; |
| 873 | break; | 1050 | break; |
| 874 | default: | 1051 | default: |
| 875 | cancel_token(&t); | 1052 | cancel_token(&t); |
| 876 | t.state = TokenizeStateLineComment; | 1053 | t.state = TokenizeState_line_comment; |
| 877 | break; | 1054 | break; |
| 878 | } | 1055 | } |
| 879 | break; | 1056 | break; |
| 880 | case TokenizeStateSawSlash3: | 1057 | case TokenizeState_doc_comment_start: |
| 881 | switch (c) { | 1058 | switch (c) { |
| 1059 | case 0: | ||
| 1060 | t.out->ids.last() = TokenIdDocComment; | ||
| 1061 | goto eof; | ||
| 882 | case '/': | 1062 | case '/': |
| 883 | cancel_token(&t); | 1063 | cancel_token(&t); |
| 884 | t.state = TokenizeStateLineComment; | 1064 | t.state = TokenizeState_line_comment; |
| 885 | break; | 1065 | break; |
| 886 | case '\n': | 1066 | case '\n': |
| 887 | set_token_id(&t, t.cur_tok, TokenIdDocComment); | 1067 | t.out->ids.last() = TokenIdDocComment; |
| 888 | end_token(&t); | 1068 | t.state = TokenizeState_start; |
| 889 | t.state = TokenizeStateStart; | ||
| 890 | break; | 1069 | break; |
| 891 | default: | 1070 | default: |
| 892 | set_token_id(&t, t.cur_tok, TokenIdDocComment); | 1071 | t.out->ids.last() = TokenIdDocComment; |
| 893 | t.state = TokenizeStateDocComment; | 1072 | t.state = TokenizeState_doc_comment; |
| 894 | break; | 1073 | break; |
| 895 | } | 1074 | } |
| 896 | break; | 1075 | break; |
| 897 | case TokenizeStateSawSlashBang: | 1076 | case TokenizeState_line_comment: |
| 898 | switch (c) { | 1077 | switch (c) { |
| 1078 | case 0: | ||
| 1079 | goto eof; | ||
| 899 | case '\n': | 1080 | case '\n': |
| 900 | set_token_id(&t, t.cur_tok, TokenIdContainerDocComment); | 1081 | t.state = TokenizeState_start; |
| 901 | end_token(&t); | ||
| 902 | t.state = TokenizeStateStart; | ||
| 903 | break; | 1082 | break; |
| 904 | default: | 1083 | default: |
| 905 | set_token_id(&t, t.cur_tok, TokenIdContainerDocComment); | ||
| 906 | t.state = TokenizeStateContainerDocComment; | ||
| 907 | break; | 1084 | break; |
| 908 | } | 1085 | } |
| 909 | break; | 1086 | break; |
| 910 | case TokenizeStateSawBackslash: | 1087 | case TokenizeState_doc_comment: |
| 1088 | case TokenizeState_container_doc_comment: | ||
| 911 | switch (c) { | 1089 | switch (c) { |
| 912 | case '\\': | 1090 | case 0: |
| 913 | t.state = TokenizeStateLineString; | 1091 | goto eof; |
| 1092 | case '\n': | ||
| 1093 | t.state = TokenizeState_start; | ||
| 914 | break; | 1094 | break; |
| 915 | default: | 1095 | default: |
| 916 | invalid_char_error(&t, c); | 1096 | // do nothing |
| 917 | break; | 1097 | break; |
| 918 | } | 1098 | } |
| 919 | break; | 1099 | break; |
| 920 | case TokenizeStateLineString: | 1100 | case TokenizeState_zero: |
| 921 | switch (c) { | 1101 | switch (c) { |
| 922 | case '\n': | 1102 | case 0: |
| 923 | t.state = TokenizeStateLineStringEnd; | 1103 | goto eof; |
| 1104 | case 'b': | ||
| 1105 | t.state = TokenizeState_int_literal_bin_no_underscore; | ||
| 924 | break; | 1106 | break; |
| 925 | default: | 1107 | case 'o': |
| 926 | buf_append_char(&t.cur_tok->data.str_lit.str, c); | 1108 | t.state = TokenizeState_int_literal_oct_no_underscore; |
| 927 | break; | 1109 | break; |
| 928 | } | 1110 | case 'x': |
| 929 | break; | 1111 | t.state = TokenizeState_int_literal_hex_no_underscore; |
| 930 | case TokenizeStateLineStringEnd: | ||
| 931 | switch (c) { | ||
| 932 | case WHITESPACE: | ||
| 933 | break; | 1112 | break; |
| 934 | case '\\': | 1113 | case DIGIT: |
| 935 | t.state = TokenizeStateLineStringContinue; | 1114 | case '_': |
| 1115 | case '.': | ||
| 1116 | case 'e': | ||
| 1117 | case 'E': | ||
| 1118 | // Reinterpret as a decimal number. | ||
| 1119 | t.state = TokenizeState_int_literal_dec; | ||
| 1120 | continue; | ||
| 1121 | case ALPHA_EXCEPT_E_B_O_X: | ||
| 1122 | invalid_char_error(&t, c); | ||
| 936 | break; | 1123 | break; |
| 937 | default: | 1124 | default: |
| 938 | t.pos -= 1; | 1125 | t.state = TokenizeState_start; |
| 939 | end_token(&t); | ||
| 940 | t.state = TokenizeStateStart; | ||
| 941 | continue; | 1126 | continue; |
| 942 | } | 1127 | } |
| 943 | break; | 1128 | break; |
| 944 | case TokenizeStateLineStringContinue: | 1129 | case TokenizeState_int_literal_bin_no_underscore: |
| 945 | switch (c) { | 1130 | switch (c) { |
| 946 | case '\\': | 1131 | case '0': |
| 947 | t.state = TokenizeStateLineString; | 1132 | case '1': |
| 948 | buf_append_char(&t.cur_tok->data.str_lit.str, '\n'); | 1133 | t.state = TokenizeState_int_literal_bin; |
| 949 | break; | 1134 | break; |
| 950 | default: | 1135 | default: |
| 951 | invalid_char_error(&t, c); | 1136 | invalid_char_error(&t, c); |
| 952 | break; | ||
| 953 | } | 1137 | } |
| 954 | break; | 1138 | break; |
| 955 | case TokenizeStateLineComment: | 1139 | case TokenizeState_int_literal_bin: |
| 956 | switch (c) { | 1140 | switch (c) { |
| 957 | case '\n': | 1141 | case 0: |
| 958 | t.state = TokenizeStateStart; | 1142 | goto eof; |
| 1143 | case '_': | ||
| 1144 | t.state = TokenizeState_int_literal_bin_no_underscore; | ||
| 959 | break; | 1145 | break; |
| 960 | default: | 1146 | case '0': |
| 961 | // do nothing | 1147 | case '1': |
| 1148 | break; | ||
| 1149 | case '2': | ||
| 1150 | case '3': | ||
| 1151 | case '4': | ||
| 1152 | case '5': | ||
| 1153 | case '6': | ||
| 1154 | case '7': | ||
| 1155 | case '8': | ||
| 1156 | case '9': | ||
| 1157 | case ALPHA: | ||
| 1158 | invalid_char_error(&t, c); | ||
| 962 | break; | 1159 | break; |
| 1160 | default: | ||
| 1161 | t.state = TokenizeState_start; | ||
| 1162 | continue; | ||
| 963 | } | 1163 | } |
| 964 | break; | 1164 | break; |
| 965 | case TokenizeStateDocComment: | 1165 | case TokenizeState_int_literal_oct_no_underscore: |
| 966 | switch (c) { | 1166 | switch (c) { |
| 967 | case '\n': | 1167 | case '0': |
| 968 | end_token(&t); | 1168 | case '1': |
| 969 | t.state = TokenizeStateStart; | 1169 | case '2': |
| 1170 | case '3': | ||
| 1171 | case '4': | ||
| 1172 | case '5': | ||
| 1173 | case '6': | ||
| 1174 | case '7': | ||
| 1175 | t.state = TokenizeState_int_literal_oct; | ||
| 970 | break; | 1176 | break; |
| 971 | default: | 1177 | default: |
| 972 | // do nothing | 1178 | invalid_char_error(&t, c); |
| 973 | break; | 1179 | break; |
| 974 | } | 1180 | } |
| 975 | break; | 1181 | break; |
| 976 | case TokenizeStateContainerDocComment: | 1182 | case TokenizeState_int_literal_oct: |
| 977 | switch (c) { | 1183 | switch (c) { |
| 978 | case '\n': | 1184 | case 0: |
| 979 | end_token(&t); | 1185 | goto eof; |
| 980 | t.state = TokenizeStateStart; | 1186 | case '_': |
| 1187 | t.state = TokenizeState_int_literal_oct_no_underscore; | ||
| 981 | break; | 1188 | break; |
| 982 | default: | 1189 | case '0': |
| 983 | // do nothing | 1190 | case '1': |
| 1191 | case '2': | ||
| 1192 | case '3': | ||
| 1193 | case '4': | ||
| 1194 | case '5': | ||
| 1195 | case '6': | ||
| 1196 | case '7': | ||
| 984 | break; | 1197 | break; |
| 985 | } | 1198 | case ALPHA: |
| 986 | break; | 1199 | case '8': |
| 987 | case TokenizeStateSawAtSign: | 1200 | case '9': |
| 988 | switch (c) { | 1201 | invalid_char_error(&t, c); |
| 989 | case '"': | ||
| 990 | set_token_id(&t, t.cur_tok, TokenIdSymbol); | ||
| 991 | t.state = TokenizeStateString; | ||
| 992 | break; | 1202 | break; |
| 993 | default: | 1203 | default: |
| 994 | t.pos -= 1; | 1204 | t.state = TokenizeState_start; |
| 995 | end_token(&t); | ||
| 996 | t.state = TokenizeStateStart; | ||
| 997 | continue; | 1205 | continue; |
| 998 | } | 1206 | } |
| 999 | break; | 1207 | break; |
| 1000 | case TokenizeStateSymbol: | 1208 | case TokenizeState_int_literal_dec_no_underscore: |
| 1001 | switch (c) { | 1209 | switch (c) { |
| 1002 | case SYMBOL_CHAR: | 1210 | case DIGIT: |
| 1003 | buf_append_char(&t.cur_tok->data.str_lit.str, c); | 1211 | t.state = TokenizeState_int_literal_dec; |
| 1004 | break; | 1212 | break; |
| 1005 | default: | 1213 | default: |
| 1006 | t.pos -= 1; | 1214 | invalid_char_error(&t, c); |
| 1007 | end_token(&t); | 1215 | break; |
| 1008 | t.state = TokenizeStateStart; | ||
| 1009 | continue; | ||
| 1010 | } | 1216 | } |
| 1011 | break; | 1217 | break; |
| 1012 | case TokenizeStateString: | 1218 | case TokenizeState_int_literal_dec: |
| 1013 | switch (c) { | 1219 | switch (c) { |
| 1014 | case '"': | 1220 | case 0: |
| 1015 | end_token(&t); | 1221 | goto eof; |
| 1016 | t.state = TokenizeStateStart; | 1222 | case '_': |
| 1223 | t.state = TokenizeState_int_literal_dec_no_underscore; | ||
| 1017 | break; | 1224 | break; |
| 1018 | case '\n': | 1225 | case '.': |
| 1019 | tokenize_error(&t, "newline not allowed in string literal"); | 1226 | t.state = TokenizeState_num_dot_dec; |
| 1227 | t.out->ids.last() = TokenIdFloatLiteral; | ||
| 1020 | break; | 1228 | break; |
| 1021 | case '\\': | 1229 | case 'e': |
| 1022 | t.state = TokenizeStateStringEscape; | 1230 | case 'E': |
| 1231 | t.state = TokenizeState_float_exponent_unsigned; | ||
| 1232 | t.out->ids.last() = TokenIdFloatLiteral; | ||
| 1023 | break; | 1233 | break; |
| 1024 | default: | 1234 | case DIGIT: |
| 1025 | buf_append_char(&t.cur_tok->data.str_lit.str, c); | 1235 | break; |
| 1236 | case ALPHA_EXCEPT_E: | ||
| 1237 | invalid_char_error(&t, c); | ||
| 1026 | break; | 1238 | break; |
| 1239 | default: | ||
| 1240 | t.state = TokenizeState_start; | ||
| 1241 | continue; | ||
| 1027 | } | 1242 | } |
| 1028 | break; | 1243 | break; |
| 1029 | case TokenizeStateStringEscape: | 1244 | case TokenizeState_int_literal_hex_no_underscore: |
| 1030 | switch (c) { | 1245 | switch (c) { |
| 1031 | case 'x': | 1246 | case HEXDIGIT: |
| 1032 | t.state = TokenizeStateCharCode; | 1247 | t.state = TokenizeState_int_literal_hex; |
| 1033 | t.radix = 16; | ||
| 1034 | t.char_code = 0; | ||
| 1035 | t.char_code_index = 0; | ||
| 1036 | t.unicode = false; | ||
| 1037 | break; | ||
| 1038 | case 'u': | ||
| 1039 | t.state = TokenizeStateStringEscapeUnicodeStart; | ||
| 1040 | break; | ||
| 1041 | case 'n': | ||
| 1042 | handle_string_escape(&t, '\n'); | ||
| 1043 | break; | 1248 | break; |
| 1044 | case 'r': | 1249 | default: |
| 1045 | handle_string_escape(&t, '\r'); | 1250 | invalid_char_error(&t, c); |
| 1251 | } | ||
| 1252 | break; | ||
| 1253 | case TokenizeState_int_literal_hex: | ||
| 1254 | switch (c) { | ||
| 1255 | case 0: | ||
| 1256 | goto eof; | ||
| 1257 | case '_': | ||
| 1258 | t.state = TokenizeState_int_literal_hex_no_underscore; | ||
| 1046 | break; | 1259 | break; |
| 1047 | case '\\': | 1260 | case '.': |
| 1048 | handle_string_escape(&t, '\\'); | 1261 | t.state = TokenizeState_num_dot_hex; |
| 1262 | t.out->ids.last() = TokenIdFloatLiteral; | ||
| 1049 | break; | 1263 | break; |
| 1050 | case 't': | 1264 | case 'p': |
| 1051 | handle_string_escape(&t, '\t'); | 1265 | case 'P': |
| 1266 | t.state = TokenizeState_float_exponent_unsigned; | ||
| 1267 | t.out->ids.last() = TokenIdFloatLiteral; | ||
| 1052 | break; | 1268 | break; |
| 1053 | case '\'': | 1269 | case HEXDIGIT: |
| 1054 | handle_string_escape(&t, '\''); | ||
| 1055 | break; | 1270 | break; |
| 1056 | case '"': | 1271 | case ALPHA_EXCEPT_HEX_AND_P: |
| 1057 | handle_string_escape(&t, '\"'); | 1272 | invalid_char_error(&t, c); |
| 1058 | break; | 1273 | break; |
| 1059 | default: | 1274 | default: |
| 1060 | invalid_char_error(&t, c); | 1275 | t.state = TokenizeState_start; |
| 1276 | continue; | ||
| 1061 | } | 1277 | } |
| 1062 | break; | 1278 | break; |
| 1063 | case TokenizeStateStringEscapeUnicodeStart: | 1279 | case TokenizeState_num_dot_dec: |
| 1064 | switch (c) { | 1280 | switch (c) { |
| 1065 | case '{': | 1281 | case 0: |
| 1066 | t.state = TokenizeStateCharCode; | 1282 | goto eof; |
| 1067 | t.radix = 16; | 1283 | case '.': |
| 1068 | t.char_code = 0; | 1284 | t.out->ids.last() = TokenIdIntLiteral; |
| 1069 | t.char_code_index = 0; | 1285 | t.pos -= 1; |
| 1070 | t.unicode = true; | 1286 | t.column -= 1; |
| 1287 | t.state = TokenizeState_start; | ||
| 1288 | continue; | ||
| 1289 | case 'e': | ||
| 1290 | case 'E': | ||
| 1291 | t.state = TokenizeState_float_exponent_unsigned; | ||
| 1292 | break; | ||
| 1293 | case DIGIT: | ||
| 1294 | t.state = TokenizeState_float_fraction_dec; | ||
| 1071 | break; | 1295 | break; |
| 1072 | default: | 1296 | default: |
| 1073 | invalid_char_error(&t, c); | 1297 | invalid_char_error(&t, c); |
| 1298 | break; | ||
| 1074 | } | 1299 | } |
| 1075 | break; | 1300 | break; |
| 1076 | case TokenizeStateCharCode: | 1301 | case TokenizeState_num_dot_hex: |
| 1077 | { | 1302 | switch (c) { |
| 1078 | if (t.unicode && c == '}') { | 1303 | case 0: |
| 1079 | if (t.char_code_index == 0) { | 1304 | goto eof; |
| 1080 | tokenize_error(&t, "empty unicode escape sequence"); | 1305 | case '.': |
| 1081 | break; | 1306 | t.out->ids.last() = TokenIdIntLiteral; |
| 1082 | } | 1307 | t.pos -= 1; |
| 1083 | if (t.char_code > 0x10ffff) { | 1308 | t.column -= 1; |
| 1084 | tokenize_error(&t, "unicode value out of range: %x", t.char_code); | 1309 | t.state = TokenizeState_start; |
| 1085 | break; | 1310 | continue; |
| 1086 | } | 1311 | case 'p': |
| 1087 | if (t.cur_tok->id == TokenIdCharLiteral) { | 1312 | case 'P': |
| 1088 | t.cur_tok->data.char_lit.c = t.char_code; | 1313 | t.state = TokenizeState_float_exponent_unsigned; |
| 1089 | t.state = TokenizeStateCharLiteralEnd; | ||
| 1090 | } else if (t.char_code <= 0x7f) { | ||
| 1091 | // 00000000 00000000 00000000 0xxxxxxx | ||
| 1092 | handle_string_escape(&t, (uint8_t)t.char_code); | ||
| 1093 | } else if (t.char_code <= 0x7ff) { | ||
| 1094 | // 00000000 00000000 00000xxx xx000000 | ||
| 1095 | handle_string_escape(&t, (uint8_t)(0xc0 | (t.char_code >> 6))); | ||
| 1096 | // 00000000 00000000 00000000 00xxxxxx | ||
| 1097 | handle_string_escape(&t, (uint8_t)(0x80 | (t.char_code & 0x3f))); | ||
| 1098 | } else if (t.char_code <= 0xffff) { | ||
| 1099 | // 00000000 00000000 xxxx0000 00000000 | ||
| 1100 | handle_string_escape(&t, (uint8_t)(0xe0 | (t.char_code >> 12))); | ||
| 1101 | // 00000000 00000000 0000xxxx xx000000 | ||
| 1102 | handle_string_escape(&t, (uint8_t)(0x80 | ((t.char_code >> 6) & 0x3f))); | ||
| 1103 | // 00000000 00000000 00000000 00xxxxxx | ||
| 1104 | handle_string_escape(&t, (uint8_t)(0x80 | (t.char_code & 0x3f))); | ||
| 1105 | } else if (t.char_code <= 0x10ffff) { | ||
| 1106 | // 00000000 000xxx00 00000000 00000000 | ||
| 1107 | handle_string_escape(&t, (uint8_t)(0xf0 | (t.char_code >> 18))); | ||
| 1108 | // 00000000 000000xx xxxx0000 00000000 | ||
| 1109 | handle_string_escape(&t, (uint8_t)(0x80 | ((t.char_code >> 12) & 0x3f))); | ||
| 1110 | // 00000000 00000000 0000xxxx xx000000 | ||
| 1111 | handle_string_escape(&t, (uint8_t)(0x80 | ((t.char_code >> 6) & 0x3f))); | ||
| 1112 | // 00000000 00000000 00000000 00xxxxxx | ||
| 1113 | handle_string_escape(&t, (uint8_t)(0x80 | (t.char_code & 0x3f))); | ||
| 1114 | } else { | ||
| 1115 | zig_unreachable(); | ||
| 1116 | } | ||
| 1117 | break; | 1314 | break; |
| 1118 | } | 1315 | case HEXDIGIT: |
| 1119 | 1316 | t.out->ids.last() = TokenIdFloatLiteral; | |
| 1120 | uint32_t digit_value = get_digit_value(c); | 1317 | t.state = TokenizeState_float_fraction_hex; |
| 1121 | if (digit_value >= t.radix) { | 1318 | break; |
| 1122 | tokenize_error(&t, "invalid digit: '%c'", c); | 1319 | default: |
| 1320 | invalid_char_error(&t, c); | ||
| 1123 | break; | 1321 | break; |
| 1124 | } | ||
| 1125 | t.char_code *= t.radix; | ||
| 1126 | t.char_code += digit_value; | ||
| 1127 | t.char_code_index += 1; | ||
| 1128 | |||
| 1129 | if (!t.unicode && t.char_code_index >= 2) { | ||
| 1130 | assert(t.char_code <= 255); | ||
| 1131 | handle_string_escape(&t, (uint8_t)t.char_code); | ||
| 1132 | } | ||
| 1133 | } | ||
| 1134 | break; | ||
| 1135 | case TokenizeStateCharLiteral: | ||
| 1136 | if (c == '\'') { | ||
| 1137 | tokenize_error(&t, "expected character"); | ||
| 1138 | } else if (c == '\\') { | ||
| 1139 | t.state = TokenizeStateStringEscape; | ||
| 1140 | } else if ((c >= 0x80 && c <= 0xbf) || c >= 0xf8) { | ||
| 1141 | // 10xxxxxx | ||
| 1142 | // 11111xxx | ||
| 1143 | invalid_char_error(&t, c); | ||
| 1144 | } else if (c >= 0xc0 && c <= 0xdf) { | ||
| 1145 | // 110xxxxx | ||
| 1146 | t.cur_tok->data.char_lit.c = c & 0x1f; | ||
| 1147 | t.remaining_code_units = 1; | ||
| 1148 | t.state = TokenizeStateCharLiteralUnicode; | ||
| 1149 | } else if (c >= 0xe0 && c <= 0xef) { | ||
| 1150 | // 1110xxxx | ||
| 1151 | t.cur_tok->data.char_lit.c = c & 0x0f; | ||
| 1152 | t.remaining_code_units = 2; | ||
| 1153 | t.state = TokenizeStateCharLiteralUnicode; | ||
| 1154 | } else if (c >= 0xf0 && c <= 0xf7) { | ||
| 1155 | // 11110xxx | ||
| 1156 | t.cur_tok->data.char_lit.c = c & 0x07; | ||
| 1157 | t.remaining_code_units = 3; | ||
| 1158 | t.state = TokenizeStateCharLiteralUnicode; | ||
| 1159 | } else { | ||
| 1160 | t.cur_tok->data.char_lit.c = c; | ||
| 1161 | t.state = TokenizeStateCharLiteralEnd; | ||
| 1162 | } | 1322 | } |
| 1163 | break; | 1323 | break; |
| 1164 | case TokenizeStateCharLiteralEnd: | 1324 | case TokenizeState_float_fraction_dec_no_underscore: |
| 1165 | switch (c) { | 1325 | switch (c) { |
| 1166 | case '\'': | 1326 | case DIGIT: |
| 1167 | end_token(&t); | 1327 | t.state = TokenizeState_float_fraction_dec; |
| 1168 | t.state = TokenizeStateStart; | ||
| 1169 | break; | 1328 | break; |
| 1170 | default: | 1329 | default: |
| 1171 | invalid_char_error(&t, c); | 1330 | invalid_char_error(&t, c); |
| 1172 | } | 1331 | } |
| 1173 | break; | 1332 | break; |
| 1174 | case TokenizeStateCharLiteralUnicode: | 1333 | case TokenizeState_float_fraction_dec: |
| 1175 | if (c <= 0x7f || c >= 0xc0) { | ||
| 1176 | invalid_char_error(&t, c); | ||
| 1177 | } | ||
| 1178 | t.cur_tok->data.char_lit.c <<= 6; | ||
| 1179 | t.cur_tok->data.char_lit.c += c & 0x3f; | ||
| 1180 | t.remaining_code_units--; | ||
| 1181 | if (t.remaining_code_units == 0) { | ||
| 1182 | t.state = TokenizeStateCharLiteralEnd; | ||
| 1183 | } | ||
| 1184 | break; | ||
| 1185 | case TokenizeStateZero: | ||
| 1186 | switch (c) { | 1334 | switch (c) { |
| 1187 | case 'b': | 1335 | case 0: |
| 1188 | t.radix = 2; | 1336 | goto eof; |
| 1189 | t.state = TokenizeStateNumberNoUnderscore; | 1337 | case '_': |
| 1338 | t.state = TokenizeState_float_fraction_dec_no_underscore; | ||
| 1190 | break; | 1339 | break; |
| 1191 | case 'o': | 1340 | case 'e': |
| 1192 | t.radix = 8; | 1341 | case 'E': |
| 1193 | t.state = TokenizeStateNumberNoUnderscore; | 1342 | t.state = TokenizeState_float_exponent_unsigned; |
| 1194 | break; | 1343 | break; |
| 1195 | case 'x': | 1344 | case DIGIT: |
| 1196 | t.radix = 16; | 1345 | break; |
| 1197 | t.state = TokenizeStateNumberNoUnderscore; | 1346 | case ALPHA_EXCEPT_E: |
| 1347 | invalid_char_error(&t, c); | ||
| 1198 | break; | 1348 | break; |
| 1199 | default: | 1349 | default: |
| 1200 | // reinterpret as normal number | 1350 | t.state = TokenizeState_start; |
| 1201 | t.pos -= 1; | ||
| 1202 | t.state = TokenizeStateNumber; | ||
| 1203 | continue; | 1351 | continue; |
| 1204 | } | 1352 | } |
| 1205 | break; | 1353 | break; |
| 1206 | case TokenizeStateNumberNoUnderscore: | 1354 | case TokenizeState_float_fraction_hex_no_underscore: |
| 1207 | if (c == '_') { | 1355 | switch (c) { |
| 1208 | invalid_char_error(&t, c); | 1356 | case HEXDIGIT: |
| 1209 | break; | 1357 | t.state = TokenizeState_float_fraction_hex; |
| 1210 | } else if (get_digit_value(c) < t.radix) { | 1358 | break; |
| 1211 | t.is_trailing_underscore = false; | 1359 | default: |
| 1212 | t.state = TokenizeStateNumber; | 1360 | invalid_char_error(&t, c); |
| 1213 | } | 1361 | } |
| 1214 | ZIG_FALLTHROUGH; | 1362 | break; |
| 1215 | case TokenizeStateNumber: | 1363 | case TokenizeState_float_fraction_hex: |
| 1216 | { | 1364 | switch (c) { |
| 1217 | if (c == '_') { | 1365 | case 0: |
| 1218 | t.is_trailing_underscore = true; | 1366 | goto eof; |
| 1219 | t.state = TokenizeStateNumberNoUnderscore; | 1367 | case '_': |
| 1368 | t.state = TokenizeState_float_fraction_hex_no_underscore; | ||
| 1220 | break; | 1369 | break; |
| 1221 | } | 1370 | case 'p': |
| 1222 | if (c == '.') { | 1371 | case 'P': |
| 1223 | if (t.is_trailing_underscore) { | 1372 | t.state = TokenizeState_float_exponent_unsigned; |
| 1224 | invalid_char_error(&t, c); | ||
| 1225 | break; | ||
| 1226 | } | ||
| 1227 | t.state = TokenizeStateNumberDot; | ||
| 1228 | break; | 1373 | break; |
| 1229 | } | 1374 | case HEXDIGIT: |
| 1230 | if (is_exponent_signifier(c, t.radix)) { | ||
| 1231 | if (t.is_trailing_underscore) { | ||
| 1232 | invalid_char_error(&t, c); | ||
| 1233 | break; | ||
| 1234 | } | ||
| 1235 | if (t.radix != 16 && t.radix != 10) { | ||
| 1236 | invalid_char_error(&t, c); | ||
| 1237 | } | ||
| 1238 | t.state = TokenizeStateFloatExponentUnsigned; | ||
| 1239 | t.radix = 10; // exponent is always base 10 | ||
| 1240 | assert(t.cur_tok->id == TokenIdIntLiteral); | ||
| 1241 | set_token_id(&t, t.cur_tok, TokenIdFloatLiteral); | ||
| 1242 | break; | 1375 | break; |
| 1243 | } | 1376 | case ALPHA_EXCEPT_HEX_AND_P: |
| 1244 | uint32_t digit_value = get_digit_value(c); | ||
| 1245 | if (digit_value >= t.radix) { | ||
| 1246 | if (t.is_trailing_underscore) { | ||
| 1247 | invalid_char_error(&t, c); | ||
| 1248 | break; | ||
| 1249 | } | ||
| 1250 | |||
| 1251 | if (is_symbol_char(c)) { | ||
| 1252 | invalid_char_error(&t, c); | ||
| 1253 | } | ||
| 1254 | // not my char | ||
| 1255 | t.pos -= 1; | ||
| 1256 | end_token(&t); | ||
| 1257 | t.state = TokenizeStateStart; | ||
| 1258 | continue; | ||
| 1259 | } | ||
| 1260 | BigInt digit_value_bi; | ||
| 1261 | bigint_init_unsigned(&digit_value_bi, digit_value); | ||
| 1262 | |||
| 1263 | BigInt radix_bi; | ||
| 1264 | bigint_init_unsigned(&radix_bi, t.radix); | ||
| 1265 | |||
| 1266 | BigInt multiplied; | ||
| 1267 | bigint_mul(&multiplied, &t.cur_tok->data.int_lit.bigint, &radix_bi); | ||
| 1268 | |||
| 1269 | bigint_add(&t.cur_tok->data.int_lit.bigint, &multiplied, &digit_value_bi); | ||
| 1270 | break; | ||
| 1271 | } | ||
| 1272 | case TokenizeStateNumberDot: | ||
| 1273 | { | ||
| 1274 | if (c == '.') { | ||
| 1275 | t.pos -= 2; | ||
| 1276 | end_token(&t); | ||
| 1277 | t.state = TokenizeStateStart; | ||
| 1278 | continue; | ||
| 1279 | } | ||
| 1280 | if (t.radix != 16 && t.radix != 10) { | ||
| 1281 | invalid_char_error(&t, c); | 1377 | invalid_char_error(&t, c); |
| 1282 | } | ||
| 1283 | t.pos -= 1; | ||
| 1284 | t.state = TokenizeStateFloatFractionNoUnderscore; | ||
| 1285 | assert(t.cur_tok->id == TokenIdIntLiteral); | ||
| 1286 | set_token_id(&t, t.cur_tok, TokenIdFloatLiteral); | ||
| 1287 | continue; | ||
| 1288 | } | ||
| 1289 | case TokenizeStateFloatFractionNoUnderscore: | ||
| 1290 | if (c == '_') { | ||
| 1291 | invalid_char_error(&t, c); | ||
| 1292 | } else if (get_digit_value(c) < t.radix) { | ||
| 1293 | t.is_trailing_underscore = false; | ||
| 1294 | t.state = TokenizeStateFloatFraction; | ||
| 1295 | } | ||
| 1296 | ZIG_FALLTHROUGH; | ||
| 1297 | case TokenizeStateFloatFraction: | ||
| 1298 | { | ||
| 1299 | if (c == '_') { | ||
| 1300 | t.is_trailing_underscore = true; | ||
| 1301 | t.state = TokenizeStateFloatFractionNoUnderscore; | ||
| 1302 | break; | ||
| 1303 | } | ||
| 1304 | if (is_exponent_signifier(c, t.radix)) { | ||
| 1305 | if (t.is_trailing_underscore) { | ||
| 1306 | invalid_char_error(&t, c); | ||
| 1307 | break; | ||
| 1308 | } | ||
| 1309 | t.state = TokenizeStateFloatExponentUnsigned; | ||
| 1310 | t.radix = 10; // exponent is always base 10 | ||
| 1311 | break; | 1378 | break; |
| 1312 | } | 1379 | default: |
| 1313 | uint32_t digit_value = get_digit_value(c); | 1380 | t.state = TokenizeState_start; |
| 1314 | if (digit_value >= t.radix) { | ||
| 1315 | if (t.is_trailing_underscore) { | ||
| 1316 | invalid_char_error(&t, c); | ||
| 1317 | break; | ||
| 1318 | } | ||
| 1319 | if (is_symbol_char(c)) { | ||
| 1320 | invalid_char_error(&t, c); | ||
| 1321 | } | ||
| 1322 | // not my char | ||
| 1323 | t.pos -= 1; | ||
| 1324 | end_token(&t); | ||
| 1325 | t.state = TokenizeStateStart; | ||
| 1326 | continue; | 1381 | continue; |
| 1327 | } | ||
| 1328 | |||
| 1329 | // we use parse_f128 to generate the float literal, so just | ||
| 1330 | // need to get to the end of the token | ||
| 1331 | } | 1382 | } |
| 1332 | break; | 1383 | break; |
| 1333 | case TokenizeStateFloatExponentUnsigned: | 1384 | case TokenizeState_float_exponent_unsigned: |
| 1334 | switch (c) { | 1385 | switch (c) { |
| 1335 | case '+': | 1386 | case '+': |
| 1336 | t.state = TokenizeStateFloatExponentNumberNoUnderscore; | ||
| 1337 | break; | ||
| 1338 | case '-': | 1387 | case '-': |
| 1339 | t.state = TokenizeStateFloatExponentNumberNoUnderscore; | 1388 | t.state = TokenizeState_float_exponent_num_no_underscore; |
| 1340 | break; | 1389 | break; |
| 1341 | default: | 1390 | default: |
| 1342 | // reinterpret as normal exponent number | 1391 | // Reinterpret as a normal exponent number. |
| 1343 | t.pos -= 1; | 1392 | t.state = TokenizeState_float_exponent_num_no_underscore; |
| 1344 | t.state = TokenizeStateFloatExponentNumberNoUnderscore; | ||
| 1345 | continue; | ||
| 1346 | } | ||
| 1347 | break; | ||
| 1348 | case TokenizeStateFloatExponentNumberNoUnderscore: | ||
| 1349 | if (c == '_') { | ||
| 1350 | invalid_char_error(&t, c); | ||
| 1351 | } else if (get_digit_value(c) < t.radix) { | ||
| 1352 | t.is_trailing_underscore = false; | ||
| 1353 | t.state = TokenizeStateFloatExponentNumber; | ||
| 1354 | } | ||
| 1355 | ZIG_FALLTHROUGH; | ||
| 1356 | case TokenizeStateFloatExponentNumber: | ||
| 1357 | { | ||
| 1358 | if (c == '_') { | ||
| 1359 | t.is_trailing_underscore = true; | ||
| 1360 | t.state = TokenizeStateFloatExponentNumberNoUnderscore; | ||
| 1361 | break; | ||
| 1362 | } | ||
| 1363 | uint32_t digit_value = get_digit_value(c); | ||
| 1364 | if (digit_value >= t.radix) { | ||
| 1365 | if (t.is_trailing_underscore) { | ||
| 1366 | invalid_char_error(&t, c); | ||
| 1367 | break; | ||
| 1368 | } | ||
| 1369 | if (is_symbol_char(c)) { | ||
| 1370 | invalid_char_error(&t, c); | ||
| 1371 | } | ||
| 1372 | // not my char | ||
| 1373 | t.pos -= 1; | ||
| 1374 | end_token(&t); | ||
| 1375 | t.state = TokenizeStateStart; | ||
| 1376 | continue; | 1393 | continue; |
| 1377 | } | ||
| 1378 | |||
| 1379 | // we use parse_f128 to generate the float literal, so just | ||
| 1380 | // need to get to the end of the token | ||
| 1381 | } | 1394 | } |
| 1382 | break; | 1395 | break; |
| 1383 | case TokenizeStateSawDash: | 1396 | case TokenizeState_float_exponent_num_no_underscore: |
| 1384 | switch (c) { | 1397 | switch (c) { |
| 1385 | case '>': | 1398 | case DIGIT: |
| 1386 | set_token_id(&t, t.cur_tok, TokenIdArrow); | 1399 | t.state = TokenizeState_float_exponent_num; |
| 1387 | end_token(&t); | ||
| 1388 | t.state = TokenizeStateStart; | ||
| 1389 | break; | ||
| 1390 | case '=': | ||
| 1391 | set_token_id(&t, t.cur_tok, TokenIdMinusEq); | ||
| 1392 | end_token(&t); | ||
| 1393 | t.state = TokenizeStateStart; | ||
| 1394 | break; | ||
| 1395 | case '%': | ||
| 1396 | set_token_id(&t, t.cur_tok, TokenIdMinusPercent); | ||
| 1397 | t.state = TokenizeStateSawMinusPercent; | ||
| 1398 | break; | 1400 | break; |
| 1399 | default: | 1401 | default: |
| 1400 | t.pos -= 1; | 1402 | invalid_char_error(&t, c); |
| 1401 | end_token(&t); | ||
| 1402 | t.state = TokenizeStateStart; | ||
| 1403 | continue; | ||
| 1404 | } | 1403 | } |
| 1405 | break; | 1404 | break; |
| 1406 | case TokenizeStateSawMinusPercent: | 1405 | case TokenizeState_float_exponent_num: |
| 1407 | switch (c) { | 1406 | switch (c) { |
| 1408 | case '=': | 1407 | case 0: |
| 1409 | set_token_id(&t, t.cur_tok, TokenIdMinusPercentEq); | 1408 | goto eof; |
| 1410 | end_token(&t); | 1409 | case '_': |
| 1411 | t.state = TokenizeStateStart; | 1410 | t.state = TokenizeState_float_exponent_num_no_underscore; |
| 1411 | break; | ||
| 1412 | case DIGIT: | ||
| 1413 | break; | ||
| 1414 | case ALPHA: | ||
| 1415 | invalid_char_error(&t, c); | ||
| 1412 | break; | 1416 | break; |
| 1413 | default: | 1417 | default: |
| 1414 | t.pos -= 1; | 1418 | t.state = TokenizeState_start; |
| 1415 | end_token(&t); | ||
| 1416 | t.state = TokenizeStateStart; | ||
| 1417 | continue; | 1419 | continue; |
| 1418 | } | 1420 | } |
| 1419 | break; | 1421 | break; |
| 1420 | } | 1422 | } |
| 1423 | t.pos += 1; | ||
| 1421 | if (c == '\n') { | 1424 | if (c == '\n') { |
| 1422 | out->line_offsets->append(t.pos + 1); | ||
| 1423 | t.line += 1; | 1425 | t.line += 1; |
| 1424 | t.column = 0; | 1426 | t.column = 0; |
| 1425 | } else { | 1427 | } else { |
| 1426 | t.column += 1; | 1428 | t.column += 1; |
| 1427 | } | 1429 | } |
| 1428 | } | 1430 | } |
| 1429 | // EOF | 1431 | eof:; |
| 1430 | switch (t.state) { | 1432 | |
| 1431 | case TokenizeStateStart: | 1433 | begin_token(&t, TokenIdEof); |
| 1432 | case TokenizeStateError: | ||
| 1433 | break; | ||
| 1434 | case TokenizeStateNumberNoUnderscore: | ||
| 1435 | case TokenizeStateFloatFractionNoUnderscore: | ||
| 1436 | case TokenizeStateFloatExponentNumberNoUnderscore: | ||
| 1437 | case TokenizeStateNumberDot: | ||
| 1438 | tokenize_error(&t, "unterminated number literal"); | ||
| 1439 | break; | ||
| 1440 | case TokenizeStateString: | ||
| 1441 | tokenize_error(&t, "unterminated string"); | ||
| 1442 | break; | ||
| 1443 | case TokenizeStateStringEscape: | ||
| 1444 | case TokenizeStateStringEscapeUnicodeStart: | ||
| 1445 | case TokenizeStateCharCode: | ||
| 1446 | if (t.cur_tok->id == TokenIdStringLiteral) { | ||
| 1447 | tokenize_error(&t, "unterminated string"); | ||
| 1448 | break; | ||
| 1449 | } else if (t.cur_tok->id == TokenIdCharLiteral) { | ||
| 1450 | tokenize_error(&t, "unterminated Unicode code point literal"); | ||
| 1451 | break; | ||
| 1452 | } else { | ||
| 1453 | zig_unreachable(); | ||
| 1454 | } | ||
| 1455 | break; | ||
| 1456 | case TokenizeStateCharLiteral: | ||
| 1457 | case TokenizeStateCharLiteralEnd: | ||
| 1458 | case TokenizeStateCharLiteralUnicode: | ||
| 1459 | tokenize_error(&t, "unterminated Unicode code point literal"); | ||
| 1460 | break; | ||
| 1461 | case TokenizeStateSymbol: | ||
| 1462 | case TokenizeStateZero: | ||
| 1463 | case TokenizeStateNumber: | ||
| 1464 | case TokenizeStateFloatFraction: | ||
| 1465 | case TokenizeStateFloatExponentUnsigned: | ||
| 1466 | case TokenizeStateFloatExponentNumber: | ||
| 1467 | case TokenizeStateSawStar: | ||
| 1468 | case TokenizeStateSawSlash: | ||
| 1469 | case TokenizeStateSawPercent: | ||
| 1470 | case TokenizeStateSawPlus: | ||
| 1471 | case TokenizeStateSawDash: | ||
| 1472 | case TokenizeStateSawAmpersand: | ||
| 1473 | case TokenizeStateSawCaret: | ||
| 1474 | case TokenizeStateSawBar: | ||
| 1475 | case TokenizeStateSawEq: | ||
| 1476 | case TokenizeStateSawBang: | ||
| 1477 | case TokenizeStateSawLessThan: | ||
| 1478 | case TokenizeStateSawLessThanLessThan: | ||
| 1479 | case TokenizeStateSawGreaterThan: | ||
| 1480 | case TokenizeStateSawGreaterThanGreaterThan: | ||
| 1481 | case TokenizeStateSawDot: | ||
| 1482 | case TokenizeStateSawDotStar: | ||
| 1483 | case TokenizeStateSawAtSign: | ||
| 1484 | case TokenizeStateSawStarPercent: | ||
| 1485 | case TokenizeStateSawPlusPercent: | ||
| 1486 | case TokenizeStateSawMinusPercent: | ||
| 1487 | case TokenizeStateLineString: | ||
| 1488 | case TokenizeStateLineStringEnd: | ||
| 1489 | case TokenizeStateDocComment: | ||
| 1490 | case TokenizeStateContainerDocComment: | ||
| 1491 | end_token(&t); | ||
| 1492 | break; | ||
| 1493 | case TokenizeStateSawDotDot: | ||
| 1494 | case TokenizeStateSawBackslash: | ||
| 1495 | case TokenizeStateLineStringContinue: | ||
| 1496 | tokenize_error(&t, "unexpected EOF"); | ||
| 1497 | break; | ||
| 1498 | case TokenizeStateLineComment: | ||
| 1499 | break; | ||
| 1500 | case TokenizeStateSawSlash2: | ||
| 1501 | cancel_token(&t); | ||
| 1502 | break; | ||
| 1503 | case TokenizeStateSawSlash3: | ||
| 1504 | set_token_id(&t, t.cur_tok, TokenIdDocComment); | ||
| 1505 | end_token(&t); | ||
| 1506 | break; | ||
| 1507 | case TokenizeStateSawSlashBang: | ||
| 1508 | set_token_id(&t, t.cur_tok, TokenIdContainerDocComment); | ||
| 1509 | end_token(&t); | ||
| 1510 | break; | ||
| 1511 | } | ||
| 1512 | if (t.state != TokenizeStateError) { | ||
| 1513 | if (t.tokens->length > 0) { | ||
| 1514 | Token *last_token = &t.tokens->last(); | ||
| 1515 | t.line = (int)last_token->start_line; | ||
| 1516 | t.column = (int)last_token->start_column; | ||
| 1517 | t.pos = last_token->start_pos; | ||
| 1518 | } else { | ||
| 1519 | t.pos = 0; | ||
| 1520 | } | ||
| 1521 | begin_token(&t, TokenIdEof); | ||
| 1522 | end_token(&t); | ||
| 1523 | assert(!t.cur_tok); | ||
| 1524 | } | ||
| 1525 | } | 1434 | } |
| 1526 | 1435 | ||
| 1527 | const char * token_name(TokenId id) { | 1436 | const char * token_name(TokenId id) { |
| 1528 | switch (id) { | 1437 | switch (id) { |
| 1529 | case TokenIdAmpersand: return "&"; | 1438 | case TokenIdAmpersand: return "&"; |
| 1530 | case TokenIdArrow: return "->"; | 1439 | case TokenIdArrow: return "->"; |
| 1531 | case TokenIdAtSign: return "@"; | ||
| 1532 | case TokenIdBang: return "!"; | 1440 | case TokenIdBang: return "!"; |
| 1533 | case TokenIdBarBar: return "||"; | 1441 | case TokenIdBarBar: return "||"; |
| 1534 | case TokenIdBinOr: return "|"; | 1442 | case TokenIdBinOr: return "|"; |
| ... | @@ -1622,9 +1530,7 @@ const char * token_name(TokenId id) { | ... | @@ -1622,9 +1530,7 @@ const char * token_name(TokenId id) { |
| 1622 | case TokenIdMinusPercent: return "-%"; | 1530 | case TokenIdMinusPercent: return "-%"; |
| 1623 | case TokenIdMinusPercentEq: return "-%="; | 1531 | case TokenIdMinusPercentEq: return "-%="; |
| 1624 | case TokenIdModEq: return "%="; | 1532 | case TokenIdModEq: return "%="; |
| 1625 | case TokenIdNumberSign: return "#"; | ||
| 1626 | case TokenIdPercent: return "%"; | 1533 | case TokenIdPercent: return "%"; |
| 1627 | case TokenIdPercentDot: return "%."; | ||
| 1628 | case TokenIdPlus: return "+"; | 1534 | case TokenIdPlus: return "+"; |
| 1629 | case TokenIdPlusEq: return "+="; | 1535 | case TokenIdPlusEq: return "+="; |
| 1630 | case TokenIdPlusPercent: return "+%"; | 1536 | case TokenIdPlusPercent: return "+%"; |
| ... | @@ -1638,33 +1544,15 @@ const char * token_name(TokenId id) { | ... | @@ -1638,33 +1544,15 @@ const char * token_name(TokenId id) { |
| 1638 | case TokenIdStar: return "*"; | 1544 | case TokenIdStar: return "*"; |
| 1639 | case TokenIdStarStar: return "**"; | 1545 | case TokenIdStarStar: return "**"; |
| 1640 | case TokenIdStringLiteral: return "StringLiteral"; | 1546 | case TokenIdStringLiteral: return "StringLiteral"; |
| 1641 | case TokenIdMultilineStringLiteral: return "MultilineStringLiteral"; | 1547 | case TokenIdMultilineStringLiteralLine: return "MultilineStringLiteralLine"; |
| 1642 | case TokenIdSymbol: return "Symbol"; | 1548 | case TokenIdIdentifier: return "Identifier"; |
| 1643 | case TokenIdTilde: return "~"; | 1549 | case TokenIdTilde: return "~"; |
| 1644 | case TokenIdTimesEq: return "*="; | 1550 | case TokenIdTimesEq: return "*="; |
| 1645 | case TokenIdTimesPercent: return "*%"; | 1551 | case TokenIdTimesPercent: return "*%"; |
| 1646 | case TokenIdTimesPercentEq: return "*%="; | 1552 | case TokenIdTimesPercentEq: return "*%="; |
| 1553 | case TokenIdBuiltin: return "Builtin"; | ||
| 1647 | case TokenIdCount: | 1554 | case TokenIdCount: |
| 1648 | zig_unreachable(); | 1555 | zig_unreachable(); |
| 1649 | } | 1556 | } |
| 1650 | return "(invalid token)"; | 1557 | return "(invalid token)"; |
| 1651 | } | 1558 | } |
| 1652 | |||
| 1653 | void print_tokens(Buf *buf, ZigList<Token> *tokens) { | ||
| 1654 | for (size_t i = 0; i < tokens->length; i += 1) { | ||
| 1655 | Token *token = &tokens->at(i); | ||
| 1656 | fprintf(stderr, "%s ", token_name(token->id)); | ||
| 1657 | if (token->start_pos != SIZE_MAX) { | ||
| 1658 | fwrite(buf_ptr(buf) + token->start_pos, 1, token->end_pos - token->start_pos, stderr); | ||
| 1659 | } | ||
| 1660 | fprintf(stderr, "\n"); | ||
| 1661 | } | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | bool valid_symbol_starter(uint8_t c) { | ||
| 1665 | switch (c) { | ||
| 1666 | case SYMBOL_START: | ||
| 1667 | return true; | ||
| 1668 | } | ||
| 1669 | return false; | ||
| 1670 | } |
src/stage1/tokenizer.hpp+14-56| ... | @@ -12,10 +12,9 @@ | ... | @@ -12,10 +12,9 @@ |
| 12 | #include "bigint.hpp" | 12 | #include "bigint.hpp" |
| 13 | #include "bigfloat.hpp" | 13 | #include "bigfloat.hpp" |
| 14 | 14 | ||
| 15 | enum TokenId { | 15 | enum TokenId : uint8_t { |
| 16 | TokenIdAmpersand, | 16 | TokenIdAmpersand, |
| 17 | TokenIdArrow, | 17 | TokenIdArrow, |
| 18 | TokenIdAtSign, | ||
| 19 | TokenIdBang, | 18 | TokenIdBang, |
| 20 | TokenIdBarBar, | 19 | TokenIdBarBar, |
| 21 | TokenIdBinOr, | 20 | TokenIdBinOr, |
| ... | @@ -27,6 +26,7 @@ enum TokenId { | ... | @@ -27,6 +26,7 @@ enum TokenId { |
| 27 | TokenIdBitShiftRight, | 26 | TokenIdBitShiftRight, |
| 28 | TokenIdBitShiftRightEq, | 27 | TokenIdBitShiftRightEq, |
| 29 | TokenIdBitXorEq, | 28 | TokenIdBitXorEq, |
| 29 | TokenIdBuiltin, | ||
| 30 | TokenIdCharLiteral, | 30 | TokenIdCharLiteral, |
| 31 | TokenIdCmpEq, | 31 | TokenIdCmpEq, |
| 32 | TokenIdCmpGreaterOrEq, | 32 | TokenIdCmpGreaterOrEq, |
| ... | @@ -109,9 +109,7 @@ enum TokenId { | ... | @@ -109,9 +109,7 @@ enum TokenId { |
| 109 | TokenIdMinusPercent, | 109 | TokenIdMinusPercent, |
| 110 | TokenIdMinusPercentEq, | 110 | TokenIdMinusPercentEq, |
| 111 | TokenIdModEq, | 111 | TokenIdModEq, |
| 112 | TokenIdNumberSign, | ||
| 113 | TokenIdPercent, | 112 | TokenIdPercent, |
| 114 | TokenIdPercentDot, | ||
| 115 | TokenIdPlus, | 113 | TokenIdPlus, |
| 116 | TokenIdPlusEq, | 114 | TokenIdPlusEq, |
| 117 | TokenIdPlusPercent, | 115 | TokenIdPlusPercent, |
| ... | @@ -125,75 +123,35 @@ enum TokenId { | ... | @@ -125,75 +123,35 @@ enum TokenId { |
| 125 | TokenIdStar, | 123 | TokenIdStar, |
| 126 | TokenIdStarStar, | 124 | TokenIdStarStar, |
| 127 | TokenIdStringLiteral, | 125 | TokenIdStringLiteral, |
| 128 | TokenIdMultilineStringLiteral, | 126 | TokenIdMultilineStringLiteralLine, |
| 129 | TokenIdSymbol, | 127 | TokenIdIdentifier, |
| 130 | TokenIdTilde, | 128 | TokenIdTilde, |
| 131 | TokenIdTimesEq, | 129 | TokenIdTimesEq, |
| 132 | TokenIdTimesPercent, | 130 | TokenIdTimesPercent, |
| 133 | TokenIdTimesPercentEq, | 131 | TokenIdTimesPercentEq, |
| 134 | TokenIdCount, | ||
| 135 | }; | ||
| 136 | |||
| 137 | struct TokenFloatLit { | ||
| 138 | BigFloat bigfloat; | ||
| 139 | // overflow is true if when parsing the number, we discovered it would not fit | ||
| 140 | // without losing data | ||
| 141 | bool overflow; | ||
| 142 | }; | ||
| 143 | |||
| 144 | struct TokenIntLit { | ||
| 145 | BigInt bigint; | ||
| 146 | }; | ||
| 147 | |||
| 148 | struct TokenStrLit { | ||
| 149 | Buf str; | ||
| 150 | }; | ||
| 151 | 132 | ||
| 152 | struct TokenCharLit { | 133 | TokenIdCount, |
| 153 | uint32_t c; | ||
| 154 | }; | 134 | }; |
| 155 | 135 | ||
| 156 | struct Token { | 136 | typedef uint32_t TokenIndex; |
| 157 | TokenId id; | ||
| 158 | size_t start_pos; | ||
| 159 | size_t end_pos; | ||
| 160 | size_t start_line; | ||
| 161 | size_t start_column; | ||
| 162 | |||
| 163 | union { | ||
| 164 | // TokenIdIntLiteral | ||
| 165 | TokenIntLit int_lit; | ||
| 166 | |||
| 167 | // TokenIdFloatLiteral | ||
| 168 | TokenFloatLit float_lit; | ||
| 169 | 137 | ||
| 170 | // TokenIdStringLiteral, TokenIdMultilineStringLiteral or TokenIdSymbol | 138 | struct TokenLoc { |
| 171 | TokenStrLit str_lit; | 139 | uint32_t offset; |
| 172 | 140 | uint32_t line; | |
| 173 | // TokenIdCharLiteral | 141 | uint32_t column; |
| 174 | TokenCharLit char_lit; | ||
| 175 | } data; | ||
| 176 | }; | 142 | }; |
| 177 | // work around conflicting name Token which is also found in libclang | ||
| 178 | typedef Token ZigToken; | ||
| 179 | 143 | ||
| 180 | struct Tokenization { | 144 | struct Tokenization { |
| 181 | ZigList<Token> *tokens; | 145 | ZigList<TokenId> ids; |
| 182 | ZigList<size_t> *line_offsets; | 146 | ZigList<TokenLoc> locs; |
| 183 | 147 | ||
| 184 | // if an error occurred | 148 | // if an error occurred |
| 185 | Buf *err; | 149 | Buf *err; |
| 186 | size_t err_line; | 150 | uint32_t err_byte_offset; |
| 187 | size_t err_column; | ||
| 188 | }; | 151 | }; |
| 189 | 152 | ||
| 190 | void tokenize(Buf *buf, Tokenization *out_tokenization); | 153 | void tokenize(const char *source, Tokenization *out_tokenization); |
| 191 | |||
| 192 | void print_tokens(Buf *buf, ZigList<Token> *tokens); | ||
| 193 | 154 | ||
| 194 | const char * token_name(TokenId id); | 155 | const char * token_name(TokenId id); |
| 195 | 156 | ||
| 196 | bool valid_symbol_starter(uint8_t c); | ||
| 197 | bool is_zig_keyword(Buf *buf); | ||
| 198 | |||
| 199 | #endif | 157 | #endif |
test/behavior/misc.zig+8-7| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const expect = std.testing.expect; | 2 | const expect = std.testing.expect; |
| 3 | const expectEqualSlices = std.testing.expectEqualSlices; | 3 | const expectEqualSlices = std.testing.expectEqualSlices; |
| 4 | const expectEqualStrings = std.testing.expectEqualStrings; | ||
| 4 | const mem = std.mem; | 5 | const mem = std.mem; |
| 5 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 6 | 7 | ||
| ... | @@ -147,13 +148,13 @@ test "array mult operator" { | ... | @@ -147,13 +148,13 @@ test "array mult operator" { |
| 147 | } | 148 | } |
| 148 | 149 | ||
| 149 | test "string escapes" { | 150 | test "string escapes" { |
| 150 | try expect(mem.eql(u8, "\"", "\x22")); | 151 | try expectEqualStrings("\"", "\x22"); |
| 151 | try expect(mem.eql(u8, "\'", "\x27")); | 152 | try expectEqualStrings("\'", "\x27"); |
| 152 | try expect(mem.eql(u8, "\n", "\x0a")); | 153 | try expectEqualStrings("\n", "\x0a"); |
| 153 | try expect(mem.eql(u8, "\r", "\x0d")); | 154 | try expectEqualStrings("\r", "\x0d"); |
| 154 | try expect(mem.eql(u8, "\t", "\x09")); | 155 | try expectEqualStrings("\t", "\x09"); |
| 155 | try expect(mem.eql(u8, "\\", "\x5c")); | 156 | try expectEqualStrings("\\", "\x5c"); |
| 156 | try expect(mem.eql(u8, "\u{1234}\u{069}\u{1}", "\xe1\x88\xb4\x69\x01")); | 157 | try expectEqualStrings("\u{1234}\u{069}\u{1}", "\xe1\x88\xb4\x69\x01"); |
| 157 | } | 158 | } |
| 158 | 159 | ||
| 159 | test "multiline string" { | 160 | test "multiline string" { |
test/compile_errors.zig+4-4| ... | @@ -34,9 +34,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -34,9 +34,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 34 | \\ const c: *S = &.{}; | 34 | \\ const c: *S = &.{}; |
| 35 | \\} | 35 | \\} |
| 36 | , &[_][]const u8{ | 36 | , &[_][]const u8{ |
| 37 | "mp.zig:2:31: error: expected type '[][]const u8', found '*const struct:2:31'", | 37 | "tmp.zig:2:31: error: expected type '[][]const u8', found '*const struct:2:31'", |
| 38 | "mp.zig:5:33: error: expected type '*[2][]const u8', found '*const struct:5:33'", | 38 | "tmp.zig:5:33: error: expected type '*[2][]const u8', found '*const struct:5:33'", |
| 39 | "mp.zig:9:21: error: expected type '*S', found '*const struct:9:21'", | 39 | "tmp.zig:9:21: error: expected type '*S', found '*const struct:9:21'", |
| 40 | }); | 40 | }); |
| 41 | 41 | ||
| 42 | cases.add("@Type() union payload is undefined", | 42 | cases.add("@Type() union payload is undefined", |
| ... | @@ -8416,6 +8416,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -8416,6 +8416,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 8416 | \\ var sequence = "repeat".*** 10; | 8416 | \\ var sequence = "repeat".*** 10; |
| 8417 | \\} | 8417 | \\} |
| 8418 | , &[_][]const u8{ | 8418 | , &[_][]const u8{ |
| 8419 | "tmp.zig:2:30: error: `.*` can't be followed by `*`. Are you missing a space?", | 8419 | "tmp.zig:2:30: error: `.*` cannot be followed by `*`. Are you missing a space?", |
| 8420 | }); | 8420 | }); |
| 8421 | } | 8421 | } |