| ... | @@ -59,6 +59,8 @@ pub const ResultLoc = union(enum) { | ... | @@ -59,6 +59,8 @@ pub const ResultLoc = union(enum) { |
| 59 | | 59 | |
| 60 | pub fn typeExpr(mod: *Module, scope: *Scope, type_node: ast.Node.Index) InnerError!*zir.Inst { | 60 | pub fn typeExpr(mod: *Module, scope: *Scope, type_node: ast.Node.Index) InnerError!*zir.Inst { |
| 61 | const tree = scope.tree(); | 61 | const tree = scope.tree(); |
| | 62 | const token_starts = tree.tokens.items(.start); |
| | 63 | |
| 62 | const type_src = token_starts[tree.firstToken(type_node)]; | 64 | const type_src = token_starts[tree.firstToken(type_node)]; |
| 63 | const type_type = try addZIRInstConst(mod, scope, type_src, .{ | 65 | const type_type = try addZIRInstConst(mod, scope, type_src, .{ |
| 64 | .ty = Type.initTag(.type), | 66 | .ty = Type.initTag(.type), |
| ... | @@ -76,13 +78,17 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.I | ... | @@ -76,13 +78,17 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.I |
| 76 | .root => unreachable, | 78 | .root => unreachable, |
| 77 | .@"usingnamespace" => unreachable, | 79 | .@"usingnamespace" => unreachable, |
| 78 | .test_decl => unreachable, | 80 | .test_decl => unreachable, |
| 79 | .doc_comment => unreachable, | 81 | .global_var_decl => unreachable, |
| 80 | .var_decl => unreachable, | 82 | .local_var_decl => unreachable, |
| | 83 | .simple_var_decl => unreachable, |
| | 84 | .aligned_var_decl => unreachable, |
| 81 | .switch_case => unreachable, | 85 | .switch_case => unreachable, |
| 82 | .switch_else => unreachable, | 86 | .switch_case_one => unreachable, |
| 83 | .container_field_init => unreachable, | 87 | .container_field_init => unreachable, |
| 84 | .container_field_align => unreachable, | 88 | .container_field_align => unreachable, |
| 85 | .container_field => unreachable, | 89 | .container_field => unreachable, |
| | 90 | .asm_output => unreachable, |
| | 91 | .asm_input => unreachable, |
| 86 | | 92 | |
| 87 | .assign, | 93 | .assign, |
| 88 | .assign_bit_and, | 94 | .assign_bit_and, |
| ... | @@ -122,58 +128,107 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.I | ... | @@ -122,58 +128,107 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.I |
| 122 | .bool_and, | 128 | .bool_and, |
| 123 | .bool_or, | 129 | .bool_or, |
| 124 | .@"asm", | 130 | .@"asm", |
| | 131 | .asm_simple, |
| 125 | .string_literal, | 132 | .string_literal, |
| 126 | .integer_literal, | 133 | .integer_literal, |
| 127 | .call, | 134 | .call, |
| 128 | .@"unreachable", | 135 | .call_comma, |
| | 136 | .async_call, |
| | 137 | .async_call_comma, |
| | 138 | .call_one, |
| | 139 | .call_one_comma, |
| | 140 | .async_call_one, |
| | 141 | .async_call_one_comma, |
| | 142 | .unreachable_literal, |
| 129 | .@"return", | 143 | .@"return", |
| 130 | .@"if", | 144 | .@"if", |
| | 145 | .if_simple, |
| 131 | .@"while", | 146 | .@"while", |
| | 147 | .while_simple, |
| | 148 | .while_cont, |
| 132 | .bool_not, | 149 | .bool_not, |
| 133 | .address_of, | 150 | .address_of, |
| 134 | .float_literal, | 151 | .float_literal, |
| 135 | .undefined_literal, | 152 | .undefined_literal, |
| 136 | .bool_literal, | 153 | .true_literal, |
| | 154 | .false_literal, |
| 137 | .null_literal, | 155 | .null_literal, |
| 138 | .optional_type, | 156 | .optional_type, |
| 139 | .block, | 157 | .block, |
| 140 | .labeled_block, | 158 | .block_semicolon, |
| | 159 | .block_two, |
| | 160 | .block_two_semicolon, |
| 141 | .@"break", | 161 | .@"break", |
| 142 | .PtrType, | 162 | .ptr_type_aligned, |
| | 163 | .ptr_type_sentinel, |
| | 164 | .ptr_type, |
| | 165 | .ptr_type_bit_range, |
| 143 | .array_type, | 166 | .array_type, |
| 144 | .array_type_sentinel, | 167 | .array_type_sentinel, |
| 145 | .enum_literal, | 168 | .enum_literal, |
| 146 | .MultilineStringLiteral, | 169 | .multiline_string_literal, |
| 147 | .char_literal, | 170 | .char_literal, |
| 148 | .@"defer", | 171 | .@"defer", |
| | 172 | .@"errdefer", |
| 149 | .@"catch", | 173 | .@"catch", |
| 150 | .error_union, | 174 | .error_union, |
| 151 | .merge_error_sets, | 175 | .merge_error_sets, |
| 152 | .range, | 176 | .switch_range, |
| 153 | .@"await", | 177 | .@"await", |
| 154 | .bit_not, | 178 | .bit_not, |
| 155 | .negation, | 179 | .negation, |
| 156 | .negation_wrap, | 180 | .negation_wrap, |
| 157 | .@"resume", | 181 | .@"resume", |
| 158 | .@"try", | 182 | .@"try", |
| 159 | .slice_type, | | |
| 160 | .slice, | 183 | .slice, |
| 161 | .ArrayInitializer, | 184 | .slice_open, |
| 162 | .ArrayInitializerDot, | 185 | .slice_sentinel, |
| 163 | .StructInitializer, | 186 | .array_init_one, |
| 164 | .StructInitializerDot, | 187 | .array_init_one_comma, |
| | 188 | .array_init_dot_two, |
| | 189 | .array_init_dot_two_comma, |
| | 190 | .array_init_dot, |
| | 191 | .array_init_dot_comma, |
| | 192 | .array_init, |
| | 193 | .array_init_comma, |
| | 194 | .struct_init_one, |
| | 195 | .struct_init_one_comma, |
| | 196 | .struct_init_dot_two, |
| | 197 | .struct_init_dot_two_comma, |
| | 198 | .struct_init_dot, |
| | 199 | .struct_init_dot_comma, |
| | 200 | .struct_init, |
| | 201 | .struct_init_comma, |
| 165 | .@"switch", | 202 | .@"switch", |
| | 203 | .switch_comma, |
| 166 | .@"for", | 204 | .@"for", |
| | 205 | .for_simple, |
| 167 | .@"suspend", | 206 | .@"suspend", |
| 168 | .@"continue", | 207 | .@"continue", |
| 169 | .@"anytype", | 208 | .@"anytype", |
| 170 | .error_type, | 209 | .fn_proto_simple, |
| 171 | .FnProto, | 210 | .fn_proto_multi, |
| | 211 | .fn_proto_one, |
| | 212 | .fn_proto, |
| | 213 | .fn_decl, |
| 172 | .anyframe_type, | 214 | .anyframe_type, |
| | 215 | .anyframe_literal, |
| 173 | .error_set_decl, | 216 | .error_set_decl, |
| 174 | .ContainerDecl, | 217 | .container_decl, |
| | 218 | .container_decl_comma, |
| | 219 | .container_decl_two, |
| | 220 | .container_decl_two_comma, |
| | 221 | .container_decl_arg, |
| | 222 | .container_decl_arg_comma, |
| | 223 | .tagged_union, |
| | 224 | .tagged_union_comma, |
| | 225 | .tagged_union_two, |
| | 226 | .tagged_union_two_comma, |
| | 227 | .tagged_union_enum_tag, |
| | 228 | .tagged_union_enum_tag_comma, |
| 175 | .@"comptime", | 229 | .@"comptime", |
| 176 | .@"nosuspend", | 230 | .@"nosuspend", |
| | 231 | .error_value, |
| 177 | => return mod.failNode(scope, node, "invalid left-hand side to assignment", .{}), | 232 | => return mod.failNode(scope, node, "invalid left-hand side to assignment", .{}), |
| 178 | | 233 | |
| 179 | .builtin_call, | 234 | .builtin_call, |
| ... | @@ -192,10 +247,10 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.I | ... | @@ -192,10 +247,10 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.I |
| 192 | } | 247 | } |
| 193 | }, | 248 | }, |
| 194 | | 249 | |
| 195 | // can be assigned to | 250 | // These can be assigned to. |
| 196 | .unwrap_optional, | 251 | .unwrap_optional, |
| 197 | .deref, | 252 | .deref, |
| 198 | .period, | 253 | .field_access, |
| 199 | .array_access, | 254 | .array_access, |
| 200 | .identifier, | 255 | .identifier, |
| 201 | .grouped_expression, | 256 | .grouped_expression, |
| ... | @@ -210,22 +265,33 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.I | ... | @@ -210,22 +265,33 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.I |
| 210 | /// result instruction can be used to inspect whether it is isNoReturn() but that is it, | 265 | /// result instruction can be used to inspect whether it is isNoReturn() but that is it, |
| 211 | /// it must otherwise not be used. | 266 | /// it must otherwise not be used. |
| 212 | pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!*zir.Inst { | 267 | pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!*zir.Inst { |
| 213 | switch (node.tag) { | 268 | const tree = scope.tree(); |
| | 269 | const main_tokens = tree.nodes.items(.main_token); |
| | 270 | const token_tags = tree.tokens.items(.tag); |
| | 271 | const node_datas = tree.nodes.items(.data); |
| | 272 | const node_tags = tree.nodes.items(.tag); |
| | 273 | const token_starts = tree.tokens.items(.start); |
| | 274 | |
| | 275 | switch (node_tags[node]) { |
| 214 | .root => unreachable, // Top-level declaration. | 276 | .root => unreachable, // Top-level declaration. |
| 215 | .@"usingnamespace" => unreachable, // Top-level declaration. | 277 | .@"usingnamespace" => unreachable, // Top-level declaration. |
| 216 | .test_decl => unreachable, // Top-level declaration. | 278 | .test_decl => unreachable, // Top-level declaration. |
| 217 | .doc_comment => unreachable, // Top-level declaration. | 279 | .container_field_init => unreachable, // Top-level declaration. |
| 218 | .var_decl => unreachable, // Handled in `blockExpr`. | 280 | .container_field_align => unreachable, // Top-level declaration. |
| | 281 | .container_field => unreachable, // Top-level declaration. |
| | 282 | .fn_decl => unreachable, // Top-level declaration. |
| | 283 | |
| | 284 | .global_var_decl => unreachable, // Handled in `blockExpr`. |
| | 285 | .local_var_decl => unreachable, // Handled in `blockExpr`. |
| | 286 | .simple_var_decl => unreachable, // Handled in `blockExpr`. |
| | 287 | .aligned_var_decl => unreachable, // Handled in `blockExpr`. |
| | 288 | |
| 219 | .switch_case => unreachable, // Handled in `switchExpr`. | 289 | .switch_case => unreachable, // Handled in `switchExpr`. |
| 220 | .switch_else => unreachable, // Handled in `switchExpr`. | 290 | .switch_case_one => unreachable, // Handled in `switchExpr`. |
| 221 | .range => unreachable, // Handled in `switchExpr`. | 291 | .switch_range => unreachable, // Handled in `switchExpr`. |
| 222 | .Else => unreachable, // Handled explicitly the control flow expression functions. | 292 | |
| 223 | .Payload => unreachable, // Handled explicitly. | 293 | .asm_output => unreachable, // Handled in `asmExpr`. |
| 224 | .PointerPayload => unreachable, // Handled explicitly. | 294 | .asm_input => unreachable, // Handled in `asmExpr`. |
| 225 | .PointerIndexPayload => unreachable, // Handled explicitly. | | |
| 226 | .ErrorTag => unreachable, // Handled explicitly. | | |
| 227 | .FieldInitializer => unreachable, // Handled explicitly. | | |
| 228 | .ContainerField => unreachable, // Handled explicitly. | | |
| 229 | | 295 | |
| 230 | .assign => return rvalueVoid(mod, scope, rl, node, try assign(mod, scope, node)), | 296 | .assign => return rvalueVoid(mod, scope, rl, node, try assign(mod, scope, node)), |
| 231 | .assign_bit_and => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .bit_and)), | 297 | .assign_bit_and => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .bit_and)), |
| ... | @@ -276,30 +342,28 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In | ... | @@ -276,30 +342,28 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 276 | | 342 | |
| 277 | .identifier => return identifier(mod, scope, rl, node), | 343 | .identifier => return identifier(mod, scope, rl, node), |
| 278 | | 344 | |
| 279 | .asm_simple => return assembly(mod, scope, rl, tree.asmSimple(node)), | 345 | .asm_simple => return asmExpr(mod, scope, rl, tree.asmSimple(node)), |
| 280 | .@"asm" => return assembly(mod, scope, rl, tree.asmFull(node)), | 346 | .@"asm" => return asmExpr(mod, scope, rl, tree.asmFull(node)), |
| 281 | | 347 | |
| 282 | .string_literal => return stringLiteral(mod, scope, rl, node), | 348 | .string_literal => return stringLiteral(mod, scope, rl, node), |
| 283 | .multiline_string_literal => return multilineStringLiteral(mod, scope, rl, node), | 349 | .multiline_string_literal => return multilineStringLiteral(mod, scope, rl, node), |
| 284 | | 350 | |
| 285 | .integer_literal => return integerLiteral(mod, scope, rl, node), | 351 | .integer_literal => return integerLiteral(mod, scope, rl, node), |
| 286 | | 352 | |
| 287 | .builtin_call => return builtinCall(mod, scope, rl, node), | | |
| 288 | | | |
| 289 | .builtin_call_two, .builtin_call_two_comma => { | 353 | .builtin_call_two, .builtin_call_two_comma => { |
| 290 | if (datas[node].lhs == 0) { | 354 | if (node_datas[node].lhs == 0) { |
| 291 | const params = [_]ast.Node.Index{}; | 355 | const params = [_]ast.Node.Index{}; |
| 292 | return builtinCall(mod, scope, rl, node, &params); | 356 | return builtinCall(mod, scope, rl, node, &params); |
| 293 | } else if (datas[node].rhs == 0) { | 357 | } else if (node_datas[node].rhs == 0) { |
| 294 | const params = [_]ast.Node.Index{datas[node].lhs}; | 358 | const params = [_]ast.Node.Index{node_datas[node].lhs}; |
| 295 | return builtinCall(mod, scope, rl, node, &params); | 359 | return builtinCall(mod, scope, rl, node, &params); |
| 296 | } else { | 360 | } else { |
| 297 | const params = [_]ast.Node.Index{ datas[node].lhs, datas[node].rhs }; | 361 | const params = [_]ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs }; |
| 298 | return builtinCall(mod, scope, rl, node, &params); | 362 | return builtinCall(mod, scope, rl, node, &params); |
| 299 | } | 363 | } |
| 300 | }, | 364 | }, |
| 301 | .builtin_call, .builtin_call_comma => { | 365 | .builtin_call, .builtin_call_comma => { |
| 302 | const params = tree.extra_data[datas[node].lhs..datas[node].rhs]; | 366 | const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs]; |
| 303 | return builtinCall(mod, scope, rl, node, params); | 367 | return builtinCall(mod, scope, rl, node, params); |
| 304 | }, | 368 | }, |
| 305 | | 369 | |
| ... | @@ -311,20 +375,20 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In | ... | @@ -311,20 +375,20 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 311 | return callExpr(mod, scope, rl, tree.callFull(node)); | 375 | return callExpr(mod, scope, rl, tree.callFull(node)); |
| 312 | }, | 376 | }, |
| 313 | | 377 | |
| 314 | .@"unreachable" => { | 378 | .unreachable_literal => { |
| 315 | const main_token = main_tokens[node]; | 379 | const main_token = main_tokens[node]; |
| 316 | const src = token_starts[main_token]; | 380 | const src = token_starts[main_token]; |
| 317 | return addZIRNoOp(mod, scope, src, .unreachable_safe); | 381 | return addZIRNoOp(mod, scope, src, .unreachable_safe); |
| 318 | }, | 382 | }, |
| 319 | .@"return" => return ret(mod, scope, node), | 383 | .@"return" => return ret(mod, scope, node), |
| 320 | .period => return field(mod, scope, rl, node), | 384 | .field_access => return field(mod, scope, rl, node), |
| 321 | .float_literal => return floatLiteral(mod, scope, rl, node), | 385 | .float_literal => return floatLiteral(mod, scope, rl, node), |
| 322 | | 386 | |
| 323 | .if_simple => return ifExpr(mod, scope, rl, tree.ifSimple(node)), | 387 | .if_simple => return ifExpr(mod, scope, rl, tree.ifSimple(node)), |
| 324 | .@"if" => return ifExpr(mode, scope, rl, tree.ifFull(node)), | 388 | .@"if" => return ifExpr(mod, scope, rl, tree.ifFull(node)), |
| 325 | | 389 | |
| 326 | .while_simple => return whileExpr(mod, scope, rl, tree.whileSimple(node)), | 390 | .while_simple => return whileExpr(mod, scope, rl, tree.whileSimple(node)), |
| 327 | .while_cont => return whileExpr(mod, scope, tree.whileCont(node)), | 391 | .while_cont => return whileExpr(mod, scope, rl, tree.whileCont(node)), |
| 328 | .@"while" => return whileExpr(mod, scope, rl, tree.whileFull(node)), | 392 | .@"while" => return whileExpr(mod, scope, rl, tree.whileFull(node)), |
| 329 | | 393 | |
| 330 | .for_simple => return forExpr(mod, scope, rl, tree.forSimple(node)), | 394 | .for_simple => return forExpr(mod, scope, rl, tree.forSimple(node)), |
| ... | @@ -389,7 +453,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In | ... | @@ -389,7 +453,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 389 | return rvalue(mod, scope, rl, result); | 453 | return rvalue(mod, scope, rl, result); |
| 390 | }, | 454 | }, |
| 391 | .unwrap_optional => { | 455 | .unwrap_optional => { |
| 392 | const operand = try expr(mod, scope, rl, node.lhs); | 456 | const operand = try expr(mod, scope, rl, node_datas[node].lhs); |
| 393 | const op: zir.Inst.Tag = switch (rl) { | 457 | const op: zir.Inst.Tag = switch (rl) { |
| 394 | .ref => .optional_payload_safe_ptr, | 458 | .ref => .optional_payload_safe_ptr, |
| 395 | else => .optional_payload_safe, | 459 | else => .optional_payload_safe, |
| ... | @@ -449,7 +513,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In | ... | @@ -449,7 +513,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 449 | }, | 513 | }, |
| 450 | .@"catch" => { | 514 | .@"catch" => { |
| 451 | const catch_token = main_tokens[node]; | 515 | const catch_token = main_tokens[node]; |
| 452 | const payload_token: ?TokenIndex = if (token_tags[catch_token + 1] == .pipe) | 516 | const payload_token: ?ast.TokenIndex = if (token_tags[catch_token + 1] == .pipe) |
| 453 | catch_token + 2 | 517 | catch_token + 2 |
| 454 | else | 518 | else |
| 455 | null; | 519 | null; |
| ... | @@ -506,6 +570,34 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In | ... | @@ -506,6 +570,34 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 506 | null, | 570 | null, |
| 507 | ), | 571 | ), |
| 508 | }, | 572 | }, |
| | 573 | |
| | 574 | .ptr_type_aligned => return ptrType(mod, scope, rl, tree.ptrTypeAligned(node)), |
| | 575 | .ptr_type_sentinel => return ptrType(mod, scope, rl, tree.ptrTypeSentinel(node)), |
| | 576 | .ptr_type => return ptrType(mod, scope, rl, tree.ptrType(node)), |
| | 577 | .ptr_type_bit_range => return ptrType(mod, scope, rl, tree.ptrTypeBitRange(node)), |
| | 578 | |
| | 579 | .container_decl, |
| | 580 | .container_decl_comma, |
| | 581 | => return containerDecl(mod, scope, rl, tree.containerDecl(node)), |
| | 582 | .container_decl_two, .container_decl_two_comma => { |
| | 583 | var buffer: [2]ast.Node.Index = undefined; |
| | 584 | return containerDecl(mod, scope, rl, tree.containerDeclTwo(&buffer, node)); |
| | 585 | }, |
| | 586 | .container_decl_arg, |
| | 587 | .container_decl_arg_comma, |
| | 588 | => return containerDecl(mod, scope, rl, tree.containerDeclArg(node)), |
| | 589 | |
| | 590 | .tagged_union, |
| | 591 | .tagged_union_comma, |
| | 592 | => return containerDecl(mod, scope, rl, tree.taggedUnion(node)), |
| | 593 | .tagged_union_two, .tagged_union_two_comma => { |
| | 594 | var buffer: [2]ast.Node.Index = undefined; |
| | 595 | return containerDecl(mod, scope, rl, tree.taggedUnionTwo(&buffer, node)); |
| | 596 | }, |
| | 597 | .tagged_union_enum_tag, |
| | 598 | .tagged_union_enum_tag_comma, |
| | 599 | => return containerDecl(mod, scope, rl, tree.taggedUnionEnumTag(node)), |
| | 600 | |
| 509 | .@"break" => return breakExpr(mod, scope, rl, node), | 601 | .@"break" => return breakExpr(mod, scope, rl, node), |
| 510 | .@"continue" => return continueExpr(mod, scope, rl, node), | 602 | .@"continue" => return continueExpr(mod, scope, rl, node), |
| 511 | .grouped_expression => return expr(mod, scope, rl, node_datas[node].lhs), | 603 | .grouped_expression => return expr(mod, scope, rl, node_datas[node].lhs), |
| ... | @@ -518,12 +610,41 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In | ... | @@ -518,12 +610,41 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 518 | .@"switch", .switch_comma => return switchExpr(mod, scope, rl, node), | 610 | .@"switch", .switch_comma => return switchExpr(mod, scope, rl, node), |
| 519 | | 611 | |
| 520 | .@"defer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .defer", .{}), | 612 | .@"defer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .defer", .{}), |
| | 613 | .@"errdefer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .errdefer", .{}), |
| 521 | .@"await" => return mod.failNode(scope, node, "TODO implement astgen.expr for .await", .{}), | 614 | .@"await" => return mod.failNode(scope, node, "TODO implement astgen.expr for .await", .{}), |
| 522 | .@"resume" => return mod.failNode(scope, node, "TODO implement astgen.expr for .resume", .{}), | 615 | .@"resume" => return mod.failNode(scope, node, "TODO implement astgen.expr for .resume", .{}), |
| 523 | .@"try" => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}), | 616 | .@"try" => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}), |
| | 617 | |
| | 618 | .array_init_one, |
| | 619 | .array_init_one_comma, |
| | 620 | .array_init_dot_two, |
| | 621 | .array_init_dot_two_comma, |
| | 622 | .array_init_dot, |
| | 623 | .array_init_dot_comma, |
| | 624 | .array_init, |
| | 625 | .array_init_comma, |
| | 626 | => return mod.failNode(scope, node, "TODO implement astgen.expr for array literals", .{}), |
| | 627 | |
| | 628 | .struct_init_one, |
| | 629 | .struct_init_one_comma, |
| | 630 | .struct_init_dot_two, |
| | 631 | .struct_init_dot_two_comma, |
| | 632 | .struct_init_dot, |
| | 633 | .struct_init_dot_comma, |
| | 634 | .struct_init, |
| | 635 | .struct_init_comma, |
| | 636 | => return mod.failNode(scope, node, "TODO implement astgen.expr for struct literals", .{}), |
| | 637 | |
| 524 | .@"suspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .suspend", .{}), | 638 | .@"suspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .suspend", .{}), |
| 525 | .@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}), | 639 | .@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}), |
| | 640 | .fn_proto_simple, |
| | 641 | .fn_proto_multi, |
| | 642 | .fn_proto_one, |
| | 643 | .fn_proto, |
| | 644 | => return mod.failNode(scope, node, "TODO implement astgen.expr for function prototypes", .{}), |
| | 645 | |
| 526 | .@"nosuspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .nosuspend", .{}), | 646 | .@"nosuspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .nosuspend", .{}), |
| | 647 | .error_value => return mod.failNode(scope, node, "TODO implement astgen.expr for .error_value", .{}), |
| 527 | } | 648 | } |
| 528 | } | 649 | } |
| 529 | | 650 | |
| ... | @@ -572,6 +693,8 @@ fn breakExpr( | ... | @@ -572,6 +693,8 @@ fn breakExpr( |
| 572 | const tree = parent_scope.tree(); | 693 | const tree = parent_scope.tree(); |
| 573 | const node_datas = tree.nodes.items(.data); | 694 | const node_datas = tree.nodes.items(.data); |
| 574 | const main_tokens = tree.nodes.items(.main_token); | 695 | const main_tokens = tree.nodes.items(.main_token); |
| | 696 | const token_starts = tree.tokens.items(.start); |
| | 697 | |
| 575 | const src = token_starts[main_tokens[node]]; | 698 | const src = token_starts[main_tokens[node]]; |
| 576 | const break_label = node_datas[node].lhs; | 699 | const break_label = node_datas[node].lhs; |
| 577 | const rhs = node_datas[node].rhs; | 700 | const rhs = node_datas[node].rhs; |
| ... | @@ -646,6 +769,8 @@ fn continueExpr( | ... | @@ -646,6 +769,8 @@ fn continueExpr( |
| 646 | const tree = parent_scope.tree(); | 769 | const tree = parent_scope.tree(); |
| 647 | const node_datas = tree.nodes.items(.data); | 770 | const node_datas = tree.nodes.items(.data); |
| 648 | const main_tokens = tree.nodes.items(.main_token); | 771 | const main_tokens = tree.nodes.items(.main_token); |
| | 772 | const token_starts = tree.tokens.items(.start); |
| | 773 | |
| 649 | const src = token_starts[main_tokens[node]]; | 774 | const src = token_starts[main_tokens[node]]; |
| 650 | const break_label = node_datas[node].lhs; | 775 | const break_label = node_datas[node].lhs; |
| 651 | | 776 | |
| ... | @@ -702,7 +827,7 @@ pub fn blockExpr( | ... | @@ -702,7 +827,7 @@ pub fn blockExpr( |
| 702 | const main_tokens = tree.nodes.items(.main_token); | 827 | const main_tokens = tree.nodes.items(.main_token); |
| 703 | const token_tags = tree.tokens.items(.tag); | 828 | const token_tags = tree.tokens.items(.tag); |
| 704 | | 829 | |
| 705 | const lbrace = main_tokens[node]; | 830 | const lbrace = main_tokens[block_node]; |
| 706 | if (token_tags[lbrace - 1] == .colon) { | 831 | if (token_tags[lbrace - 1] == .colon) { |
| 707 | return labeledBlockExpr(mod, scope, rl, block_node, statements, .block); | 832 | return labeledBlockExpr(mod, scope, rl, block_node, statements, .block); |
| 708 | } | 833 | } |
| ... | @@ -721,8 +846,9 @@ fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIn | ... | @@ -721,8 +846,9 @@ fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIn |
| 721 | if (gen_zir.label) |prev_label| { | 846 | if (gen_zir.label) |prev_label| { |
| 722 | if (try tokenIdentEql(mod, parent_scope, label, prev_label.token)) { | 847 | if (try tokenIdentEql(mod, parent_scope, label, prev_label.token)) { |
| 723 | const tree = parent_scope.tree(); | 848 | const tree = parent_scope.tree(); |
| 724 | const node_datas = tree.nodes.items(.data); | | |
| 725 | const main_tokens = tree.nodes.items(.main_token); | 849 | const main_tokens = tree.nodes.items(.main_token); |
| | 850 | const token_starts = tree.tokens.items(.start); |
| | 851 | |
| 726 | const label_src = token_starts[label]; | 852 | const label_src = token_starts[label]; |
| 727 | const prev_label_src = token_starts[prev_label.token]; | 853 | const prev_label_src = token_starts[prev_label.token]; |
| 728 | | 854 | |
| ... | @@ -770,9 +896,9 @@ fn labeledBlockExpr( | ... | @@ -770,9 +896,9 @@ fn labeledBlockExpr( |
| 770 | assert(zir_tag == .block or zir_tag == .block_comptime); | 896 | assert(zir_tag == .block or zir_tag == .block_comptime); |
| 771 | | 897 | |
| 772 | const tree = parent_scope.tree(); | 898 | const tree = parent_scope.tree(); |
| 773 | const node_datas = tree.nodes.items(.data); | | |
| 774 | const main_tokens = tree.nodes.items(.main_token); | 899 | const main_tokens = tree.nodes.items(.main_token); |
| 775 | const token_starts = tree.tokens.items(.start); | 900 | const token_starts = tree.tokens.items(.start); |
| | 901 | const token_tags = tree.tokens.items(.tag); |
| 776 | | 902 | |
| 777 | const lbrace = main_tokens[block_node]; | 903 | const lbrace = main_tokens[block_node]; |
| 778 | const label_token = lbrace - 1; | 904 | const label_token = lbrace - 1; |
| ... | @@ -813,10 +939,10 @@ fn labeledBlockExpr( | ... | @@ -813,10 +939,10 @@ fn labeledBlockExpr( |
| 813 | defer block_scope.labeled_breaks.deinit(mod.gpa); | 939 | defer block_scope.labeled_breaks.deinit(mod.gpa); |
| 814 | defer block_scope.labeled_store_to_block_ptr_list.deinit(mod.gpa); | 940 | defer block_scope.labeled_store_to_block_ptr_list.deinit(mod.gpa); |
| 815 | | 941 | |
| 816 | try blockExprStmts(mod, &block_scope.base, block_node, block_node.statements()); | 942 | try blockExprStmts(mod, &block_scope.base, block_node, statements); |
| 817 | | 943 | |
| 818 | if (!block_scope.label.?.used) { | 944 | if (!block_scope.label.?.used) { |
| 819 | return mod.fail(parent_scope, token_starts[block_node.label], "unused block label", .{}); | 945 | return mod.failTok(parent_scope, label_token, "unused block label", .{}); |
| 820 | } | 946 | } |
| 821 | | 947 | |
| 822 | try gen_zir.instructions.append(mod.gpa, &block_inst.base); | 948 | try gen_zir.instructions.append(mod.gpa, &block_inst.base); |
| ... | @@ -860,21 +986,23 @@ fn blockExprStmts( | ... | @@ -860,21 +986,23 @@ fn blockExprStmts( |
| 860 | statements: []const ast.Node.Index, | 986 | statements: []const ast.Node.Index, |
| 861 | ) !void { | 987 | ) !void { |
| 862 | const tree = parent_scope.tree(); | 988 | const tree = parent_scope.tree(); |
| 863 | const node_datas = tree.nodes.items(.data); | | |
| 864 | const main_tokens = tree.nodes.items(.main_token); | 989 | const main_tokens = tree.nodes.items(.main_token); |
| | 990 | const token_starts = tree.tokens.items(.start); |
| | 991 | const node_tags = tree.nodes.items(.tag); |
| 865 | | 992 | |
| 866 | var block_arena = std.heap.ArenaAllocator.init(mod.gpa); | 993 | var block_arena = std.heap.ArenaAllocator.init(mod.gpa); |
| 867 | defer block_arena.deinit(); | 994 | defer block_arena.deinit(); |
| 868 | | 995 | |
| 869 | var scope = parent_scope; | 996 | var scope = parent_scope; |
| 870 | for (statements) |statement| { | 997 | for (statements) |statement| { |
| 871 | const src = token_starts[statement.firstToken()]; | 998 | const src = token_starts[tree.firstToken(statement)]; |
| 872 | _ = try addZIRNoOp(mod, scope, src, .dbg_stmt); | 999 | _ = try addZIRNoOp(mod, scope, src, .dbg_stmt); |
| 873 | switch (statement.tag) { | 1000 | switch (node_tags[statement]) { |
| 874 | .var_decl => { | 1001 | .global_var_decl => scope = try varDecl(mod, scope, &block_arena.allocator, tree.globalVarDecl(statement)), |
| 875 | const var_decl_node = statement.castTag(.var_decl).?; | 1002 | .local_var_decl => scope = try varDecl(mod, scope, &block_arena.allocator, tree.localVarDecl(statement)), |
| 876 | scope = try varDecl(mod, scope, var_decl_node, &block_arena.allocator); | 1003 | .simple_var_decl => scope = try varDecl(mod, scope, &block_arena.allocator, tree.simpleVarDecl(statement)), |
| 877 | }, | 1004 | .aligned_var_decl => scope = try varDecl(mod, scope, &block_arena.allocator, tree.alignedVarDecl(statement)), |
| | 1005 | |
| 878 | .assign => try assign(mod, scope, statement), | 1006 | .assign => try assign(mod, scope, statement), |
| 879 | .assign_bit_and => try assignOp(mod, scope, statement, .bit_and), | 1007 | .assign_bit_and => try assignOp(mod, scope, statement, .bit_and), |
| 880 | .assign_bit_or => try assignOp(mod, scope, statement, .bit_or), | 1008 | .assign_bit_or => try assignOp(mod, scope, statement, .bit_or), |
| ... | @@ -903,20 +1031,23 @@ fn blockExprStmts( | ... | @@ -903,20 +1031,23 @@ fn blockExprStmts( |
| 903 | fn varDecl( | 1031 | fn varDecl( |
| 904 | mod: *Module, | 1032 | mod: *Module, |
| 905 | scope: *Scope, | 1033 | scope: *Scope, |
| 906 | node: *ast.Node.var_decl, | | |
| 907 | block_arena: *Allocator, | 1034 | block_arena: *Allocator, |
| | 1035 | var_decl: ast.full.VarDecl, |
| 908 | ) InnerError!*Scope { | 1036 | ) InnerError!*Scope { |
| 909 | if (node.getComptimeToken()) |comptime_token| { | 1037 | if (var_decl.comptime_token) |comptime_token| { |
| 910 | return mod.failTok(scope, comptime_token, "TODO implement comptime locals", .{}); | 1038 | return mod.failTok(scope, comptime_token, "TODO implement comptime locals", .{}); |
| 911 | } | 1039 | } |
| 912 | if (node.getAlignNode()) |align_node| { | 1040 | if (var_decl.ast.align_node != 0) { |
| 913 | return mod.failNode(scope, align_node, "TODO implement alignment on locals", .{}); | 1041 | return mod.failNode(scope, var_decl.ast.align_node, "TODO implement alignment on locals", .{}); |
| 914 | } | 1042 | } |
| 915 | const tree = scope.tree(); | 1043 | const tree = scope.tree(); |
| 916 | const node_datas = tree.nodes.items(.data); | | |
| 917 | const main_tokens = tree.nodes.items(.main_token); | 1044 | const main_tokens = tree.nodes.items(.main_token); |
| 918 | const name_src = token_starts[node.name_token]; | 1045 | const token_starts = tree.tokens.items(.start); |
| 919 | const ident_name = try mod.identifierTokenString(scope, node.name_token); | 1046 | const token_tags = tree.tokens.items(.tag); |
| | 1047 | |
| | 1048 | const name_token = var_decl.ast.mut_token + 1; |
| | 1049 | const name_src = token_starts[name_token]; |
| | 1050 | const ident_name = try mod.identifierTokenString(scope, name_token); |
| 920 | | 1051 | |
| 921 | // Local variables shadowing detection, including function parameters. | 1052 | // Local variables shadowing detection, including function parameters. |
| 922 | { | 1053 | { |
| ... | @@ -962,20 +1093,21 @@ fn varDecl( | ... | @@ -962,20 +1093,21 @@ fn varDecl( |
| 962 | // TODO add note for other definition | 1093 | // TODO add note for other definition |
| 963 | return mod.fail(scope, name_src, "redefinition of '{s}'", .{ident_name}); | 1094 | return mod.fail(scope, name_src, "redefinition of '{s}'", .{ident_name}); |
| 964 | } | 1095 | } |
| 965 | const init_node = node.getInitNode() orelse | 1096 | if (var_decl.ast.init_node == 0) { |
| 966 | return mod.fail(scope, name_src, "variables must be initialized", .{}); | 1097 | return mod.fail(scope, name_src, "variables must be initialized", .{}); |
| | 1098 | } |
| 967 | | 1099 | |
| 968 | switch (tree.token_ids[node.mut_token]) { | 1100 | switch (token_tags[var_decl.ast.mut_token]) { |
| 969 | .keyword_const => { | 1101 | .keyword_const => { |
| 970 | // Depending on the type of AST the initialization expression is, we may need an lvalue | 1102 | // Depending on the type of AST the initialization expression is, we may need an lvalue |
| 971 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as | 1103 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as |
| 972 | // the variable, no memory location needed. | 1104 | // the variable, no memory location needed. |
| 973 | if (!nodeMayNeedMemoryLocation(init_node, scope)) { | 1105 | if (!nodeMayNeedMemoryLocation(scope, var_decl.ast.init_node)) { |
| 974 | const result_loc: ResultLoc = if (node.getTypeNode()) |type_node| | 1106 | const result_loc: ResultLoc = if (var_decl.ast.type_node != 0) |
| 975 | .{ .ty = try typeExpr(mod, scope, type_node) } | 1107 | .{ .ty = try typeExpr(mod, scope, var_decl.ast.type_node) } |
| 976 | else | 1108 | else |
| 977 | .none; | 1109 | .none; |
| 978 | const init_inst = try expr(mod, scope, result_loc, init_node); | 1110 | const init_inst = try expr(mod, scope, result_loc, var_decl.ast.init_node); |
| 979 | const sub_scope = try block_arena.create(Scope.LocalVal); | 1111 | const sub_scope = try block_arena.create(Scope.LocalVal); |
| 980 | sub_scope.* = .{ | 1112 | sub_scope.* = .{ |
| 981 | .parent = scope, | 1113 | .parent = scope, |
| ... | @@ -999,8 +1131,8 @@ fn varDecl( | ... | @@ -999,8 +1131,8 @@ fn varDecl( |
| 999 | | 1131 | |
| 1000 | var resolve_inferred_alloc: ?*zir.Inst = null; | 1132 | var resolve_inferred_alloc: ?*zir.Inst = null; |
| 1001 | var opt_type_inst: ?*zir.Inst = null; | 1133 | var opt_type_inst: ?*zir.Inst = null; |
| 1002 | if (node.getTypeNode()) |type_node| { | 1134 | if (var_decl.ast.type_node != 0) { |
| 1003 | const type_inst = try typeExpr(mod, &init_scope.base, type_node); | 1135 | const type_inst = try typeExpr(mod, &init_scope.base, var_decl.ast.type_node); |
| 1004 | opt_type_inst = type_inst; | 1136 | opt_type_inst = type_inst; |
| 1005 | init_scope.rl_ptr = try addZIRUnOp(mod, &init_scope.base, name_src, .alloc, type_inst); | 1137 | init_scope.rl_ptr = try addZIRUnOp(mod, &init_scope.base, name_src, .alloc, type_inst); |
| 1006 | } else { | 1138 | } else { |
| ... | @@ -1009,7 +1141,7 @@ fn varDecl( | ... | @@ -1009,7 +1141,7 @@ fn varDecl( |
| 1009 | init_scope.rl_ptr = &alloc.base; | 1141 | init_scope.rl_ptr = &alloc.base; |
| 1010 | } | 1142 | } |
| 1011 | const init_result_loc: ResultLoc = .{ .block_ptr = &init_scope }; | 1143 | const init_result_loc: ResultLoc = .{ .block_ptr = &init_scope }; |
| 1012 | const init_inst = try expr(mod, &init_scope.base, init_result_loc, init_node); | 1144 | const init_inst = try expr(mod, &init_scope.base, init_result_loc, var_decl.ast.init_node); |
| 1013 | const parent_zir = &scope.getGenZIR().instructions; | 1145 | const parent_zir = &scope.getGenZIR().instructions; |
| 1014 | if (init_scope.rvalue_rl_count == 1) { | 1146 | if (init_scope.rvalue_rl_count == 1) { |
| 1015 | // Result location pointer not used. We don't need an alloc for this | 1147 | // Result location pointer not used. We don't need an alloc for this |
| ... | @@ -1069,8 +1201,11 @@ fn varDecl( | ... | @@ -1069,8 +1201,11 @@ fn varDecl( |
| 1069 | }, | 1201 | }, |
| 1070 | .keyword_var => { | 1202 | .keyword_var => { |
| 1071 | var resolve_inferred_alloc: ?*zir.Inst = null; | 1203 | var resolve_inferred_alloc: ?*zir.Inst = null; |
| 1072 | const var_data: struct { result_loc: ResultLoc, alloc: *zir.Inst } = if (node.getTypeNode()) |type_node| a: { | 1204 | const var_data: struct { |
| 1073 | const type_inst = try typeExpr(mod, scope, type_node); | 1205 | result_loc: ResultLoc, |
| | 1206 | alloc: *zir.Inst, |
| | 1207 | } = if (var_decl.ast.type_node != 0) a: { |
| | 1208 | const type_inst = try typeExpr(mod, scope, var_decl.ast.type_node); |
| 1074 | const alloc = try addZIRUnOp(mod, scope, name_src, .alloc_mut, type_inst); | 1209 | const alloc = try addZIRUnOp(mod, scope, name_src, .alloc_mut, type_inst); |
| 1075 | break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } }; | 1210 | break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } }; |
| 1076 | } else a: { | 1211 | } else a: { |
| ... | @@ -1078,7 +1213,7 @@ fn varDecl( | ... | @@ -1078,7 +1213,7 @@ fn varDecl( |
| 1078 | resolve_inferred_alloc = &alloc.base; | 1213 | resolve_inferred_alloc = &alloc.base; |
| 1079 | break :a .{ .alloc = &alloc.base, .result_loc = .{ .inferred_ptr = alloc } }; | 1214 | break :a .{ .alloc = &alloc.base, .result_loc = .{ .inferred_ptr = alloc } }; |
| 1080 | }; | 1215 | }; |
| 1081 | const init_inst = try expr(mod, scope, var_data.result_loc, init_node); | 1216 | const init_inst = try expr(mod, scope, var_data.result_loc, var_decl.ast.init_node); |
| 1082 | if (resolve_inferred_alloc) |inst| { | 1217 | if (resolve_inferred_alloc) |inst| { |
| 1083 | _ = try addZIRUnOp(mod, scope, name_src, .resolve_inferred_alloc, inst); | 1218 | _ = try addZIRUnOp(mod, scope, name_src, .resolve_inferred_alloc, inst); |
| 1084 | } | 1219 | } |
| ... | @@ -1099,13 +1234,15 @@ fn assign(mod: *Module, scope: *Scope, infix_node: ast.Node.Index) InnerError!vo | ... | @@ -1099,13 +1234,15 @@ fn assign(mod: *Module, scope: *Scope, infix_node: ast.Node.Index) InnerError!vo |
| 1099 | const tree = scope.tree(); | 1234 | const tree = scope.tree(); |
| 1100 | const node_datas = tree.nodes.items(.data); | 1235 | const node_datas = tree.nodes.items(.data); |
| 1101 | const main_tokens = tree.nodes.items(.main_token); | 1236 | const main_tokens = tree.nodes.items(.main_token); |
| | 1237 | const node_tags = tree.nodes.items(.tag); |
| | 1238 | |
| 1102 | const lhs = node_datas[infix_node].lhs; | 1239 | const lhs = node_datas[infix_node].lhs; |
| 1103 | const rhs = node_datas[infix_node].rhs; | 1240 | const rhs = node_datas[infix_node].rhs; |
| 1104 | if (node_tags[lhs] == .identifier) { | 1241 | if (node_tags[lhs] == .identifier) { |
| 1105 | // This intentionally does not support `@"_"` syntax. | 1242 | // This intentionally does not support `@"_"` syntax. |
| 1106 | const ident_name = tree.tokenSlice(main_tokens[lhs]); | 1243 | const ident_name = tree.tokenSlice(main_tokens[lhs]); |
| 1107 | if (mem.eql(u8, ident_name, "_")) { | 1244 | if (mem.eql(u8, ident_name, "_")) { |
| 1108 | _ = try expr(mod, scope, .discard, infix_node.rhs); | 1245 | _ = try expr(mod, scope, .discard, rhs); |
| 1109 | return; | 1246 | return; |
| 1110 | } | 1247 | } |
| 1111 | } | 1248 | } |
| ... | @@ -1122,6 +1259,7 @@ fn assignOp( | ... | @@ -1122,6 +1259,7 @@ fn assignOp( |
| 1122 | const tree = scope.tree(); | 1259 | const tree = scope.tree(); |
| 1123 | const node_datas = tree.nodes.items(.data); | 1260 | const node_datas = tree.nodes.items(.data); |
| 1124 | const main_tokens = tree.nodes.items(.main_token); | 1261 | const main_tokens = tree.nodes.items(.main_token); |
| | 1262 | const token_starts = tree.tokens.items(.start); |
| 1125 | | 1263 | |
| 1126 | const lhs_ptr = try lvalExpr(mod, scope, node_datas[infix_node].lhs); | 1264 | const lhs_ptr = try lvalExpr(mod, scope, node_datas[infix_node].lhs); |
| 1127 | const lhs = try addZIRUnOp(mod, scope, lhs_ptr.src, .deref, lhs_ptr); | 1265 | const lhs = try addZIRUnOp(mod, scope, lhs_ptr.src, .deref, lhs_ptr); |
| ... | @@ -1136,6 +1274,7 @@ fn boolNot(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.In | ... | @@ -1136,6 +1274,7 @@ fn boolNot(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.In |
| 1136 | const tree = scope.tree(); | 1274 | const tree = scope.tree(); |
| 1137 | const node_datas = tree.nodes.items(.data); | 1275 | const node_datas = tree.nodes.items(.data); |
| 1138 | const main_tokens = tree.nodes.items(.main_token); | 1276 | const main_tokens = tree.nodes.items(.main_token); |
| | 1277 | const token_starts = tree.tokens.items(.start); |
| 1139 | | 1278 | |
| 1140 | const src = token_starts[main_tokens[node]]; | 1279 | const src = token_starts[main_tokens[node]]; |
| 1141 | const bool_type = try addZIRInstConst(mod, scope, src, .{ | 1280 | const bool_type = try addZIRInstConst(mod, scope, src, .{ |
| ... | @@ -1150,6 +1289,7 @@ fn bitNot(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.Ins | ... | @@ -1150,6 +1289,7 @@ fn bitNot(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.Ins |
| 1150 | const tree = scope.tree(); | 1289 | const tree = scope.tree(); |
| 1151 | const node_datas = tree.nodes.items(.data); | 1290 | const node_datas = tree.nodes.items(.data); |
| 1152 | const main_tokens = tree.nodes.items(.main_token); | 1291 | const main_tokens = tree.nodes.items(.main_token); |
| | 1292 | const token_starts = tree.tokens.items(.start); |
| 1153 | | 1293 | |
| 1154 | const src = token_starts[main_tokens[node]]; | 1294 | const src = token_starts[main_tokens[node]]; |
| 1155 | const operand = try expr(mod, scope, .none, node_datas[node].lhs); | 1295 | const operand = try expr(mod, scope, .none, node_datas[node].lhs); |
| ... | @@ -1165,6 +1305,7 @@ fn negation( | ... | @@ -1165,6 +1305,7 @@ fn negation( |
| 1165 | const tree = scope.tree(); | 1305 | const tree = scope.tree(); |
| 1166 | const node_datas = tree.nodes.items(.data); | 1306 | const node_datas = tree.nodes.items(.data); |
| 1167 | const main_tokens = tree.nodes.items(.main_token); | 1307 | const main_tokens = tree.nodes.items(.main_token); |
| | 1308 | const token_starts = tree.tokens.items(.start); |
| 1168 | | 1309 | |
| 1169 | const src = token_starts[main_tokens[node]]; | 1310 | const src = token_starts[main_tokens[node]]; |
| 1170 | const lhs = try addZIRInstConst(mod, scope, src, .{ | 1311 | const lhs = try addZIRInstConst(mod, scope, src, .{ |
| ... | @@ -1175,53 +1316,61 @@ fn negation( | ... | @@ -1175,53 +1316,61 @@ fn negation( |
| 1175 | return addZIRBinOp(mod, scope, src, op_inst_tag, lhs, rhs); | 1316 | return addZIRBinOp(mod, scope, src, op_inst_tag, lhs, rhs); |
| 1176 | } | 1317 | } |
| 1177 | | 1318 | |
| 1178 | fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo, rhs: *ast.Node, size: std.builtin.TypeInfo.Pointer.Size) InnerError!*zir.Inst { | 1319 | fn ptrType( |
| | 1320 | mod: *Module, |
| | 1321 | scope: *Scope, |
| | 1322 | rl: ResultLoc, |
| | 1323 | ptr_info: ast.full.PtrType, |
| | 1324 | ) InnerError!*zir.Inst { |
| | 1325 | const tree = scope.tree(); |
| | 1326 | const token_starts = tree.tokens.items(.start); |
| | 1327 | |
| | 1328 | const src = token_starts[ptr_info.ast.main_token]; |
| | 1329 | |
| 1179 | const simple = ptr_info.allowzero_token == null and | 1330 | const simple = ptr_info.allowzero_token == null and |
| 1180 | ptr_info.align_info == null and | 1331 | ptr_info.ast.align_node == 0 and |
| 1181 | ptr_info.volatile_token == null and | 1332 | ptr_info.volatile_token == null and |
| 1182 | ptr_info.sentinel == null; | 1333 | ptr_info.ast.sentinel == 0; |
| 1183 | | 1334 | |
| 1184 | if (simple) { | 1335 | if (simple) { |
| 1185 | const child_type = try typeExpr(mod, scope, rhs); | 1336 | const child_type = try typeExpr(mod, scope, ptr_info.ast.child_type); |
| 1186 | const mutable = ptr_info.const_token == null; | 1337 | const mutable = ptr_info.const_token == null; |
| 1187 | // TODO stage1 type inference bug | | |
| 1188 | const T = zir.Inst.Tag; | 1338 | const T = zir.Inst.Tag; |
| 1189 | return addZIRUnOp(mod, scope, src, switch (size) { | 1339 | const result = try addZIRUnOp(mod, scope, src, switch (ptr_info.size) { |
| 1190 | .One => if (mutable) T.single_mut_ptr_type else T.single_const_ptr_type, | 1340 | .One => if (mutable) T.single_mut_ptr_type else T.single_const_ptr_type, |
| 1191 | .Many => if (mutable) T.many_mut_ptr_type else T.many_const_ptr_type, | 1341 | .Many => if (mutable) T.many_mut_ptr_type else T.many_const_ptr_type, |
| 1192 | .C => if (mutable) T.c_mut_ptr_type else T.c_const_ptr_type, | 1342 | .C => if (mutable) T.c_mut_ptr_type else T.c_const_ptr_type, |
| 1193 | .Slice => if (mutable) T.mut_slice_type else T.const_slice_type, | 1343 | .Slice => if (mutable) T.mut_slice_type else T.const_slice_type, |
| 1194 | }, child_type); | 1344 | }, child_type); |
| | 1345 | return rvalue(mod, scope, rl, result); |
| 1195 | } | 1346 | } |
| 1196 | | 1347 | |
| 1197 | var kw_args: std.meta.fieldInfo(zir.Inst.PtrType, .kw_args).field_type = .{}; | 1348 | var kw_args: std.meta.fieldInfo(zir.Inst.PtrType, .kw_args).field_type = .{}; |
| 1198 | kw_args.size = size; | 1349 | kw_args.size = ptr_info.size; |
| 1199 | kw_args.@"allowzero" = ptr_info.allowzero_token != null; | 1350 | kw_args.@"allowzero" = ptr_info.allowzero_token != null; |
| 1200 | if (ptr_info.align_info) |some| { | 1351 | if (ptr_info.ast.align_node != 0) { |
| 1201 | kw_args.@"align" = try expr(mod, scope, .none, some.node); | 1352 | kw_args.@"align" = try expr(mod, scope, .none, ptr_info.ast.align_node); |
| 1202 | if (some.bit_range) |bit_range| { | 1353 | if (ptr_info.ast.bit_range_start != 0) { |
| 1203 | kw_args.align_bit_start = try expr(mod, scope, .none, bit_range.start); | 1354 | kw_args.align_bit_start = try expr(mod, scope, .none, ptr_info.ast.bit_range_start); |
| 1204 | kw_args.align_bit_end = try expr(mod, scope, .none, bit_range.end); | 1355 | kw_args.align_bit_end = try expr(mod, scope, .none, ptr_info.ast.bit_range_end); |
| 1205 | } | 1356 | } |
| 1206 | } | 1357 | } |
| 1207 | kw_args.mutable = ptr_info.const_token == null; | 1358 | kw_args.mutable = ptr_info.const_token == null; |
| 1208 | kw_args.@"volatile" = ptr_info.volatile_token != null; | 1359 | kw_args.@"volatile" = ptr_info.volatile_token != null; |
| 1209 | if (ptr_info.sentinel) |some| { | 1360 | const child_type = try typeExpr(mod, scope, ptr_info.ast.child_type); |
| 1210 | kw_args.sentinel = try expr(mod, scope, .none, some); | 1361 | if (ptr_info.ast.sentinel != 0) { |
| 1211 | } | 1362 | kw_args.sentinel = try expr(mod, scope, .{ .ty = child_type }, ptr_info.ast.sentinel); |
| 1212 | | | |
| 1213 | const child_type = try typeExpr(mod, scope, rhs); | | |
| 1214 | if (kw_args.sentinel) |some| { | | |
| 1215 | kw_args.sentinel = try addZIRBinOp(mod, scope, some.src, .as, child_type, some); | | |
| 1216 | } | 1363 | } |
| 1217 | | 1364 | const result = try addZIRInst(mod, scope, src, zir.Inst.PtrType, .{ .child_type = child_type }, kw_args); |
| 1218 | return addZIRInst(mod, scope, src, zir.Inst.PtrType, .{ .child_type = child_type }, kw_args); | 1365 | return rvalue(mod, scope, rl, result); |
| 1219 | } | 1366 | } |
| 1220 | | 1367 | |
| 1221 | fn arrayType(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !*zir.Inst { | 1368 | fn arrayType(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !*zir.Inst { |
| 1222 | const tree = scope.tree(); | 1369 | const tree = scope.tree(); |
| 1223 | const main_tokens = tree.nodes.items(.main_token); | 1370 | const main_tokens = tree.nodes.items(.main_token); |
| 1224 | const node_datas = tree.nodes.items(.data); | 1371 | const node_datas = tree.nodes.items(.data); |
| | 1372 | const token_starts = tree.tokens.items(.start); |
| | 1373 | |
| 1225 | const src = token_starts[main_tokens[node]]; | 1374 | const src = token_starts[main_tokens[node]]; |
| 1226 | const usize_type = try addZIRInstConst(mod, scope, src, .{ | 1375 | const usize_type = try addZIRInstConst(mod, scope, src, .{ |
| 1227 | .ty = Type.initTag(.type), | 1376 | .ty = Type.initTag(.type), |
| ... | @@ -1246,6 +1395,9 @@ fn arrayType(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) ! | ... | @@ -1246,6 +1395,9 @@ fn arrayType(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) ! |
| 1246 | fn arrayTypeSentinel(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !*zir.Inst { | 1395 | fn arrayTypeSentinel(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !*zir.Inst { |
| 1247 | const tree = scope.tree(); | 1396 | const tree = scope.tree(); |
| 1248 | const main_tokens = tree.nodes.items(.main_token); | 1397 | const main_tokens = tree.nodes.items(.main_token); |
| | 1398 | const token_starts = tree.tokens.items(.start); |
| | 1399 | const node_datas = tree.nodes.items(.data); |
| | 1400 | |
| 1249 | const len_node = node_datas[node].lhs; | 1401 | const len_node = node_datas[node].lhs; |
| 1250 | const extra = tree.extraData(node_datas[node].rhs, ast.Node.ArrayTypeSentinel); | 1402 | const extra = tree.extraData(node_datas[node].rhs, ast.Node.ArrayTypeSentinel); |
| 1251 | const src = token_starts[main_tokens[node]]; | 1403 | const src = token_starts[main_tokens[node]]; |
| ... | @@ -1274,6 +1426,8 @@ fn containerField( | ... | @@ -1274,6 +1426,8 @@ fn containerField( |
| 1274 | node: *ast.Node.ContainerField, | 1426 | node: *ast.Node.ContainerField, |
| 1275 | ) InnerError!*zir.Inst { | 1427 | ) InnerError!*zir.Inst { |
| 1276 | const tree = scope.tree(); | 1428 | const tree = scope.tree(); |
| | 1429 | const token_starts = tree.tokens.items(.start); |
| | 1430 | |
| 1277 | const src = token_starts[tree.firstToken(node)]; | 1431 | const src = token_starts[tree.firstToken(node)]; |
| 1278 | const name = try mod.identifierTokenString(scope, node.name_token); | 1432 | const name = try mod.identifierTokenString(scope, node.name_token); |
| 1279 | | 1433 | |
| ... | @@ -1305,9 +1459,18 @@ fn containerField( | ... | @@ -1305,9 +1459,18 @@ fn containerField( |
| 1305 | }); | 1459 | }); |
| 1306 | } | 1460 | } |
| 1307 | | 1461 | |
| 1308 | fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ContainerDecl) InnerError!*zir.Inst { | 1462 | fn containerDecl( |
| | 1463 | mod: *Module, |
| | 1464 | scope: *Scope, |
| | 1465 | rl: ResultLoc, |
| | 1466 | container_decl: ast.full.ContainerDecl, |
| | 1467 | ) InnerError!*zir.Inst { |
| 1309 | const tree = scope.tree(); | 1468 | const tree = scope.tree(); |
| 1310 | const src = token_starts[node.kind_token]; | 1469 | const token_starts = tree.tokens.items(.start); |
| | 1470 | const node_tags = tree.nodes.items(.tag); |
| | 1471 | const token_tags = tree.tokens.items(.tag); |
| | 1472 | |
| | 1473 | const src = token_starts[container_decl.ast.main_token]; |
| 1311 | | 1474 | |
| 1312 | var gen_scope: Scope.GenZIR = .{ | 1475 | var gen_scope: Scope.GenZIR = .{ |
| 1313 | .parent = scope, | 1476 | .parent = scope, |
| ... | @@ -1321,9 +1484,12 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con | ... | @@ -1321,9 +1484,12 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con |
| 1321 | var fields = std.ArrayList(*zir.Inst).init(mod.gpa); | 1484 | var fields = std.ArrayList(*zir.Inst).init(mod.gpa); |
| 1322 | defer fields.deinit(); | 1485 | defer fields.deinit(); |
| 1323 | | 1486 | |
| 1324 | for (node.fieldsAndDecls()) |fd| { | 1487 | for (container_decl.ast.members) |member| { |
| 1325 | if (fd.castTag(.ContainerField)) |f| { | 1488 | switch (node_tags[member]) { |
| 1326 | try fields.append(try containerField(mod, &gen_scope.base, f)); | 1489 | .container_field_init, .container_field_align, .container_field => { |
| | 1490 | try fields.append(try containerField(mod, &gen_scope.base, member)); |
| | 1491 | }, |
| | 1492 | else => continue, |
| 1327 | } | 1493 | } |
| 1328 | } | 1494 | } |
| 1329 | | 1495 | |
| ... | @@ -1332,19 +1498,22 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con | ... | @@ -1332,19 +1498,22 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con |
| 1332 | const arena = &decl_arena.allocator; | 1498 | const arena = &decl_arena.allocator; |
| 1333 | | 1499 | |
| 1334 | var layout: std.builtin.TypeInfo.ContainerLayout = .Auto; | 1500 | var layout: std.builtin.TypeInfo.ContainerLayout = .Auto; |
| 1335 | if (node.layout_token) |some| switch (tree.token_ids[some]) { | 1501 | if (container_decl.layout_token) |some| switch (token_tags[some]) { |
| 1336 | .keyword_extern => layout = .Extern, | 1502 | .keyword_extern => layout = .Extern, |
| 1337 | .keyword_packed => layout = .Packed, | 1503 | .keyword_packed => layout = .Packed, |
| 1338 | else => unreachable, | 1504 | else => unreachable, |
| 1339 | }; | 1505 | }; |
| 1340 | | 1506 | |
| 1341 | const container_type = switch (tree.token_ids[node.kind_token]) { | 1507 | // TODO this implementation is incorrect. The types must be created in semantic |
| | 1508 | // analysis, not astgen, because the same ZIR is re-used for multiple inline function calls, |
| | 1509 | // comptime function calls, and generic function instantiations, and these |
| | 1510 | // must result in different instances of container types. |
| | 1511 | const container_type = switch (token_tags[container_decl.ast.main_token]) { |
| 1342 | .keyword_enum => blk: { | 1512 | .keyword_enum => blk: { |
| 1343 | const tag_type: ?*zir.Inst = switch (node.init_arg_expr) { | 1513 | const tag_type: ?*zir.Inst = if (container_decl.ast.arg != 0) |
| 1344 | .Type => |t| try typeExpr(mod, &gen_scope.base, t), | 1514 | try typeExpr(mod, &gen_scope.base, container_decl.ast.arg) |
| 1345 | .None => null, | 1515 | else |
| 1346 | .Enum => unreachable, | 1516 | null; |
| 1347 | }; | | |
| 1348 | const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.EnumType, .{ | 1517 | const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.EnumType, .{ |
| 1349 | .fields = try arena.dupe(*zir.Inst, fields.items), | 1518 | .fields = try arena.dupe(*zir.Inst, fields.items), |
| 1350 | }, .{ | 1519 | }, .{ |
| ... | @@ -1367,7 +1536,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con | ... | @@ -1367,7 +1536,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con |
| 1367 | break :blk Type.initPayload(&enum_type.base); | 1536 | break :blk Type.initPayload(&enum_type.base); |
| 1368 | }, | 1537 | }, |
| 1369 | .keyword_struct => blk: { | 1538 | .keyword_struct => blk: { |
| 1370 | assert(node.init_arg_expr == .None); | 1539 | assert(container_decl.ast.arg == 0); |
| 1371 | const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.StructType, .{ | 1540 | const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.StructType, .{ |
| 1372 | .fields = try arena.dupe(*zir.Inst, fields.items), | 1541 | .fields = try arena.dupe(*zir.Inst, fields.items), |
| 1373 | }, .{ | 1542 | }, .{ |
| ... | @@ -1389,21 +1558,16 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con | ... | @@ -1389,21 +1558,16 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con |
| 1389 | break :blk Type.initPayload(&struct_type.base); | 1558 | break :blk Type.initPayload(&struct_type.base); |
| 1390 | }, | 1559 | }, |
| 1391 | .keyword_union => blk: { | 1560 | .keyword_union => blk: { |
| 1392 | const init_inst = switch (node.init_arg_expr) { | 1561 | const init_inst: ?*zir.Inst = if (container_decl.ast.arg != 0) |
| 1393 | .Enum => |e| if (e) |t| try typeExpr(mod, &gen_scope.base, t) else null, | 1562 | try typeExpr(mod, &gen_scope.base, container_decl.ast.arg) |
| 1394 | .None => null, | 1563 | else |
| 1395 | .Type => |t| try typeExpr(mod, &gen_scope.base, t), | 1564 | null; |
| 1396 | }; | 1565 | const has_enum_token = container_decl.ast.enum_token != null; |
| 1397 | const init_kind: zir.Inst.UnionType.InitKind = switch (node.init_arg_expr) { | | |
| 1398 | .Enum => .enum_type, | | |
| 1399 | .None => .none, | | |
| 1400 | .Type => .tag_type, | | |
| 1401 | }; | | |
| 1402 | const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.UnionType, .{ | 1566 | const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.UnionType, .{ |
| 1403 | .fields = try arena.dupe(*zir.Inst, fields.items), | 1567 | .fields = try arena.dupe(*zir.Inst, fields.items), |
| 1404 | }, .{ | 1568 | }, .{ |
| 1405 | .layout = layout, | 1569 | .layout = layout, |
| 1406 | .init_kind = init_kind, | 1570 | .has_enum_token = has_enum_token, |
| 1407 | .init_inst = init_inst, | 1571 | .init_inst = init_inst, |
| 1408 | }); | 1572 | }); |
| 1409 | const union_type = try arena.create(Type.Payload.Union); | 1573 | const union_type = try arena.create(Type.Payload.Union); |
| ... | @@ -1437,7 +1601,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con | ... | @@ -1437,7 +1601,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con |
| 1437 | else => unreachable, | 1601 | else => unreachable, |
| 1438 | }; | 1602 | }; |
| 1439 | const val = try Value.Tag.ty.create(arena, container_type); | 1603 | const val = try Value.Tag.ty.create(arena, container_type); |
| 1440 | const decl = try mod.createContainerDecl(scope, node.kind_token, &decl_arena, .{ | 1604 | const decl = try mod.createContainerDecl(scope, container_decl.ast.main_token, &decl_arena, .{ |
| 1441 | .ty = Type.initTag(.type), | 1605 | .ty = Type.initTag(.type), |
| 1442 | .val = val, | 1606 | .val = val, |
| 1443 | }); | 1607 | }); |
| ... | @@ -1459,6 +1623,7 @@ fn errorSetDecl( | ... | @@ -1459,6 +1623,7 @@ fn errorSetDecl( |
| 1459 | const tree = scope.tree(); | 1623 | const tree = scope.tree(); |
| 1460 | const main_tokens = tree.nodes.items(.main_token); | 1624 | const main_tokens = tree.nodes.items(.main_token); |
| 1461 | const token_tags = tree.tokens.items(.tag); | 1625 | const token_tags = tree.tokens.items(.tag); |
| | 1626 | const token_starts = tree.tokens.items(.start); |
| 1462 | | 1627 | |
| 1463 | // Count how many fields there are. | 1628 | // Count how many fields there are. |
| 1464 | const error_token = main_tokens[node]; | 1629 | const error_token = main_tokens[node]; |
| ... | @@ -1500,15 +1665,17 @@ fn orelseCatchExpr( | ... | @@ -1500,15 +1665,17 @@ fn orelseCatchExpr( |
| 1500 | mod: *Module, | 1665 | mod: *Module, |
| 1501 | scope: *Scope, | 1666 | scope: *Scope, |
| 1502 | rl: ResultLoc, | 1667 | rl: ResultLoc, |
| 1503 | lhs: *ast.Node, | 1668 | lhs: ast.Node.Index, |
| 1504 | op_token: ast.TokenIndex, | 1669 | op_token: ast.TokenIndex, |
| 1505 | cond_op: zir.Inst.Tag, | 1670 | cond_op: zir.Inst.Tag, |
| 1506 | unwrap_op: zir.Inst.Tag, | 1671 | unwrap_op: zir.Inst.Tag, |
| 1507 | unwrap_code_op: zir.Inst.Tag, | 1672 | unwrap_code_op: zir.Inst.Tag, |
| 1508 | rhs: *ast.Node, | 1673 | rhs: ast.Node.Index, |
| 1509 | payload_node: ?*ast.Node, | 1674 | payload_token: ?ast.TokenIndex, |
| 1510 | ) InnerError!*zir.Inst { | 1675 | ) InnerError!*zir.Inst { |
| 1511 | const tree = scope.tree(); | 1676 | const tree = scope.tree(); |
| | 1677 | const token_starts = tree.tokens.items(.start); |
| | 1678 | |
| 1512 | const src = token_starts[op_token]; | 1679 | const src = token_starts[op_token]; |
| 1513 | | 1680 | |
| 1514 | var block_scope: Scope.GenZIR = .{ | 1681 | var block_scope: Scope.GenZIR = .{ |
| ... | @@ -1547,12 +1714,11 @@ fn orelseCatchExpr( | ... | @@ -1547,12 +1714,11 @@ fn orelseCatchExpr( |
| 1547 | | 1714 | |
| 1548 | var err_val_scope: Scope.LocalVal = undefined; | 1715 | var err_val_scope: Scope.LocalVal = undefined; |
| 1549 | const then_sub_scope = blk: { | 1716 | const then_sub_scope = blk: { |
| 1550 | const payload = payload_node orelse break :blk &then_scope.base; | 1717 | const payload = payload_token orelse break :blk &then_scope.base; |
| 1551 | | 1718 | if (mem.eql(u8, tree.tokenSlice(payload), "_")) { |
| 1552 | const err_name = tree.tokenSlice(payload.castTag(.Payload).?.error_symbol.firstToken()); | 1719 | return mod.failTok(&then_scope.base, payload, "discard of error capture; omit it instead", .{}); |
| 1553 | if (mem.eql(u8, err_name, "_")) | 1720 | } |
| 1554 | break :blk &then_scope.base; | 1721 | const err_name = try mod.identifierTokenString(scope, payload); |
| 1555 | | | |
| 1556 | err_val_scope = .{ | 1722 | err_val_scope = .{ |
| 1557 | .parent = &then_scope.base, | 1723 | .parent = &then_scope.base, |
| 1558 | .gen_zir = &then_scope, | 1724 | .gen_zir = &then_scope, |
| ... | @@ -1685,18 +1851,20 @@ pub fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) I | ... | @@ -1685,18 +1851,20 @@ pub fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) I |
| 1685 | const tree = scope.tree(); | 1851 | const tree = scope.tree(); |
| 1686 | const token_starts = tree.tokens.items(.start); | 1852 | const token_starts = tree.tokens.items(.start); |
| 1687 | const main_tokens = tree.nodes.items(.main_token); | 1853 | const main_tokens = tree.nodes.items(.main_token); |
| | 1854 | const node_datas = tree.nodes.items(.data); |
| | 1855 | |
| 1688 | const dot_token = main_tokens[node]; | 1856 | const dot_token = main_tokens[node]; |
| 1689 | const src = token_starts[dot_token]; | 1857 | const src = token_starts[dot_token]; |
| 1690 | const field_ident = dot_token + 1; | 1858 | const field_ident = dot_token + 1; |
| 1691 | const field_name = try mod.identifierTokenString(scope, field_ident); | 1859 | const field_name = try mod.identifierTokenString(scope, field_ident); |
| 1692 | if (rl == .ref) { | 1860 | if (rl == .ref) { |
| 1693 | return addZirInstTag(mod, scope, src, .field_ptr, .{ | 1861 | return addZirInstTag(mod, scope, src, .field_ptr, .{ |
| 1694 | .object = try expr(mod, scope, .ref, node.lhs), | 1862 | .object = try expr(mod, scope, .ref, node_datas[node].lhs), |
| 1695 | .field_name = field_name, | 1863 | .field_name = field_name, |
| 1696 | }); | 1864 | }); |
| 1697 | } else { | 1865 | } else { |
| 1698 | return rvalue(mod, scope, rl, try addZirInstTag(mod, scope, src, .field_val, .{ | 1866 | return rvalue(mod, scope, rl, try addZirInstTag(mod, scope, src, .field_val, .{ |
| 1699 | .object = try expr(mod, scope, .none, node.lhs), | 1867 | .object = try expr(mod, scope, .none, node_datas[node].lhs), |
| 1700 | .field_name = field_name, | 1868 | .field_name = field_name, |
| 1701 | })); | 1869 | })); |
| 1702 | } | 1870 | } |
| ... | @@ -1711,6 +1879,8 @@ fn arrayAccess( | ... | @@ -1711,6 +1879,8 @@ fn arrayAccess( |
| 1711 | const tree = scope.tree(); | 1879 | const tree = scope.tree(); |
| 1712 | const main_tokens = tree.nodes.items(.main_token); | 1880 | const main_tokens = tree.nodes.items(.main_token); |
| 1713 | const token_starts = tree.tokens.items(.start); | 1881 | const token_starts = tree.tokens.items(.start); |
| | 1882 | const node_datas = tree.nodes.items(.data); |
| | 1883 | |
| 1714 | const src = token_starts[main_tokens[node]]; | 1884 | const src = token_starts[main_tokens[node]]; |
| 1715 | const usize_type = try addZIRInstConst(mod, scope, src, .{ | 1885 | const usize_type = try addZIRInstConst(mod, scope, src, .{ |
| 1716 | .ty = Type.initTag(.type), | 1886 | .ty = Type.initTag(.type), |
| ... | @@ -1737,6 +1907,7 @@ fn sliceExpr( | ... | @@ -1737,6 +1907,7 @@ fn sliceExpr( |
| 1737 | ) InnerError!*zir.Inst { | 1907 | ) InnerError!*zir.Inst { |
| 1738 | const tree = scope.tree(); | 1908 | const tree = scope.tree(); |
| 1739 | const token_starts = tree.tokens.items(.start); | 1909 | const token_starts = tree.tokens.items(.start); |
| | 1910 | |
| 1740 | const src = token_starts[slice.ast.lbracket]; | 1911 | const src = token_starts[slice.ast.lbracket]; |
| 1741 | | 1912 | |
| 1742 | const usize_type = try addZIRInstConst(mod, scope, src, .{ | 1913 | const usize_type = try addZIRInstConst(mod, scope, src, .{ |
| ... | @@ -1786,6 +1957,7 @@ fn simpleBinOp( | ... | @@ -1786,6 +1957,7 @@ fn simpleBinOp( |
| 1786 | const tree = scope.tree(); | 1957 | const tree = scope.tree(); |
| 1787 | const node_datas = tree.nodes.items(.data); | 1958 | const node_datas = tree.nodes.items(.data); |
| 1788 | const main_tokens = tree.nodes.items(.main_token); | 1959 | const main_tokens = tree.nodes.items(.main_token); |
| | 1960 | const token_starts = tree.tokens.items(.start); |
| 1789 | | 1961 | |
| 1790 | const lhs = try expr(mod, scope, .none, node_datas[infix_node].lhs); | 1962 | const lhs = try expr(mod, scope, .none, node_datas[infix_node].lhs); |
| 1791 | const rhs = try expr(mod, scope, .none, node_datas[infix_node].rhs); | 1963 | const rhs = try expr(mod, scope, .none, node_datas[infix_node].rhs); |
| ... | @@ -1804,6 +1976,7 @@ fn boolBinOp( | ... | @@ -1804,6 +1976,7 @@ fn boolBinOp( |
| 1804 | const tree = scope.tree(); | 1976 | const tree = scope.tree(); |
| 1805 | const node_datas = tree.nodes.items(.data); | 1977 | const node_datas = tree.nodes.items(.data); |
| 1806 | const main_tokens = tree.nodes.items(.main_token); | 1978 | const main_tokens = tree.nodes.items(.main_token); |
| | 1979 | const token_starts = tree.tokens.items(.start); |
| 1807 | | 1980 | |
| 1808 | const src = token_starts[main_tokens[infix_node]]; | 1981 | const src = token_starts[main_tokens[infix_node]]; |
| 1809 | const bool_type = try addZIRInstConst(mod, scope, src, .{ | 1982 | const bool_type = try addZIRInstConst(mod, scope, src, .{ |
| ... | @@ -1899,13 +2072,14 @@ fn ifExpr( | ... | @@ -1899,13 +2072,14 @@ fn ifExpr( |
| 1899 | defer block_scope.instructions.deinit(mod.gpa); | 2072 | defer block_scope.instructions.deinit(mod.gpa); |
| 1900 | | 2073 | |
| 1901 | const tree = scope.tree(); | 2074 | const tree = scope.tree(); |
| 1902 | const node_datas = tree.nodes.items(.data); | | |
| 1903 | const main_tokens = tree.nodes.items(.main_token); | 2075 | const main_tokens = tree.nodes.items(.main_token); |
| | 2076 | const token_starts = tree.tokens.items(.start); |
| | 2077 | |
| 1904 | const if_src = token_starts[if_full.ast.if_token]; | 2078 | const if_src = token_starts[if_full.ast.if_token]; |
| 1905 | | 2079 | |
| 1906 | const cond = c: { | 2080 | const cond = c: { |
| 1907 | // TODO https://github.com/ziglang/zig/issues/7929 | 2081 | // TODO https://github.com/ziglang/zig/issues/7929 |
| 1908 | if (if_full.ast.error_token) |error_token| { | 2082 | if (if_full.error_token) |error_token| { |
| 1909 | return mod.failTok(scope, error_token, "TODO implement if error union", .{}); | 2083 | return mod.failTok(scope, error_token, "TODO implement if error union", .{}); |
| 1910 | } else if (if_full.payload_token) |payload_token| { | 2084 | } else if (if_full.payload_token) |payload_token| { |
| 1911 | return mod.failTok(scope, payload_token, "TODO implement if optional", .{}); | 2085 | return mod.failTok(scope, payload_token, "TODO implement if optional", .{}); |
| ... | @@ -1966,7 +2140,7 @@ fn ifExpr( | ... | @@ -1966,7 +2140,7 @@ fn ifExpr( |
| 1966 | }; | 2140 | }; |
| 1967 | } else | 2141 | } else |
| 1968 | .{ | 2142 | .{ |
| 1969 | .src = token_starts[tree.lastToken(if_full.then_expr)], | 2143 | .src = token_starts[tree.lastToken(if_full.ast.then_expr)], |
| 1970 | .result = null, | 2144 | .result = null, |
| 1971 | }; | 2145 | }; |
| 1972 | | 2146 | |
| ... | @@ -2042,8 +2216,9 @@ fn whileExpr( | ... | @@ -2042,8 +2216,9 @@ fn whileExpr( |
| 2042 | defer continue_scope.instructions.deinit(mod.gpa); | 2216 | defer continue_scope.instructions.deinit(mod.gpa); |
| 2043 | | 2217 | |
| 2044 | const tree = scope.tree(); | 2218 | const tree = scope.tree(); |
| 2045 | const node_datas = tree.nodes.items(.data); | | |
| 2046 | const main_tokens = tree.nodes.items(.main_token); | 2219 | const main_tokens = tree.nodes.items(.main_token); |
| | 2220 | const token_starts = tree.tokens.items(.start); |
| | 2221 | |
| 2047 | const while_src = token_starts[while_full.ast.while_token]; | 2222 | const while_src = token_starts[while_full.ast.while_token]; |
| 2048 | const void_type = try addZIRInstConst(mod, scope, while_src, .{ | 2223 | const void_type = try addZIRInstConst(mod, scope, while_src, .{ |
| 2049 | .ty = Type.initTag(.type), | 2224 | .ty = Type.initTag(.type), |
| ... | @@ -2051,16 +2226,16 @@ fn whileExpr( | ... | @@ -2051,16 +2226,16 @@ fn whileExpr( |
| 2051 | }); | 2226 | }); |
| 2052 | const cond = c: { | 2227 | const cond = c: { |
| 2053 | // TODO https://github.com/ziglang/zig/issues/7929 | 2228 | // TODO https://github.com/ziglang/zig/issues/7929 |
| 2054 | if (while_full.ast.error_token) |error_token| { | 2229 | if (while_full.error_token) |error_token| { |
| 2055 | return mod.failTok(scope, error_token, "TODO implement while error union", .{}); | 2230 | return mod.failTok(scope, error_token, "TODO implement while error union", .{}); |
| 2056 | } else if (while_full.payload_token) |payload_token| { | 2231 | } else if (while_full.payload_token) |payload_token| { |
| 2057 | return mod.failTok(scope, payload_token, "TODO implement while optional", .{}); | 2232 | return mod.failTok(scope, payload_token, "TODO implement while optional", .{}); |
| 2058 | } else { | 2233 | } else { |
| 2059 | const bool_type = try addZIRInstConst(mod, &block_scope.base, while_src, .{ | 2234 | const bool_type = try addZIRInstConst(mod, &continue_scope.base, while_src, .{ |
| 2060 | .ty = Type.initTag(.type), | 2235 | .ty = Type.initTag(.type), |
| 2061 | .val = Value.initTag(.bool_type), | 2236 | .val = Value.initTag(.bool_type), |
| 2062 | }); | 2237 | }); |
| 2063 | break :c try expr(mod, &block_scope.base, .{ .ty = bool_type }, while_full.ast.cond_expr); | 2238 | break :c try expr(mod, &continue_scope.base, .{ .ty = bool_type }, while_full.ast.cond_expr); |
| 2064 | } | 2239 | } |
| 2065 | }; | 2240 | }; |
| 2066 | | 2241 | |
| ... | @@ -2128,7 +2303,7 @@ fn whileExpr( | ... | @@ -2128,7 +2303,7 @@ fn whileExpr( |
| 2128 | }; | 2303 | }; |
| 2129 | defer else_scope.instructions.deinit(mod.gpa); | 2304 | defer else_scope.instructions.deinit(mod.gpa); |
| 2130 | | 2305 | |
| 2131 | const else_node = if_full.ast.else_expr; | 2306 | const else_node = while_full.ast.else_expr; |
| 2132 | const else_info: struct { src: usize, result: ?*zir.Inst } = if (else_node != 0) blk: { | 2307 | const else_info: struct { src: usize, result: ?*zir.Inst } = if (else_node != 0) blk: { |
| 2133 | loop_scope.break_count += 1; | 2308 | loop_scope.break_count += 1; |
| 2134 | const sub_scope = &else_scope.base; | 2309 | const sub_scope = &else_scope.base; |
| ... | @@ -2138,7 +2313,7 @@ fn whileExpr( | ... | @@ -2138,7 +2313,7 @@ fn whileExpr( |
| 2138 | }; | 2313 | }; |
| 2139 | } else | 2314 | } else |
| 2140 | .{ | 2315 | .{ |
| 2141 | .src = token_starts[tree.lastToken(then_node)], | 2316 | .src = token_starts[tree.lastToken(while_full.ast.then_expr)], |
| 2142 | .result = null, | 2317 | .result = null, |
| 2143 | }; | 2318 | }; |
| 2144 | | 2319 | |
| ... | @@ -2181,8 +2356,10 @@ fn forExpr( | ... | @@ -2181,8 +2356,10 @@ fn forExpr( |
| 2181 | | 2356 | |
| 2182 | // Set up variables and constants. | 2357 | // Set up variables and constants. |
| 2183 | const tree = scope.tree(); | 2358 | const tree = scope.tree(); |
| 2184 | const node_datas = tree.nodes.items(.data); | | |
| 2185 | const main_tokens = tree.nodes.items(.main_token); | 2359 | const main_tokens = tree.nodes.items(.main_token); |
| | 2360 | const token_starts = tree.tokens.items(.start); |
| | 2361 | const token_tags = tree.tokens.items(.tag); |
| | 2362 | |
| 2186 | const for_src = token_starts[for_full.ast.while_token]; | 2363 | const for_src = token_starts[for_full.ast.while_token]; |
| 2187 | const index_ptr = blk: { | 2364 | const index_ptr = blk: { |
| 2188 | const usize_type = try addZIRInstConst(mod, scope, for_src, .{ | 2365 | const usize_type = try addZIRInstConst(mod, scope, for_src, .{ |
| ... | @@ -2299,7 +2476,7 @@ fn forExpr( | ... | @@ -2299,7 +2476,7 @@ fn forExpr( |
| 2299 | else | 2476 | else |
| 2300 | break :blk &then_scope.base; | 2477 | break :blk &then_scope.base; |
| 2301 | if (mem.eql(u8, tree.tokenSlice(index_token), "_")) { | 2478 | if (mem.eql(u8, tree.tokenSlice(index_token), "_")) { |
| 2302 | return mod.failTok(&then_scope.base, index_token, "discard of index capture not allowed; omit it instead", .{}); | 2479 | return mod.failTok(&then_scope.base, index_token, "discard of index capture; omit it instead", .{}); |
| 2303 | } | 2480 | } |
| 2304 | const index_name = try mod.identifierTokenString(&then_scope.base, index_token); | 2481 | const index_name = try mod.identifierTokenString(&then_scope.base, index_token); |
| 2305 | index_scope = .{ | 2482 | index_scope = .{ |
| ... | @@ -2334,7 +2511,7 @@ fn forExpr( | ... | @@ -2334,7 +2511,7 @@ fn forExpr( |
| 2334 | }; | 2511 | }; |
| 2335 | } else | 2512 | } else |
| 2336 | .{ | 2513 | .{ |
| 2337 | .src = token_starts[tree.lastToken(then_node)], | 2514 | .src = token_starts[tree.lastToken(for_full.ast.then_expr)], |
| 2338 | .result = null, | 2515 | .result = null, |
| 2339 | }; | 2516 | }; |
| 2340 | | 2517 | |
| ... | @@ -2386,10 +2563,12 @@ fn switchExpr( | ... | @@ -2386,10 +2563,12 @@ fn switchExpr( |
| 2386 | const node_datas = tree.nodes.items(.data); | 2563 | const node_datas = tree.nodes.items(.data); |
| 2387 | const main_tokens = tree.nodes.items(.main_token); | 2564 | const main_tokens = tree.nodes.items(.main_token); |
| 2388 | const token_tags = tree.tokens.items(.tag); | 2565 | const token_tags = tree.tokens.items(.tag); |
| | 2566 | const token_starts = tree.tokens.items(.start); |
| | 2567 | const node_tags = tree.nodes.items(.tag); |
| 2389 | | 2568 | |
| 2390 | const switch_token = main_tokens[switch_node]; | 2569 | const switch_token = main_tokens[switch_node]; |
| 2391 | const target_node = datas[switch_node].lhs; | 2570 | const target_node = node_datas[switch_node].lhs; |
| 2392 | const extra = tree.extraData(datas[switch_node].rhs, ast.switch_node.SubRange); | 2571 | const extra = tree.extraData(node_datas[switch_node].rhs, ast.Node.SubRange); |
| 2393 | const case_nodes = tree.extra_data[extra.start..extra.end]; | 2572 | const case_nodes = tree.extra_data[extra.start..extra.end]; |
| 2394 | | 2573 | |
| 2395 | const switch_src = token_starts[switch_token]; | 2574 | const switch_src = token_starts[switch_token]; |
| ... | @@ -2552,7 +2731,7 @@ fn switchExpr( | ... | @@ -2552,7 +2731,7 @@ fn switchExpr( |
| 2552 | defer else_scope.instructions.deinit(mod.gpa); | 2731 | defer else_scope.instructions.deinit(mod.gpa); |
| 2553 | | 2732 | |
| 2554 | // Now generate all but the special cases. | 2733 | // Now generate all but the special cases. |
| 2555 | var special_case: ?ast.Node.Index = null; | 2734 | var special_case: ?ast.full.SwitchCase = null; |
| 2556 | var items_index: usize = 0; | 2735 | var items_index: usize = 0; |
| 2557 | var case_index: usize = 0; | 2736 | var case_index: usize = 0; |
| 2558 | for (case_nodes) |case_node| { | 2737 | for (case_nodes) |case_node| { |
| ... | @@ -2582,7 +2761,7 @@ fn switchExpr( | ... | @@ -2582,7 +2761,7 @@ fn switchExpr( |
| 2582 | { | 2761 | { |
| 2583 | const item = items.items[items_index]; | 2762 | const item = items.items[items_index]; |
| 2584 | items_index += 1; | 2763 | items_index += 1; |
| 2585 | try switchCaseExpr(mod, &case_scope.base, block_scope.break_result_loc, block, case, target, target_ptr); | 2764 | try switchCaseExpr(mod, &case_scope.base, block_scope.break_result_loc, block, case, target); |
| 2586 | | 2765 | |
| 2587 | cases[case_index] = .{ | 2766 | cases[case_index] = .{ |
| 2588 | .item = item, | 2767 | .item = item, |
| ... | @@ -2638,7 +2817,7 @@ fn switchExpr( | ... | @@ -2638,7 +2817,7 @@ fn switchExpr( |
| 2638 | | 2817 | |
| 2639 | // reset cond_scope for then_body | 2818 | // reset cond_scope for then_body |
| 2640 | case_scope.instructions.items.len = 0; | 2819 | case_scope.instructions.items.len = 0; |
| 2641 | try switchCaseExpr(mod, &case_scope.base, block_scope.break_result_loc, block, case, target, target_ptr); | 2820 | try switchCaseExpr(mod, &case_scope.base, block_scope.break_result_loc, block, case, target); |
| 2642 | condbr.positionals.then_body = .{ | 2821 | condbr.positionals.then_body = .{ |
| 2643 | .instructions = try scope.arena().dupe(*zir.Inst, case_scope.instructions.items), | 2822 | .instructions = try scope.arena().dupe(*zir.Inst, case_scope.instructions.items), |
| 2644 | }; | 2823 | }; |
| ... | @@ -2655,7 +2834,7 @@ fn switchExpr( | ... | @@ -2655,7 +2834,7 @@ fn switchExpr( |
| 2655 | | 2834 | |
| 2656 | // Finally generate else block or a break. | 2835 | // Finally generate else block or a break. |
| 2657 | if (special_case) |case| { | 2836 | if (special_case) |case| { |
| 2658 | try switchCaseExpr(mod, &else_scope.base, block_scope.break_result_loc, block, case, target, target_ptr); | 2837 | try switchCaseExpr(mod, &else_scope.base, block_scope.break_result_loc, block, case, target); |
| 2659 | } else { | 2838 | } else { |
| 2660 | // Not handling all possible cases is a compile error. | 2839 | // Not handling all possible cases is a compile error. |
| 2661 | _ = try addZIRNoOp(mod, &else_scope.base, switch_src, .unreachable_unsafe); | 2840 | _ = try addZIRNoOp(mod, &else_scope.base, switch_src, .unreachable_unsafe); |
| ... | @@ -2674,11 +2853,13 @@ fn switchCaseExpr( | ... | @@ -2674,11 +2853,13 @@ fn switchCaseExpr( |
| 2674 | block: *zir.Inst.Block, | 2853 | block: *zir.Inst.Block, |
| 2675 | case: ast.full.SwitchCase, | 2854 | case: ast.full.SwitchCase, |
| 2676 | target: *zir.Inst, | 2855 | target: *zir.Inst, |
| 2677 | target_ptr: ?*zir.Inst, | | |
| 2678 | ) !void { | 2856 | ) !void { |
| 2679 | const tree = scope.tree(); | 2857 | const tree = scope.tree(); |
| 2680 | const node_datas = tree.nodes.items(.data); | 2858 | const node_datas = tree.nodes.items(.data); |
| 2681 | const main_tokens = tree.nodes.items(.main_token); | 2859 | const main_tokens = tree.nodes.items(.main_token); |
| | 2860 | const token_starts = tree.tokens.items(.start); |
| | 2861 | const token_tags = tree.tokens.items(.tag); |
| | 2862 | |
| 2682 | const case_src = token_starts[case.ast.arrow_token]; | 2863 | const case_src = token_starts[case.ast.arrow_token]; |
| 2683 | const sub_scope = blk: { | 2864 | const sub_scope = blk: { |
| 2684 | const payload_token = case.payload_token orelse break :blk scope; | 2865 | const payload_token = case.payload_token orelse break :blk scope; |
| ... | @@ -2690,11 +2871,11 @@ fn switchCaseExpr( | ... | @@ -2690,11 +2871,11 @@ fn switchCaseExpr( |
| 2690 | const value_name = tree.tokenSlice(ident); | 2871 | const value_name = tree.tokenSlice(ident); |
| 2691 | if (mem.eql(u8, value_name, "_")) { | 2872 | if (mem.eql(u8, value_name, "_")) { |
| 2692 | if (is_ptr) { | 2873 | if (is_ptr) { |
| 2693 | return mod.failTok(scope, payload.ptr_token.?, "pointer modifier invalid on discard", .{}); | 2874 | return mod.failTok(scope, payload_token, "pointer modifier invalid on discard", .{}); |
| 2694 | } | 2875 | } |
| 2695 | break :blk scope; | 2876 | break :blk scope; |
| 2696 | } | 2877 | } |
| 2697 | return mod.failNode(scope, payload.value_symbol, "TODO implement switch value payload", .{}); | 2878 | return mod.failTok(scope, ident, "TODO implement switch value payload", .{}); |
| 2698 | }; | 2879 | }; |
| 2699 | | 2880 | |
| 2700 | const case_body = try expr(mod, sub_scope, rl, case.ast.target_expr); | 2881 | const case_body = try expr(mod, sub_scope, rl, case.ast.target_expr); |
| ... | @@ -2710,10 +2891,12 @@ fn ret(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.Inst { | ... | @@ -2710,10 +2891,12 @@ fn ret(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.Inst { |
| 2710 | const tree = scope.tree(); | 2891 | const tree = scope.tree(); |
| 2711 | const node_datas = tree.nodes.items(.data); | 2892 | const node_datas = tree.nodes.items(.data); |
| 2712 | const main_tokens = tree.nodes.items(.main_token); | 2893 | const main_tokens = tree.nodes.items(.main_token); |
| | 2894 | const token_starts = tree.tokens.items(.start); |
| | 2895 | |
| 2713 | const src = token_starts[main_tokens[node]]; | 2896 | const src = token_starts[main_tokens[node]]; |
| 2714 | const rhs_node = node_datas[node].lhs; | 2897 | const rhs_node = node_datas[node].lhs; |
| 2715 | if (rhs_node != 0) { | 2898 | if (rhs_node != 0) { |
| 2716 | if (nodeMayNeedMemoryLocation(rhs_node, scope)) { | 2899 | if (nodeMayNeedMemoryLocation(scope, rhs_node)) { |
| 2717 | const ret_ptr = try addZIRNoOp(mod, scope, src, .ret_ptr); | 2900 | const ret_ptr = try addZIRNoOp(mod, scope, src, .ret_ptr); |
| 2718 | const operand = try expr(mod, scope, .{ .ptr = ret_ptr }, rhs_node); | 2901 | const operand = try expr(mod, scope, .{ .ptr = ret_ptr }, rhs_node); |
| 2719 | return addZIRUnOp(mod, scope, src, .@"return", operand); | 2902 | return addZIRUnOp(mod, scope, src, .@"return", operand); |
| ... | @@ -2737,8 +2920,8 @@ fn identifier( | ... | @@ -2737,8 +2920,8 @@ fn identifier( |
| 2737 | defer tracy.end(); | 2920 | defer tracy.end(); |
| 2738 | | 2921 | |
| 2739 | const tree = scope.tree(); | 2922 | const tree = scope.tree(); |
| 2740 | const node_datas = tree.nodes.items(.data); | | |
| 2741 | const main_tokens = tree.nodes.items(.main_token); | 2923 | const main_tokens = tree.nodes.items(.main_token); |
| | 2924 | const token_starts = tree.tokens.items(.start); |
| 2742 | | 2925 | |
| 2743 | const ident_token = main_tokens[ident]; | 2926 | const ident_token = main_tokens[ident]; |
| 2744 | const ident_name = try mod.identifierTokenString(scope, ident_token); | 2927 | const ident_name = try mod.identifierTokenString(scope, ident_token); |
| ... | @@ -2826,6 +3009,27 @@ fn identifier( | ... | @@ -2826,6 +3009,27 @@ fn identifier( |
| 2826 | return mod.failNode(scope, ident, "use of undeclared identifier '{s}'", .{ident_name}); | 3009 | return mod.failNode(scope, ident, "use of undeclared identifier '{s}'", .{ident_name}); |
| 2827 | } | 3010 | } |
| 2828 | | 3011 | |
| | 3012 | fn parseStringLiteral(mod: *Module, scope: *Scope, token: ast.TokenIndex) ![]u8 { |
| | 3013 | const tree = scope.tree(); |
| | 3014 | const token_tags = tree.tokens.items(.tag); |
| | 3015 | const token_starts = tree.tokens.items(.start); |
| | 3016 | assert(token_tags[token] == .string_literal); |
| | 3017 | const unparsed = tree.tokenSlice(token); |
| | 3018 | const arena = scope.arena(); |
| | 3019 | var bad_index: usize = undefined; |
| | 3020 | const bytes = std.zig.parseStringLiteral(arena, unparsed, &bad_index) catch |err| switch (err) { |
| | 3021 | error.InvalidCharacter => { |
| | 3022 | const bad_byte = unparsed[bad_index]; |
| | 3023 | const src = token_starts[token]; |
| | 3024 | return mod.fail(scope, src + bad_index, "invalid string literal character: '{c}'", .{ |
| | 3025 | bad_byte, |
| | 3026 | }); |
| | 3027 | }, |
| | 3028 | else => |e| return e, |
| | 3029 | }; |
| | 3030 | return bytes; |
| | 3031 | } |
| | 3032 | |
| 2829 | fn stringLiteral( | 3033 | fn stringLiteral( |
| 2830 | mod: *Module, | 3034 | mod: *Module, |
| 2831 | scope: *Scope, | 3035 | scope: *Scope, |
| ... | @@ -2833,23 +3037,11 @@ fn stringLiteral( | ... | @@ -2833,23 +3037,11 @@ fn stringLiteral( |
| 2833 | str_lit: ast.Node.Index, | 3037 | str_lit: ast.Node.Index, |
| 2834 | ) InnerError!*zir.Inst { | 3038 | ) InnerError!*zir.Inst { |
| 2835 | const tree = scope.tree(); | 3039 | const tree = scope.tree(); |
| 2836 | const node_datas = tree.nodes.items(.data); | | |
| 2837 | const main_tokens = tree.nodes.items(.main_token); | 3040 | const main_tokens = tree.nodes.items(.main_token); |
| | 3041 | const token_starts = tree.tokens.items(.start); |
| 2838 | | 3042 | |
| 2839 | const str_lit_token = main_tokens[str_lit]; | 3043 | const str_lit_token = main_tokens[str_lit]; |
| 2840 | const unparsed_bytes = tree.tokenSlice(str_lit_token); | 3044 | const bytes = try parseStringLiteral(mod, scope, str_lit_token); |
| 2841 | const arena = scope.arena(); | | |
| 2842 | | | |
| 2843 | var bad_index: usize = undefined; | | |
| 2844 | const bytes = std.zig.parseStringLiteral(arena, unparsed_bytes, &bad_index) catch |err| switch (err) { | | |
| 2845 | error.InvalidCharacter => { | | |
| 2846 | const bad_byte = unparsed_bytes[bad_index]; | | |
| 2847 | const src = token_starts[str_lit_token]; | | |
| 2848 | return mod.fail(scope, src + bad_index, "invalid string literal character: '{c}'\n", .{bad_byte}); | | |
| 2849 | }, | | |
| 2850 | else => |e| return e, | | |
| 2851 | }; | | |
| 2852 | | | |
| 2853 | const src = token_starts[str_lit_token]; | 3045 | const src = token_starts[str_lit_token]; |
| 2854 | const str_inst = try addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{}); | 3046 | const str_inst = try addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{}); |
| 2855 | return rvalue(mod, scope, rl, str_inst); | 3047 | return rvalue(mod, scope, rl, str_inst); |
| ... | @@ -2864,9 +3056,10 @@ fn multilineStringLiteral( | ... | @@ -2864,9 +3056,10 @@ fn multilineStringLiteral( |
| 2864 | const tree = scope.tree(); | 3056 | const tree = scope.tree(); |
| 2865 | const node_datas = tree.nodes.items(.data); | 3057 | const node_datas = tree.nodes.items(.data); |
| 2866 | const main_tokens = tree.nodes.items(.main_token); | 3058 | const main_tokens = tree.nodes.items(.main_token); |
| | 3059 | const token_starts = tree.tokens.items(.start); |
| 2867 | | 3060 | |
| 2868 | const start = node_datas[node].lhs; | 3061 | const start = node_datas[str_lit].lhs; |
| 2869 | const end = node_datas[node].rhs; | 3062 | const end = node_datas[str_lit].rhs; |
| 2870 | | 3063 | |
| 2871 | // Count the number of bytes to allocate. | 3064 | // Count the number of bytes to allocate. |
| 2872 | const len: usize = len: { | 3065 | const len: usize = len: { |
| ... | @@ -2905,9 +3098,10 @@ fn multilineStringLiteral( | ... | @@ -2905,9 +3098,10 @@ fn multilineStringLiteral( |
| 2905 | | 3098 | |
| 2906 | fn charLiteral(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !*zir.Inst { | 3099 | fn charLiteral(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !*zir.Inst { |
| 2907 | const tree = scope.tree(); | 3100 | const tree = scope.tree(); |
| 2908 | const node_datas = tree.nodes.items(.data); | | |
| 2909 | const main_tokens = tree.nodes.items(.main_token); | 3101 | const main_tokens = tree.nodes.items(.main_token); |
| 2910 | const main_token = main_tokens[node]; | 3102 | const main_token = main_tokens[node]; |
| | 3103 | const token_starts = tree.tokens.items(.start); |
| | 3104 | |
| 2911 | const src = token_starts[main_token]; | 3105 | const src = token_starts[main_token]; |
| 2912 | const slice = tree.tokenSlice(main_token); | 3106 | const slice = tree.tokenSlice(main_token); |
| 2913 | | 3107 | |
| ... | @@ -2934,6 +3128,7 @@ fn integerLiteral( | ... | @@ -2934,6 +3128,7 @@ fn integerLiteral( |
| 2934 | const arena = scope.arena(); | 3128 | const arena = scope.arena(); |
| 2935 | const tree = scope.tree(); | 3129 | const tree = scope.tree(); |
| 2936 | const main_tokens = tree.nodes.items(.main_token); | 3130 | const main_tokens = tree.nodes.items(.main_token); |
| | 3131 | const token_starts = tree.tokens.items(.start); |
| 2937 | | 3132 | |
| 2938 | const int_token = main_tokens[int_lit]; | 3133 | const int_token = main_tokens[int_lit]; |
| 2939 | const prefixed_bytes = tree.tokenSlice(int_token); | 3134 | const prefixed_bytes = tree.tokenSlice(int_token); |
| ... | @@ -2972,6 +3167,8 @@ fn floatLiteral( | ... | @@ -2972,6 +3167,8 @@ fn floatLiteral( |
| 2972 | const arena = scope.arena(); | 3167 | const arena = scope.arena(); |
| 2973 | const tree = scope.tree(); | 3168 | const tree = scope.tree(); |
| 2974 | const main_tokens = tree.nodes.items(.main_token); | 3169 | const main_tokens = tree.nodes.items(.main_token); |
| | 3170 | const token_starts = tree.tokens.items(.start); |
| | 3171 | |
| 2975 | const main_token = main_tokens[float_lit]; | 3172 | const main_token = main_tokens[float_lit]; |
| 2976 | const bytes = tree.tokenSlice(main_token); | 3173 | const bytes = tree.tokenSlice(main_token); |
| 2977 | if (bytes.len > 2 and bytes[1] == 'x') { | 3174 | if (bytes.len > 2 and bytes[1] == 'x') { |
| ... | @@ -2988,17 +3185,18 @@ fn floatLiteral( | ... | @@ -2988,17 +3185,18 @@ fn floatLiteral( |
| 2988 | return rvalue(mod, scope, rl, result); | 3185 | return rvalue(mod, scope, rl, result); |
| 2989 | } | 3186 | } |
| 2990 | | 3187 | |
| 2991 | fn assembly(mod: *Module, scope: *Scope, rl: ResultLoc, full: ast.full.Asm) InnerError!*zir.Inst { | 3188 | fn asmExpr(mod: *Module, scope: *Scope, rl: ResultLoc, full: ast.full.Asm) InnerError!*zir.Inst { |
| 2992 | const arena = scope.arena(); | 3189 | const arena = scope.arena(); |
| 2993 | const tree = scope.tree(); | 3190 | const tree = scope.tree(); |
| 2994 | const node_datas = tree.nodes.items(.data); | | |
| 2995 | const main_tokens = tree.nodes.items(.main_token); | 3191 | const main_tokens = tree.nodes.items(.main_token); |
| | 3192 | const token_starts = tree.tokens.items(.start); |
| | 3193 | const node_datas = tree.nodes.items(.data); |
| 2996 | | 3194 | |
| 2997 | if (full.outputs.len != 0) { | 3195 | if (full.outputs.len != 0) { |
| 2998 | return mod.failTok(scope, full.ast.asm_token, "TODO implement asm with an output", .{}); | 3196 | return mod.failTok(scope, full.ast.asm_token, "TODO implement asm with an output", .{}); |
| 2999 | } | 3197 | } |
| 3000 | | 3198 | |
| 3001 | const inputs = try arena.alloc(*zir.Inst, full.inputs.len); | 3199 | const inputs = try arena.alloc([]const u8, full.inputs.len); |
| 3002 | const args = try arena.alloc(*zir.Inst, full.inputs.len); | 3200 | const args = try arena.alloc(*zir.Inst, full.inputs.len); |
| 3003 | | 3201 | |
| 3004 | const src = token_starts[full.ast.asm_token]; | 3202 | const src = token_starts[full.ast.asm_token]; |
| ... | @@ -3010,15 +3208,16 @@ fn assembly(mod: *Module, scope: *Scope, rl: ResultLoc, full: ast.full.Asm) Inne | ... | @@ -3010,15 +3208,16 @@ fn assembly(mod: *Module, scope: *Scope, rl: ResultLoc, full: ast.full.Asm) Inne |
| 3010 | | 3208 | |
| 3011 | for (full.inputs) |input, i| { | 3209 | for (full.inputs) |input, i| { |
| 3012 | // TODO semantically analyze constraints | 3210 | // TODO semantically analyze constraints |
| 3013 | inputs[i] = try expr(mod, scope, str_type_rl, input.constraint); | 3211 | const constraint_token = main_tokens[input] + 2; |
| 3014 | args[i] = try expr(mod, scope, .none, input.expr); | 3212 | inputs[i] = try parseStringLiteral(mod, scope, constraint_token); |
| | 3213 | args[i] = try expr(mod, scope, .none, node_datas[input].lhs); |
| 3015 | } | 3214 | } |
| 3016 | | 3215 | |
| 3017 | const return_type = try addZIRInstConst(mod, scope, src, .{ | 3216 | const return_type = try addZIRInstConst(mod, scope, src, .{ |
| 3018 | .ty = Type.initTag(.type), | 3217 | .ty = Type.initTag(.type), |
| 3019 | .val = Value.initTag(.void_type), | 3218 | .val = Value.initTag(.void_type), |
| 3020 | }); | 3219 | }); |
| 3021 | const asm_inst = try addZIRInst(mod, scope, src, zir.Inst.@"asm", .{ | 3220 | const asm_inst = try addZIRInst(mod, scope, src, zir.Inst.Asm, .{ |
| 3022 | .asm_source = try expr(mod, scope, str_type_rl, full.ast.template), | 3221 | .asm_source = try expr(mod, scope, str_type_rl, full.ast.template), |
| 3023 | .return_type = return_type, | 3222 | .return_type = return_type, |
| 3024 | }, .{ | 3223 | }, .{ |
| ... | @@ -3185,8 +3384,9 @@ fn builtinCall( | ... | @@ -3185,8 +3384,9 @@ fn builtinCall( |
| 3185 | params: []const ast.Node.Index, | 3384 | params: []const ast.Node.Index, |
| 3186 | ) InnerError!*zir.Inst { | 3385 | ) InnerError!*zir.Inst { |
| 3187 | const tree = scope.tree(); | 3386 | const tree = scope.tree(); |
| 3188 | const node_datas = tree.nodes.items(.data); | | |
| 3189 | const main_tokens = tree.nodes.items(.main_token); | 3387 | const main_tokens = tree.nodes.items(.main_token); |
| | 3388 | const token_starts = tree.tokens.items(.start); |
| | 3389 | |
| 3190 | const builtin_token = main_tokens[call]; | 3390 | const builtin_token = main_tokens[call]; |
| 3191 | const builtin_name = tree.tokenSlice(builtin_token); | 3391 | const builtin_name = tree.tokenSlice(builtin_token); |
| 3192 | | 3392 | |
| ... | @@ -3200,11 +3400,13 @@ fn builtinCall( | ... | @@ -3200,11 +3400,13 @@ fn builtinCall( |
| 3200 | builtin_name, | 3400 | builtin_name, |
| 3201 | }); | 3401 | }); |
| 3202 | }; | 3402 | }; |
| 3203 | if (info.param_count != params.len) { | 3403 | if (info.param_count) |expected| { |
| 3204 | const s = if (params.len == 1) "" else "s"; | 3404 | if (expected != params.len) { |
| 3205 | return mod.failTok(scope, builtin_token, "expected {d} parameter{s}, found {d}", .{ | 3405 | const s = if (expected == 1) "" else "s"; |
| 3206 | expected, s, found, | 3406 | return mod.failTok(scope, builtin_token, "expected {d} parameter{s}, found {d}", .{ |
| 3207 | }); | 3407 | expected, s, params.len, |
| | 3408 | }); |
| | 3409 | } |
| 3208 | } | 3410 | } |
| 3209 | const src = token_starts[builtin_token]; | 3411 | const src = token_starts[builtin_token]; |
| 3210 | | 3412 | |
| ... | @@ -3237,7 +3439,7 @@ fn builtinCall( | ... | @@ -3237,7 +3439,7 @@ fn builtinCall( |
| 3237 | }, | 3439 | }, |
| 3238 | .compile_error => { | 3440 | .compile_error => { |
| 3239 | const target = try expr(mod, scope, .none, params[0]); | 3441 | const target = try expr(mod, scope, .none, params[0]); |
| 3240 | const result = addZIRUnOp(mod, scope, src, .compile_error, target); | 3442 | const result = try addZIRUnOp(mod, scope, src, .compile_error, target); |
| 3241 | return rvalue(mod, scope, rl, result); | 3443 | return rvalue(mod, scope, rl, result); |
| 3242 | }, | 3444 | }, |
| 3243 | .set_eval_branch_quota => { | 3445 | .set_eval_branch_quota => { |
| ... | @@ -3386,8 +3588,9 @@ fn callExpr( | ... | @@ -3386,8 +3588,9 @@ fn callExpr( |
| 3386 | } | 3588 | } |
| 3387 | | 3589 | |
| 3388 | const tree = scope.tree(); | 3590 | const tree = scope.tree(); |
| 3389 | const node_datas = tree.nodes.items(.data); | | |
| 3390 | const main_tokens = tree.nodes.items(.main_token); | 3591 | const main_tokens = tree.nodes.items(.main_token); |
| | 3592 | const token_starts = tree.tokens.items(.start); |
| | 3593 | |
| 3391 | const lhs = try expr(mod, scope, .none, call.ast.fn_expr); | 3594 | const lhs = try expr(mod, scope, .none, call.ast.fn_expr); |
| 3392 | | 3595 | |
| 3393 | const args = try scope.getGenZIR().arena.alloc(*zir.Inst, call.ast.params.len); | 3596 | const args = try scope.getGenZIR().arena.alloc(*zir.Inst, call.ast.params.len); |
| ... | @@ -3446,23 +3649,26 @@ fn getSimplePrimitiveValue(name: []const u8) ?TypedValue { | ... | @@ -3446,23 +3649,26 @@ fn getSimplePrimitiveValue(name: []const u8) ?TypedValue { |
| 3446 | return null; | 3649 | return null; |
| 3447 | } | 3650 | } |
| 3448 | | 3651 | |
| 3449 | fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { | 3652 | fn nodeMayNeedMemoryLocation(scope: *Scope, start_node: ast.Node.Index) bool { |
| | 3653 | const tree = scope.tree(); |
| | 3654 | const node_tags = tree.nodes.items(.tag); |
| | 3655 | const node_datas = tree.nodes.items(.data); |
| | 3656 | const main_tokens = tree.nodes.items(.main_token); |
| | 3657 | const token_tags = tree.tokens.items(.tag); |
| | 3658 | |
| 3450 | var node = start_node; | 3659 | var node = start_node; |
| 3451 | while (true) { | 3660 | while (true) { |
| 3452 | switch (node.tag) { | 3661 | switch (node_tags[node]) { |
| 3453 | .Root, | 3662 | .root, |
| 3454 | .@"usingnamespace", | 3663 | .@"usingnamespace", |
| 3455 | .test_decl, | 3664 | .test_decl, |
| 3456 | .doc_comment, | | |
| 3457 | .switch_case, | 3665 | .switch_case, |
| 3458 | .switch_else, | 3666 | .switch_case_one, |
| 3459 | .Else, | 3667 | .container_field_init, |
| 3460 | .Payload, | 3668 | .container_field_align, |
| 3461 | .PointerPayload, | 3669 | .container_field, |
| 3462 | .PointerIndexPayload, | 3670 | .asm_output, |
| 3463 | .ContainerField, | 3671 | .asm_input, |
| 3464 | .ErrorTag, | | |
| 3465 | .FieldInitializer, | | |
| 3466 | => unreachable, | 3672 | => unreachable, |
| 3467 | | 3673 | |
| 3468 | .@"return", | 3674 | .@"return", |
| ... | @@ -3470,8 +3676,12 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { | ... | @@ -3470,8 +3676,12 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { |
| 3470 | .@"continue", | 3676 | .@"continue", |
| 3471 | .bit_not, | 3677 | .bit_not, |
| 3472 | .bool_not, | 3678 | .bool_not, |
| 3473 | .var_decl, | 3679 | .global_var_decl, |
| | 3680 | .local_var_decl, |
| | 3681 | .simple_var_decl, |
| | 3682 | .aligned_var_decl, |
| 3474 | .@"defer", | 3683 | .@"defer", |
| | 3684 | .@"errdefer", |
| 3475 | .address_of, | 3685 | .address_of, |
| 3476 | .optional_type, | 3686 | .optional_type, |
| 3477 | .negation, | 3687 | .negation, |
| ... | @@ -3479,27 +3689,46 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { | ... | @@ -3479,27 +3689,46 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { |
| 3479 | .@"resume", | 3689 | .@"resume", |
| 3480 | .array_type, | 3690 | .array_type, |
| 3481 | .array_type_sentinel, | 3691 | .array_type_sentinel, |
| 3482 | .PtrType, | 3692 | .ptr_type_aligned, |
| 3483 | .slice_type, | 3693 | .ptr_type_sentinel, |
| | 3694 | .ptr_type, |
| | 3695 | .ptr_type_bit_range, |
| 3484 | .@"suspend", | 3696 | .@"suspend", |
| 3485 | .@"anytype", | 3697 | .@"anytype", |
| 3486 | .error_type, | 3698 | .fn_proto_simple, |
| 3487 | .FnProto, | 3699 | .fn_proto_multi, |
| | 3700 | .fn_proto_one, |
| | 3701 | .fn_proto, |
| | 3702 | .fn_decl, |
| 3488 | .anyframe_type, | 3703 | .anyframe_type, |
| | 3704 | .anyframe_literal, |
| 3489 | .integer_literal, | 3705 | .integer_literal, |
| 3490 | .float_literal, | 3706 | .float_literal, |
| 3491 | .enum_literal, | 3707 | .enum_literal, |
| 3492 | .string_literal, | 3708 | .string_literal, |
| 3493 | .MultilineStringLiteral, | 3709 | .multiline_string_literal, |
| 3494 | .char_literal, | 3710 | .char_literal, |
| 3495 | .bool_literal, | 3711 | .true_literal, |
| | 3712 | .false_literal, |
| 3496 | .null_literal, | 3713 | .null_literal, |
| 3497 | .undefined_literal, | 3714 | .undefined_literal, |
| 3498 | .@"unreachable", | 3715 | .unreachable_literal, |
| 3499 | .identifier, | 3716 | .identifier, |
| 3500 | .error_set_decl, | 3717 | .error_set_decl, |
| 3501 | .ContainerDecl, | 3718 | .container_decl, |
| | 3719 | .container_decl_comma, |
| | 3720 | .container_decl_two, |
| | 3721 | .container_decl_two_comma, |
| | 3722 | .container_decl_arg, |
| | 3723 | .container_decl_arg_comma, |
| | 3724 | .tagged_union, |
| | 3725 | .tagged_union_comma, |
| | 3726 | .tagged_union_two, |
| | 3727 | .tagged_union_two_comma, |
| | 3728 | .tagged_union_enum_tag, |
| | 3729 | .tagged_union_enum_tag_comma, |
| 3502 | .@"asm", | 3730 | .@"asm", |
| | 3731 | .asm_simple, |
| 3503 | .add, | 3732 | .add, |
| 3504 | .add_wrap, | 3733 | .add_wrap, |
| 3505 | .array_cat, | 3734 | .array_cat, |
| ... | @@ -3537,14 +3766,16 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { | ... | @@ -3537,14 +3766,16 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { |
| 3537 | .mod, | 3766 | .mod, |
| 3538 | .mul, | 3767 | .mul, |
| 3539 | .mul_wrap, | 3768 | .mul_wrap, |
| 3540 | .range, | 3769 | .switch_range, |
| 3541 | .period, | 3770 | .field_access, |
| 3542 | .sub, | 3771 | .sub, |
| 3543 | .sub_wrap, | 3772 | .sub_wrap, |
| 3544 | .slice, | 3773 | .slice, |
| | 3774 | .slice_open, |
| | 3775 | .slice_sentinel, |
| 3545 | .deref, | 3776 | .deref, |
| 3546 | .array_access, | 3777 | .array_access, |
| 3547 | .block, | 3778 | .error_value, |
| 3548 | .while_simple, // This variant cannot have an else expression. | 3779 | .while_simple, // This variant cannot have an else expression. |
| 3549 | .while_cont, // This variant cannot have an else expression. | 3780 | .while_cont, // This variant cannot have an else expression. |
| 3550 | .for_simple, // This variant cannot have an else expression. | 3781 | .for_simple, // This variant cannot have an else expression. |
| ... | @@ -3558,18 +3789,30 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { | ... | @@ -3558,18 +3789,30 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { |
| 3558 | .@"comptime", | 3789 | .@"comptime", |
| 3559 | .@"nosuspend", | 3790 | .@"nosuspend", |
| 3560 | .unwrap_optional, | 3791 | .unwrap_optional, |
| 3561 | => node = datas[node].lhs, | 3792 | => node = node_datas[node].lhs, |
| 3562 | | 3793 | |
| 3563 | // Forward the question to the RHS sub-expression. | 3794 | // Forward the question to the RHS sub-expression. |
| 3564 | .@"catch", | 3795 | .@"catch", |
| 3565 | .@"orelse", | 3796 | .@"orelse", |
| 3566 | => node = datas[node].rhs, | 3797 | => node = node_datas[node].rhs, |
| 3567 | | 3798 | |
| 3568 | // True because these are exactly the expressions we need memory locations for. | 3799 | // True because these are exactly the expressions we need memory locations for. |
| 3569 | .ArrayInitializer, | 3800 | .array_init_one, |
| 3570 | .ArrayInitializerDot, | 3801 | .array_init_one_comma, |
| 3571 | .StructInitializer, | 3802 | .array_init_dot_two, |
| 3572 | .StructInitializerDot, | 3803 | .array_init_dot_two_comma, |
| | 3804 | .array_init_dot, |
| | 3805 | .array_init_dot_comma, |
| | 3806 | .array_init, |
| | 3807 | .array_init_comma, |
| | 3808 | .struct_init_one, |
| | 3809 | .struct_init_one_comma, |
| | 3810 | .struct_init_dot_two, |
| | 3811 | .struct_init_dot_two_comma, |
| | 3812 | .struct_init_dot, |
| | 3813 | .struct_init_dot_comma, |
| | 3814 | .struct_init, |
| | 3815 | .struct_init_comma, |
| 3573 | => return true, | 3816 | => return true, |
| 3574 | | 3817 | |
| 3575 | // True because depending on comptime conditions, sub-expressions | 3818 | // True because depending on comptime conditions, sub-expressions |
| ... | @@ -3578,6 +3821,7 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { | ... | @@ -3578,6 +3821,7 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { |
| 3578 | .@"if", // This variant always has an else expression. | 3821 | .@"if", // This variant always has an else expression. |
| 3579 | .@"for", // This variant always has an else expression. | 3822 | .@"for", // This variant always has an else expression. |
| 3580 | .@"switch", | 3823 | .@"switch", |
| | 3824 | .switch_comma, |
| 3581 | .call_one, | 3825 | .call_one, |
| 3582 | .call_one_comma, | 3826 | .call_one_comma, |
| 3583 | .async_call_one, | 3827 | .async_call_one, |
| ... | @@ -3588,10 +3832,10 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { | ... | @@ -3588,10 +3832,10 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { |
| 3588 | .async_call_comma, | 3832 | .async_call_comma, |
| 3589 | => return true, | 3833 | => return true, |
| 3590 | | 3834 | |
| 3591 | block_two, | 3835 | .block_two, |
| 3592 | block_two_semicolon, | 3836 | .block_two_semicolon, |
| 3593 | block, | 3837 | .block, |
| 3594 | block_semicolon, | 3838 | .block_semicolon, |
| 3595 | => { | 3839 | => { |
| 3596 | const lbrace = main_tokens[node]; | 3840 | const lbrace = main_tokens[node]; |
| 3597 | if (token_tags[lbrace - 1] == .colon) { | 3841 | if (token_tags[lbrace - 1] == .colon) { |
| ... | @@ -3603,7 +3847,11 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { | ... | @@ -3603,7 +3847,11 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool { |
| 3603 | } | 3847 | } |
| 3604 | }, | 3848 | }, |
| 3605 | | 3849 | |
| 3606 | .builtin_call => { | 3850 | .builtin_call, |
| | 3851 | .builtin_call_comma, |
| | 3852 | .builtin_call_two, |
| | 3853 | .builtin_call_two_comma, |
| | 3854 | => { |
| 3607 | const builtin_token = main_tokens[node]; | 3855 | const builtin_token = main_tokens[node]; |
| 3608 | const builtin_name = tree.tokenSlice(builtin_token); | 3856 | const builtin_name = tree.tokenSlice(builtin_token); |
| 3609 | // If the builtin is an invalid name, we don't cause an error here; instead | 3857 | // If the builtin is an invalid name, we don't cause an error here; instead |
| ... | @@ -3661,7 +3909,6 @@ fn rvalueVoid( | ... | @@ -3661,7 +3909,6 @@ fn rvalueVoid( |
| 3661 | result: void, | 3909 | result: void, |
| 3662 | ) InnerError!*zir.Inst { | 3910 | ) InnerError!*zir.Inst { |
| 3663 | const tree = scope.tree(); | 3911 | const tree = scope.tree(); |
| 3664 | const node_datas = tree.nodes.items(.data); | | |
| 3665 | const main_tokens = tree.nodes.items(.main_token); | 3912 | const main_tokens = tree.nodes.items(.main_token); |
| 3666 | const src = tree.tokens.items(.start)[tree.firstToken(node)]; | 3913 | const src = tree.tokens.items(.start)[tree.firstToken(node)]; |
| 3667 | const void_inst = try addZIRInstConst(mod, scope, src, .{ | 3914 | const void_inst = try addZIRInstConst(mod, scope, src, .{ |
| ... | @@ -3765,7 +4012,7 @@ pub fn addZirInstT( | ... | @@ -3765,7 +4012,7 @@ pub fn addZirInstT( |
| 3765 | src: usize, | 4012 | src: usize, |
| 3766 | comptime T: type, | 4013 | comptime T: type, |
| 3767 | tag: zir.Inst.Tag, | 4014 | tag: zir.Inst.Tag, |
| 3768 | positionals: std.meta.fieldInfo(tag.Type(), .positionals).field_type, | 4015 | positionals: std.meta.fieldInfo(T, .positionals).field_type, |
| 3769 | ) !*T { | 4016 | ) !*T { |
| 3770 | const gen_zir = scope.getGenZIR(); | 4017 | const gen_zir = scope.getGenZIR(); |
| 3771 | try gen_zir.instructions.ensureCapacity(mod.gpa, gen_zir.instructions.items.len + 1); | 4018 | try gen_zir.instructions.ensureCapacity(mod.gpa, gen_zir.instructions.items.len + 1); |