authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-09-15 00:00:11+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-15 11:42:08-07:00
logf366d9f8793fc297e581321fbbd6242089f07440
treed6254129a206accbdc10e615689e658f80e05c58
parentded628e4fae41e0816c30b5c93f56b44f0e23a41

compiler: start using destructure syntax


2 files changed, 74 insertions(+), 108 deletions(-)

src/AstGen.zig+28-46
...@@ -1392,14 +1392,8 @@ fn arrayInitExpr(...@@ -1392,14 +1392,8 @@ fn arrayInitExpr(
13921392
1393 assert(array_init.ast.elements.len != 0); // Otherwise it would be struct init.1393 assert(array_init.ast.elements.len != 0); // Otherwise it would be struct init.
13941394
1395 const types: struct {1395 const array_ty: Zir.Inst.Ref, const elem_ty: Zir.Inst.Ref = inst: {
1396 array: Zir.Inst.Ref,1396 if (array_init.ast.type_expr == 0) break :inst .{ .none, .none };
1397 elem: Zir.Inst.Ref,
1398 } = inst: {
1399 if (array_init.ast.type_expr == 0) break :inst .{
1400 .array = .none,
1401 .elem = .none,
1402 };
14031397
1404 infer: {1398 infer: {
1405 const array_type: Ast.full.ArrayType = tree.fullArrayType(array_init.ast.type_expr) orelse break :infer;1399 const array_type: Ast.full.ArrayType = tree.fullArrayType(array_init.ast.type_expr) orelse break :infer;
...@@ -1414,10 +1408,7 @@ fn arrayInitExpr(...@@ -1414,10 +1408,7 @@ fn arrayInitExpr(
1414 .lhs = len_inst,1408 .lhs = len_inst,
1415 .rhs = elem_type,1409 .rhs = elem_type,
1416 });1410 });
1417 break :inst .{1411 break :inst .{ array_type_inst, elem_type };
1418 .array = array_type_inst,
1419 .elem = elem_type,
1420 };
1421 } else {1412 } else {
1422 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel);1413 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel);
1423 const array_type_inst = try gz.addPlNode(1414 const array_type_inst = try gz.addPlNode(
...@@ -1429,10 +1420,7 @@ fn arrayInitExpr(...@@ -1429,10 +1420,7 @@ fn arrayInitExpr(
1429 .sentinel = sentinel,1420 .sentinel = sentinel,
1430 },1421 },
1431 );1422 );
1432 break :inst .{1423 break :inst .{ array_type_inst, elem_type };
1433 .array = array_type_inst,
1434 .elem = elem_type,
1435 };
1436 }1424 }
1437 }1425 }
1438 }1426 }
...@@ -1441,29 +1429,26 @@ fn arrayInitExpr(...@@ -1441,29 +1429,26 @@ fn arrayInitExpr(
1441 .ty = array_type_inst,1429 .ty = array_type_inst,
1442 .init_count = @intCast(array_init.ast.elements.len),1430 .init_count = @intCast(array_init.ast.elements.len),
1443 });1431 });
1444 break :inst .{1432 break :inst .{ array_type_inst, .none };
1445 .array = array_type_inst,
1446 .elem = .none,
1447 };
1448 };1433 };
14491434
1450 switch (ri.rl) {1435 switch (ri.rl) {
1451 .discard => {1436 .discard => {
1452 if (types.elem != .none) {1437 if (elem_ty != .none) {
1453 const elem_ri: ResultInfo = .{ .rl = .{ .ty = types.elem } };1438 const elem_ri: ResultInfo = .{ .rl = .{ .ty = elem_ty } };
1454 for (array_init.ast.elements) |elem_init| {1439 for (array_init.ast.elements) |elem_init| {
1455 _ = try expr(gz, scope, elem_ri, elem_init);1440 _ = try expr(gz, scope, elem_ri, elem_init);
1456 }1441 }
1457 } else if (types.array != .none) {1442 } else if (array_ty != .none) {
1458 for (array_init.ast.elements, 0..) |elem_init, i| {1443 for (array_init.ast.elements, 0..) |elem_init, i| {
1459 const elem_ty = try gz.add(.{1444 const this_elem_ty = try gz.add(.{
1460 .tag = .elem_type_index,1445 .tag = .elem_type_index,
1461 .data = .{ .bin = .{1446 .data = .{ .bin = .{
1462 .lhs = types.array,1447 .lhs = array_ty,
1463 .rhs = @enumFromInt(i),1448 .rhs = @enumFromInt(i),
1464 } },1449 } },
1465 });1450 });
1466 _ = try expr(gz, scope, .{ .rl = .{ .ty = elem_ty } }, elem_init);1451 _ = try expr(gz, scope, .{ .rl = .{ .ty = this_elem_ty } }, elem_init);
1467 }1452 }
1468 } else {1453 } else {
1469 for (array_init.ast.elements) |elem_init| {1454 for (array_init.ast.elements) |elem_init| {
...@@ -1473,15 +1458,15 @@ fn arrayInitExpr(...@@ -1473,15 +1458,15 @@ fn arrayInitExpr(
1473 return Zir.Inst.Ref.void_value;1458 return Zir.Inst.Ref.void_value;
1474 },1459 },
1475 .ref => {1460 .ref => {
1476 const tag: Zir.Inst.Tag = if (types.array != .none) .array_init_ref else .array_init_anon_ref;1461 const tag: Zir.Inst.Tag = if (array_ty != .none) .array_init_ref else .array_init_anon_ref;
1477 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);1462 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, elem_ty, tag);
1478 },1463 },
1479 .none => {1464 .none => {
1480 const tag: Zir.Inst.Tag = if (types.array != .none) .array_init else .array_init_anon;1465 const tag: Zir.Inst.Tag = if (array_ty != .none) .array_init else .array_init_anon;
1481 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);1466 return arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, elem_ty, tag);
1482 },1467 },
1483 .ty, .coerced_ty => |ty_inst| {1468 .ty, .coerced_ty => |ty_inst| {
1484 const arr_ty = if (types.array != .none) types.array else blk: {1469 const arr_ty = if (array_ty != .none) array_ty else blk: {
1485 const arr_ty = try gz.addUnNode(.opt_eu_base_ty, ty_inst, node);1470 const arr_ty = try gz.addUnNode(.opt_eu_base_ty, ty_inst, node);
1486 _ = try gz.addPlNode(.validate_array_init_ty, node, Zir.Inst.ArrayInit{1471 _ = try gz.addPlNode(.validate_array_init_ty, node, Zir.Inst.ArrayInit{
1487 .ty = arr_ty,1472 .ty = arr_ty,
...@@ -1489,29 +1474,29 @@ fn arrayInitExpr(...@@ -1489,29 +1474,29 @@ fn arrayInitExpr(
1489 });1474 });
1490 break :blk arr_ty;1475 break :blk arr_ty;
1491 };1476 };
1492 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, arr_ty, types.elem, .array_init);1477 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, arr_ty, elem_ty, .array_init);
1493 return rvalue(gz, ri, result, node);1478 return rvalue(gz, ri, result, node);
1494 },1479 },
1495 .ptr => |ptr_res| {1480 .ptr => |ptr_res| {
1496 return arrayInitExprRlPtr(gz, scope, node, ptr_res.inst, array_init.ast.elements, types.array);1481 return arrayInitExprRlPtr(gz, scope, node, ptr_res.inst, array_init.ast.elements, array_ty);
1497 },1482 },
1498 .inferred_ptr => |ptr_inst| {1483 .inferred_ptr => |ptr_inst| {
1499 if (types.array == .none) {1484 if (array_ty == .none) {
1500 // We treat this case differently so that we don't get a crash when1485 // We treat this case differently so that we don't get a crash when
1501 // analyzing array_base_ptr against an alloc_inferred_mut.1486 // analyzing array_base_ptr against an alloc_inferred_mut.
1502 // See corresponding logic in structInitExpr.1487 // See corresponding logic in structInitExpr.
1503 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);1488 const result = try arrayInitExprRlNone(gz, scope, node, array_init.ast.elements, .array_init_anon);
1504 return rvalue(gz, ri, result, node);1489 return rvalue(gz, ri, result, node);
1505 } else {1490 } else {
1506 return arrayInitExprRlPtr(gz, scope, node, ptr_inst, array_init.ast.elements, types.array);1491 return arrayInitExprRlPtr(gz, scope, node, ptr_inst, array_init.ast.elements, array_ty);
1507 }1492 }
1508 },1493 },
1509 .destructure => |destructure| {1494 .destructure => |destructure| {
1510 if (types.array != .none) {1495 if (array_ty != .none) {
1511 // We have a specific type, so there may be things like default1496 // We have a specific type, so there may be things like default
1512 // field values messing with us. Do this as a standard typed1497 // field values messing with us. Do this as a standard typed
1513 // init followed by an rvalue destructure.1498 // init followed by an rvalue destructure.
1514 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, .array_init);1499 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, array_ty, elem_ty, .array_init);
1515 return rvalue(gz, ri, result, node);1500 return rvalue(gz, ri, result, node);
1516 }1501 }
1517 // Untyped init - destructure directly into result pointers1502 // Untyped init - destructure directly into result pointers
...@@ -3177,10 +3162,7 @@ fn varDecl(...@@ -3177,10 +3162,7 @@ fn varDecl(
3177 .keyword_var => {3162 .keyword_var => {
3178 const is_comptime = var_decl.comptime_token != null or gz.is_comptime;3163 const is_comptime = var_decl.comptime_token != null or gz.is_comptime;
3179 var resolve_inferred_alloc: Zir.Inst.Ref = .none;3164 var resolve_inferred_alloc: Zir.Inst.Ref = .none;
3180 const var_data: struct {3165 const alloc: Zir.Inst.Ref, const result_info: ResultInfo = if (var_decl.ast.type_node != 0) a: {
3181 result_info: ResultInfo,
3182 alloc: Zir.Inst.Ref,
3183 } = if (var_decl.ast.type_node != 0) a: {
3184 const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);3166 const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);
3185 const alloc = alloc: {3167 const alloc = alloc: {
3186 if (align_inst == .none) {3168 if (align_inst == .none) {
...@@ -3199,7 +3181,7 @@ fn varDecl(...@@ -3199,7 +3181,7 @@ fn varDecl(
3199 });3181 });
3200 }3182 }
3201 };3183 };
3202 break :a .{ .alloc = alloc, .result_info = .{ .rl = .{ .ptr = .{ .inst = alloc } } } };3184 break :a .{ alloc, .{ .rl = .{ .ptr = .{ .inst = alloc } } } };
3203 } else a: {3185 } else a: {
3204 const alloc = alloc: {3186 const alloc = alloc: {
3205 if (align_inst == .none) {3187 if (align_inst == .none) {
...@@ -3219,24 +3201,24 @@ fn varDecl(...@@ -3219,24 +3201,24 @@ fn varDecl(
3219 }3201 }
3220 };3202 };
3221 resolve_inferred_alloc = alloc;3203 resolve_inferred_alloc = alloc;
3222 break :a .{ .alloc = alloc, .result_info = .{ .rl = .{ .inferred_ptr = alloc } } };3204 break :a .{ alloc, .{ .rl = .{ .inferred_ptr = alloc } } };
3223 };3205 };
3224 const prev_anon_name_strategy = gz.anon_name_strategy;3206 const prev_anon_name_strategy = gz.anon_name_strategy;
3225 gz.anon_name_strategy = .dbg_var;3207 gz.anon_name_strategy = .dbg_var;
3226 _ = try reachableExprComptime(gz, scope, var_data.result_info, var_decl.ast.init_node, node, is_comptime);3208 _ = try reachableExprComptime(gz, scope, result_info, var_decl.ast.init_node, node, is_comptime);
3227 gz.anon_name_strategy = prev_anon_name_strategy;3209 gz.anon_name_strategy = prev_anon_name_strategy;
3228 if (resolve_inferred_alloc != .none) {3210 if (resolve_inferred_alloc != .none) {
3229 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);3211 _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node);
3230 }3212 }
32313213
3232 try gz.addDbgVar(.dbg_var_ptr, ident_name, var_data.alloc);3214 try gz.addDbgVar(.dbg_var_ptr, ident_name, alloc);
32333215
3234 const sub_scope = try block_arena.create(Scope.LocalPtr);3216 const sub_scope = try block_arena.create(Scope.LocalPtr);
3235 sub_scope.* = .{3217 sub_scope.* = .{
3236 .parent = scope,3218 .parent = scope,
3237 .gen_zir = gz,3219 .gen_zir = gz,
3238 .name = ident_name,3220 .name = ident_name,
3239 .ptr = var_data.alloc,3221 .ptr = alloc,
3240 .token_src = name_token,3222 .token_src = name_token,
3241 .maybe_comptime = is_comptime,3223 .maybe_comptime = is_comptime,
3242 .id_cat = .@"local variable",3224 .id_cat = .@"local variable",
src/Sema.zig+46-62
...@@ -11092,17 +11092,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -11092,17 +11092,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
11092 const special_prong_src: LazySrcLoc = .{ .node_offset_switch_special_prong = src_node_offset };11092 const special_prong_src: LazySrcLoc = .{ .node_offset_switch_special_prong = src_node_offset };
11093 const extra = sema.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index);11093 const extra = sema.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index);
1109411094
11095 const raw_operand: struct { val: Air.Inst.Ref, ptr: Air.Inst.Ref } = blk: {11095 const raw_operand_val: Air.Inst.Ref, const raw_operand_ptr: Air.Inst.Ref = blk: {
11096 const maybe_ptr = try sema.resolveInst(extra.data.operand);11096 const maybe_ptr = try sema.resolveInst(extra.data.operand);
11097 if (operand_is_ref) {11097 if (operand_is_ref) {
11098 const val = try sema.analyzeLoad(block, src, maybe_ptr, operand_src);11098 const val = try sema.analyzeLoad(block, src, maybe_ptr, operand_src);
11099 break :blk .{ .val = val, .ptr = maybe_ptr };11099 break :blk .{ val, maybe_ptr };
11100 } else {11100 } else {
11101 break :blk .{ .val = maybe_ptr, .ptr = undefined };11101 break :blk .{ maybe_ptr, undefined };
11102 }11102 }
11103 };11103 };
1110411104
11105 const operand = try sema.switchCond(block, operand_src, raw_operand.val);11105 const operand = try sema.switchCond(block, operand_src, raw_operand_val);
1110611106
11107 // AstGen guarantees that the instruction immediately preceding11107 // AstGen guarantees that the instruction immediately preceding
11108 // switch_block(_ref) is a dbg_stmt11108 // switch_block(_ref) is a dbg_stmt
...@@ -11160,7 +11160,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -11160,7 +11160,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
11160 },11160 },
11161 };11161 };
1116211162
11163 const maybe_union_ty = sema.typeOf(raw_operand.val);11163 const maybe_union_ty = sema.typeOf(raw_operand_val);
11164 const union_originally = maybe_union_ty.zigTypeTag(mod) == .Union;11164 const union_originally = maybe_union_ty.zigTypeTag(mod) == .Union;
1116511165
11166 // Duplicate checking variables later also used for `inline else`.11166 // Duplicate checking variables later also used for `inline else`.
...@@ -11711,8 +11711,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r...@@ -11711,8 +11711,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
11711 const spa: SwitchProngAnalysis = .{11711 const spa: SwitchProngAnalysis = .{
11712 .sema = sema,11712 .sema = sema,
11713 .parent_block = block,11713 .parent_block = block,
11714 .operand = raw_operand.val,11714 .operand = raw_operand_val,
11715 .operand_ptr = raw_operand.ptr,11715 .operand_ptr = raw_operand_ptr,
11716 .cond = operand,11716 .cond = operand,
11717 .else_error_ty = else_error_ty,11717 .else_error_ty = else_error_ty,
11718 .switch_block_inst = inst,11718 .switch_block_inst = inst,
...@@ -15500,11 +15500,7 @@ fn analyzeArithmetic(...@@ -15500,11 +15500,7 @@ fn analyzeArithmetic(
1550015500
15501 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);15501 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
15502 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);15502 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);
15503 const rs: struct {15503 const runtime_src: LazySrcLoc, const air_tag: Air.Inst.Tag, const air_tag_safe: Air.Inst.Tag = rs: {
15504 src: LazySrcLoc,
15505 air_tag: Air.Inst.Tag,
15506 air_tag_safe: Air.Inst.Tag,
15507 } = rs: {
15508 switch (zir_tag) {15504 switch (zir_tag) {
15509 .add, .add_unsafe => {15505 .add, .add_unsafe => {
15510 // For integers:intAddSat15506 // For integers:intAddSat
...@@ -15551,8 +15547,8 @@ fn analyzeArithmetic(...@@ -15551,8 +15547,8 @@ fn analyzeArithmetic(
15551 } else {15547 } else {
15552 return Air.internedToRef((try Value.floatAdd(lhs_val, rhs_val, resolved_type, sema.arena, mod)).toIntern());15548 return Air.internedToRef((try Value.floatAdd(lhs_val, rhs_val, resolved_type, sema.arena, mod)).toIntern());
15553 }15549 }
15554 } else break :rs .{ .src = rhs_src, .air_tag = air_tag, .air_tag_safe = .add_safe };15550 } else break :rs .{ rhs_src, air_tag, .add_safe };
15555 } else break :rs .{ .src = lhs_src, .air_tag = air_tag, .air_tag_safe = .add_safe };15551 } else break :rs .{ lhs_src, air_tag, .add_safe };
15556 },15552 },
15557 .addwrap => {15553 .addwrap => {
15558 // Integers only; floats are checked above.15554 // Integers only; floats are checked above.
...@@ -15572,8 +15568,8 @@ fn analyzeArithmetic(...@@ -15572,8 +15568,8 @@ fn analyzeArithmetic(
15572 }15568 }
15573 if (maybe_lhs_val) |lhs_val| {15569 if (maybe_lhs_val) |lhs_val| {
15574 return Air.internedToRef((try sema.numberAddWrapScalar(lhs_val, rhs_val, resolved_type)).toIntern());15570 return Air.internedToRef((try sema.numberAddWrapScalar(lhs_val, rhs_val, resolved_type)).toIntern());
15575 } else break :rs .{ .src = lhs_src, .air_tag = .add_wrap, .air_tag_safe = .add_wrap };15571 } else break :rs .{ lhs_src, .add_wrap, .add_wrap };
15576 } else break :rs .{ .src = rhs_src, .air_tag = .add_wrap, .air_tag_safe = .add_wrap };15572 } else break :rs .{ rhs_src, .add_wrap, .add_wrap };
15577 },15573 },
15578 .add_sat => {15574 .add_sat => {
15579 // Integers only; floats are checked above.15575 // Integers only; floats are checked above.
...@@ -15599,14 +15595,14 @@ fn analyzeArithmetic(...@@ -15599,14 +15595,14 @@ fn analyzeArithmetic(
1559915595
15600 return Air.internedToRef(val.toIntern());15596 return Air.internedToRef(val.toIntern());
15601 } else break :rs .{15597 } else break :rs .{
15602 .src = lhs_src,15598 lhs_src,
15603 .air_tag = .add_sat,15599 .add_sat,
15604 .air_tag_safe = .add_sat,15600 .add_sat,
15605 };15601 };
15606 } else break :rs .{15602 } else break :rs .{
15607 .src = rhs_src,15603 rhs_src,
15608 .air_tag = .add_sat,15604 .add_sat,
15609 .air_tag_safe = .add_sat,15605 .add_sat,
15610 };15606 };
15611 },15607 },
15612 .sub => {15608 .sub => {
...@@ -15649,8 +15645,8 @@ fn analyzeArithmetic(...@@ -15649,8 +15645,8 @@ fn analyzeArithmetic(
15649 } else {15645 } else {
15650 return Air.internedToRef((try Value.floatSub(lhs_val, rhs_val, resolved_type, sema.arena, mod)).toIntern());15646 return Air.internedToRef((try Value.floatSub(lhs_val, rhs_val, resolved_type, sema.arena, mod)).toIntern());
15651 }15647 }
15652 } else break :rs .{ .src = rhs_src, .air_tag = air_tag, .air_tag_safe = .sub_safe };15648 } else break :rs .{ rhs_src, air_tag, .sub_safe };
15653 } else break :rs .{ .src = lhs_src, .air_tag = air_tag, .air_tag_safe = .sub_safe };15649 } else break :rs .{ lhs_src, air_tag, .sub_safe };
15654 },15650 },
15655 .subwrap => {15651 .subwrap => {
15656 // Integers only; floats are checked above.15652 // Integers only; floats are checked above.
...@@ -15670,8 +15666,8 @@ fn analyzeArithmetic(...@@ -15670,8 +15666,8 @@ fn analyzeArithmetic(
15670 }15666 }
15671 if (maybe_rhs_val) |rhs_val| {15667 if (maybe_rhs_val) |rhs_val| {
15672 return Air.internedToRef((try sema.numberSubWrapScalar(lhs_val, rhs_val, resolved_type)).toIntern());15668 return Air.internedToRef((try sema.numberSubWrapScalar(lhs_val, rhs_val, resolved_type)).toIntern());
15673 } else break :rs .{ .src = rhs_src, .air_tag = .sub_wrap, .air_tag_safe = .sub_wrap };15669 } else break :rs .{ rhs_src, .sub_wrap, .sub_wrap };
15674 } else break :rs .{ .src = lhs_src, .air_tag = .sub_wrap, .air_tag_safe = .sub_wrap };15670 } else break :rs .{ lhs_src, .sub_wrap, .sub_wrap };
15675 },15671 },
15676 .sub_sat => {15672 .sub_sat => {
15677 // Integers only; floats are checked above.15673 // Integers only; floats are checked above.
...@@ -15696,8 +15692,8 @@ fn analyzeArithmetic(...@@ -15696,8 +15692,8 @@ fn analyzeArithmetic(
15696 try lhs_val.intSubSat(rhs_val, resolved_type, sema.arena, mod);15692 try lhs_val.intSubSat(rhs_val, resolved_type, sema.arena, mod);
1569715693
15698 return Air.internedToRef(val.toIntern());15694 return Air.internedToRef(val.toIntern());
15699 } else break :rs .{ .src = rhs_src, .air_tag = .sub_sat, .air_tag_safe = .sub_sat };15695 } else break :rs .{ rhs_src, .sub_sat, .sub_sat };
15700 } else break :rs .{ .src = lhs_src, .air_tag = .sub_sat, .air_tag_safe = .sub_sat };15696 } else break :rs .{ lhs_src, .sub_sat, .sub_sat };
15701 },15697 },
15702 .mul => {15698 .mul => {
15703 // For integers:15699 // For integers:
...@@ -15789,8 +15785,8 @@ fn analyzeArithmetic(...@@ -15789,8 +15785,8 @@ fn analyzeArithmetic(
15789 } else {15785 } else {
15790 return Air.internedToRef((try lhs_val.floatMul(rhs_val, resolved_type, sema.arena, mod)).toIntern());15786 return Air.internedToRef((try lhs_val.floatMul(rhs_val, resolved_type, sema.arena, mod)).toIntern());
15791 }15787 }
15792 } else break :rs .{ .src = lhs_src, .air_tag = air_tag, .air_tag_safe = .mul_safe };15788 } else break :rs .{ lhs_src, air_tag, .mul_safe };
15793 } else break :rs .{ .src = rhs_src, .air_tag = air_tag, .air_tag_safe = .mul_safe };15789 } else break :rs .{ rhs_src, air_tag, .mul_safe };
15794 },15790 },
15795 .mulwrap => {15791 .mulwrap => {
15796 // Integers only; floats are handled above.15792 // Integers only; floats are handled above.
...@@ -15834,8 +15830,8 @@ fn analyzeArithmetic(...@@ -15834,8 +15830,8 @@ fn analyzeArithmetic(
15834 return mod.undefRef(resolved_type);15830 return mod.undefRef(resolved_type);
15835 }15831 }
15836 return Air.internedToRef((try lhs_val.numberMulWrap(rhs_val, resolved_type, sema.arena, mod)).toIntern());15832 return Air.internedToRef((try lhs_val.numberMulWrap(rhs_val, resolved_type, sema.arena, mod)).toIntern());
15837 } else break :rs .{ .src = lhs_src, .air_tag = .mul_wrap, .air_tag_safe = .mul_wrap };15833 } else break :rs .{ lhs_src, .mul_wrap, .mul_wrap };
15838 } else break :rs .{ .src = rhs_src, .air_tag = .mul_wrap, .air_tag_safe = .mul_wrap };15834 } else break :rs .{ rhs_src, .mul_wrap, .mul_wrap };
15839 },15835 },
15840 .mul_sat => {15836 .mul_sat => {
15841 // Integers only; floats are checked above.15837 // Integers only; floats are checked above.
...@@ -15885,20 +15881,20 @@ fn analyzeArithmetic(...@@ -15885,20 +15881,20 @@ fn analyzeArithmetic(
15885 try lhs_val.intMulSat(rhs_val, resolved_type, sema.arena, mod);15881 try lhs_val.intMulSat(rhs_val, resolved_type, sema.arena, mod);
1588615882
15887 return Air.internedToRef(val.toIntern());15883 return Air.internedToRef(val.toIntern());
15888 } else break :rs .{ .src = lhs_src, .air_tag = .mul_sat, .air_tag_safe = .mul_sat };15884 } else break :rs .{ lhs_src, .mul_sat, .mul_sat };
15889 } else break :rs .{ .src = rhs_src, .air_tag = .mul_sat, .air_tag_safe = .mul_sat };15885 } else break :rs .{ rhs_src, .mul_sat, .mul_sat };
15890 },15886 },
15891 else => unreachable,15887 else => unreachable,
15892 }15888 }
15893 };15889 };
1589415890
15895 try sema.requireRuntimeBlock(block, src, rs.src);15891 try sema.requireRuntimeBlock(block, src, runtime_src);
15896 if (block.wantSafety() and want_safety and scalar_tag == .Int) {15892 if (block.wantSafety() and want_safety and scalar_tag == .Int) {
15897 if (mod.backendSupportsFeature(.safety_checked_instructions)) {15893 if (mod.backendSupportsFeature(.safety_checked_instructions)) {
15898 _ = try sema.preparePanicId(block, .integer_overflow);15894 _ = try sema.preparePanicId(block, .integer_overflow);
15899 return block.addBinOp(rs.air_tag_safe, casted_lhs, casted_rhs);15895 return block.addBinOp(air_tag_safe, casted_lhs, casted_rhs);
15900 } else {15896 } else {
15901 const maybe_op_ov: ?Air.Inst.Tag = switch (rs.air_tag) {15897 const maybe_op_ov: ?Air.Inst.Tag = switch (air_tag) {
15902 .add => .add_with_overflow,15898 .add => .add_with_overflow,
15903 .sub => .sub_with_overflow,15899 .sub => .sub_with_overflow,
15904 .mul => .mul_with_overflow,15900 .mul => .mul_with_overflow,
...@@ -15935,7 +15931,7 @@ fn analyzeArithmetic(...@@ -15935,7 +15931,7 @@ fn analyzeArithmetic(
15935 }15931 }
15936 }15932 }
15937 }15933 }
15938 return block.addBinOp(rs.air_tag, casted_lhs, casted_rhs);15934 return block.addBinOp(air_tag, casted_lhs, casted_rhs);
15939}15935}
1594015936
15941fn analyzePtrArithmetic(15937fn analyzePtrArithmetic(
...@@ -32345,16 +32341,10 @@ fn compareIntsOnlyPossibleResult(...@@ -32345,16 +32341,10 @@ fn compareIntsOnlyPossibleResult(
3234532341
32346 // For any other comparison, we need to know if the LHS value is32342 // For any other comparison, we need to know if the LHS value is
32347 // equal to the maximum or minimum possible value of the RHS type.32343 // equal to the maximum or minimum possible value of the RHS type.
32348 const edge: struct { min: bool, max: bool } = edge: {32344 const is_min, const is_max = edge: {
32349 if (is_zero and rhs_info.signedness == .unsigned) break :edge .{32345 if (is_zero and rhs_info.signedness == .unsigned) break :edge .{ true, false };
32350 .min = true,
32351 .max = false,
32352 };
3235332346
32354 if (req_bits != rhs_info.bits) break :edge .{32347 if (req_bits != rhs_info.bits) break :edge .{ false, false };
32355 .min = false,
32356 .max = false,
32357 };
3235832348
32359 const ty = try mod.intType(32349 const ty = try mod.intType(
32360 if (is_negative) .signed else .unsigned,32350 if (is_negative) .signed else .unsigned,
...@@ -32363,24 +32353,18 @@ fn compareIntsOnlyPossibleResult(...@@ -32363,24 +32353,18 @@ fn compareIntsOnlyPossibleResult(
32363 const pop_count = lhs_val.popCount(ty, mod);32353 const pop_count = lhs_val.popCount(ty, mod);
3236432354
32365 if (is_negative) {32355 if (is_negative) {
32366 break :edge .{32356 break :edge .{ pop_count == 1, false };
32367 .min = pop_count == 1,
32368 .max = false,
32369 };
32370 } else {32357 } else {
32371 break :edge .{32358 break :edge .{ false, pop_count == req_bits - sign_adj };
32372 .min = false,
32373 .max = pop_count == req_bits - sign_adj,
32374 };
32375 }32359 }
32376 };32360 };
3237732361
32378 assert(fits);32362 assert(fits);
32379 return switch (op) {32363 return switch (op) {
32380 .lt => if (edge.max) false else null,32364 .lt => if (is_max) false else null,
32381 .lte => if (edge.min) true else null,32365 .lte => if (is_min) true else null,
32382 .gt => if (edge.min) false else null,32366 .gt => if (is_min) false else null,
32383 .gte => if (edge.max) true else null,32367 .gte => if (is_max) true else null,
32384 .eq, .neq => unreachable,32368 .eq, .neq => unreachable,
32385 };32369 };
32386}32370}
...@@ -32617,7 +32601,7 @@ const PeerResolveStrategy = enum {...@@ -32617,7 +32601,7 @@ const PeerResolveStrategy = enum {
32617 either,32601 either,
32618 };32602 };
3261932603
32620 const res: struct { ReasonMethod, PeerResolveStrategy } = switch (s0) {32604 const reason_method: ReasonMethod, const strat: PeerResolveStrategy = switch (s0) {
32621 .unknown => .{ .all_s1, s1 },32605 .unknown => .{ .all_s1, s1 },
32622 .error_set => switch (s1) {32606 .error_set => switch (s1) {
32623 .error_set => .{ .either, .error_set },32607 .error_set => .{ .either, .error_set },
...@@ -32685,7 +32669,7 @@ const PeerResolveStrategy = enum {...@@ -32685,7 +32669,7 @@ const PeerResolveStrategy = enum {
32685 .exact => .{ .all_s0, .exact },32669 .exact => .{ .all_s0, .exact },
32686 };32670 };
3268732671
32688 switch (res[0]) {32672 switch (reason_method) {
32689 .all_s0 => {32673 .all_s0 => {
32690 if (!s0_is_a) {32674 if (!s0_is_a) {
32691 reason_peer.* = b_peer_idx;32675 reason_peer.* = b_peer_idx;
...@@ -32702,7 +32686,7 @@ const PeerResolveStrategy = enum {...@@ -32702,7 +32686,7 @@ const PeerResolveStrategy = enum {
32702 },32686 },
32703 }32687 }
3270432688
32705 return res[1];32689 return strat;
32706 }32690 }
3270732691
32708 fn select(ty: Type, mod: *Module) PeerResolveStrategy {32692 fn select(ty: Type, mod: *Module) PeerResolveStrategy {