From 83fa216c8d2375476ee02ccf53bf6b5a9ed7480e Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Tue, 27 Sep 2022 15:32:34 +0300 Subject: Sema: implement `inline else` for ints --- src/Sema.zig | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) (limited to 'src/Sema.zig') diff --git a/src/Sema.zig b/src/Sema.zig index 08deb31714..3a3dc5f6ec 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -10414,7 +10414,41 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError } }, .Int => { - return sema.fail(block, special_prong_src, "TODO 'inline else' Int", .{}); + var it = try RangeSetUnhandledIterator.init(sema, block, special_prong_src, operand_ty, range_set); + var emit_bb = false; + while (try it.next()) |cur| { + cases_len += 1; + + const item_ref = try sema.addConstant(operand_ty, cur); + case_block.inline_case_capture = item_ref; + + case_block.instructions.shrinkRetainingCapacity(0); + case_block.wip_capture_scope = child_block.wip_capture_scope; + + if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); + emit_bb = true; + + _ = sema.analyzeBodyInner(&case_block, special.body) catch |err| switch (err) { + error.ComptimeBreak => { + const zir_datas = sema.code.instructions.items(.data); + const break_data = zir_datas[sema.comptime_break_inst].@"break"; + try sema.addRuntimeBreak(&case_block, .{ + .block_inst = break_data.block_inst, + .operand = break_data.operand, + .inst = sema.comptime_break_inst, + }); + }, + else => |e| return e, + }; + + // try wip_captures.finalize(); + + try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); + cases_extra.appendAssumeCapacity(1); // items_len + cases_extra.appendAssumeCapacity(@intCast(u32, case_block.instructions.items.len)); + cases_extra.appendAssumeCapacity(@enumToInt(item_ref)); + cases_extra.appendSliceAssumeCapacity(case_block.instructions.items); + } }, .Bool => { var emit_bb = false; @@ -10561,6 +10595,55 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError return sema.analyzeBlockBody(block, src, &child_block, merges); } +const RangeSetUnhandledIterator = struct { + sema: *Sema, + block: *Block, + src: LazySrcLoc, + ty: Type, + cur: Value, + max: Value, + ranges: []const RangeSet.Range, + range_i: usize = 0, + first: bool = true, + + fn init(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type, range_set: RangeSet) !RangeSetUnhandledIterator { + const target = sema.mod.getTarget(); + const min = try ty.minInt(sema.arena, target); + const max = try ty.maxInt(sema.arena, target); + + return RangeSetUnhandledIterator{ + .sema = sema, + .block = block, + .src = src, + .ty = ty, + .cur = min, + .max = max, + .ranges = range_set.ranges.items, + }; + } + + fn next(it: *RangeSetUnhandledIterator) !?Value { + while (it.range_i < it.ranges.len) : (it.range_i += 1) { + if (!it.first) { + it.cur = try it.sema.intAdd(it.block, it.src, it.cur, Value.one, it.ty); + } + it.first = false; + if (it.cur.compare(.lt, it.ranges[it.range_i].first, it.ty, it.sema.mod)) { + return it.cur; + } + it.cur = it.ranges[it.range_i].last; + } + if (!it.first) { + it.cur = try it.sema.intAdd(it.block, it.src, it.cur, Value.one, it.ty); + } + it.first = false; + if (it.cur.compare(.lte, it.max, it.ty, it.sema.mod)) { + return it.cur; + } + return null; + } +}; + fn resolveSwitchItemVal( sema: *Sema, block: *Block, -- cgit v1.2.3