| ... | @@ -4170,159 +4170,201 @@ fn analyzeSwitch( | ... | @@ -4170,159 +4170,201 @@ fn analyzeSwitch( |
| 4170 | | 4170 | |
| 4171 | try sema.requireRuntimeBlock(block, src); | 4171 | try sema.requireRuntimeBlock(block, src); |
| 4172 | | 4172 | |
| 4173 | // TODO when reworking AIR memory layout make multi cases get generated as cases, | 4173 | var cases_extra: std.ArrayListUnmanaged(u32) = .{}; |
| 4174 | // not as part of the "else" block. | 4174 | defer cases_extra.deinit(gpa); |
| 4175 | return mod.fail(&block.base, src, "TODO rework runtime switch Sema", .{}); | | |
| 4176 | //const cases = try sema.arena.alloc(Inst.SwitchBr.Case, scalar_cases_len); | | |
| 4177 | | | |
| 4178 | //var case_block = child_block.makeSubBlock(); | | |
| 4179 | //case_block.runtime_loop = null; | | |
| 4180 | //case_block.runtime_cond = operand.src; | | |
| 4181 | //case_block.runtime_index += 1; | | |
| 4182 | //defer case_block.instructions.deinit(gpa); | | |
| 4183 | | | |
| 4184 | //var extra_index: usize = special.end; | | |
| 4185 | | | |
| 4186 | //var scalar_i: usize = 0; | | |
| 4187 | //while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | | |
| 4188 | // const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | | |
| 4189 | // extra_index += 1; | | |
| 4190 | // const body_len = sema.code.extra[extra_index]; | | |
| 4191 | // extra_index += 1; | | |
| 4192 | // const body = sema.code.extra[extra_index..][0..body_len]; | | |
| 4193 | // extra_index += body_len; | | |
| 4194 | | 4175 | |
| 4195 | // case_block.instructions.shrinkRetainingCapacity(0); | 4176 | try cases_extra.ensureTotalCapacity(gpa, (scalar_cases_len + multi_cases_len) * |
| 4196 | // const item = sema.resolveInst(item_ref); | 4177 | @typeInfo(Air.SwitchBr.Case).Struct.fields.len + 2); |
| 4197 | // // We validate these above; these two calls are guaranteed to succeed. | | |
| 4198 | // const item_val = sema.resolveConstValue(&case_block, .unneeded, item) catch unreachable; | | |
| 4199 | | 4178 | |
| 4200 | // _ = try sema.analyzeBody(&case_block, body); | 4179 | var case_block = child_block.makeSubBlock(); |
| | 4180 | case_block.runtime_loop = null; |
| | 4181 | case_block.runtime_cond = operand_src; |
| | 4182 | case_block.runtime_index += 1; |
| | 4183 | defer case_block.instructions.deinit(gpa); |
| 4201 | | 4184 | |
| 4202 | // cases[scalar_i] = .{ | 4185 | var extra_index: usize = special.end; |
| 4203 | // .item = item_val, | | |
| 4204 | // .body = .{ .instructions = try sema.arena.dupe(Air.Inst.Index, case_block.instructions.items) }, | | |
| 4205 | // }; | | |
| 4206 | //} | | |
| 4207 | | 4186 | |
| 4208 | //var first_else_body: Body = undefined; | 4187 | var scalar_i: usize = 0; |
| 4209 | //var prev_condbr: ?*Inst.CondBr = null; | 4188 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| | 4189 | const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| | 4190 | extra_index += 1; |
| | 4191 | const body_len = sema.code.extra[extra_index]; |
| | 4192 | extra_index += 1; |
| | 4193 | const body = sema.code.extra[extra_index..][0..body_len]; |
| | 4194 | extra_index += body_len; |
| 4210 | | 4195 | |
| 4211 | //var multi_i: usize = 0; | 4196 | case_block.instructions.shrinkRetainingCapacity(0); |
| 4212 | //while (multi_i < multi_cases_len) : (multi_i += 1) { | 4197 | const item = sema.resolveInst(item_ref); |
| 4213 | // const items_len = sema.code.extra[extra_index]; | 4198 | // `item` is already guaranteed to be constant known. |
| 4214 | // extra_index += 1; | 4199 | |
| 4215 | // const ranges_len = sema.code.extra[extra_index]; | 4200 | _ = try sema.analyzeBody(&case_block, body); |
| 4216 | // extra_index += 1; | 4201 | |
| 4217 | // const body_len = sema.code.extra[extra_index]; | 4202 | try cases_extra.ensureUnusedCapacity(gpa, 3 + case_block.instructions.items.len); |
| 4218 | // extra_index += 1; | 4203 | cases_extra.appendAssumeCapacity(1); // items_len |
| 4219 | // const items = sema.code.refSlice(extra_index, items_len); | 4204 | cases_extra.appendAssumeCapacity(@intCast(u32, case_block.instructions.items.len)); |
| 4220 | // extra_index += items_len; | 4205 | cases_extra.appendAssumeCapacity(@enumToInt(item)); |
| 4221 | | 4206 | cases_extra.appendSliceAssumeCapacity(case_block.instructions.items); |
| 4222 | // case_block.instructions.shrinkRetainingCapacity(0); | 4207 | } |
| 4223 | | 4208 | |
| 4224 | // var any_ok: ?Air.Inst.Index = null; | 4209 | var is_first = true; |
| 4225 | | 4210 | var prev_cond_br: Air.Inst.Index = undefined; |
| 4226 | // for (items) |item_ref| { | 4211 | var first_else_body: []const Air.Inst.Index = &.{}; |
| 4227 | // const item = sema.resolveInst(item_ref); | 4212 | defer gpa.free(first_else_body); |
| 4228 | // _ = try sema.resolveConstValue(&child_block, item.src, item); | 4213 | var prev_then_body: []const Air.Inst.Index = &.{}; |
| 4229 | | 4214 | defer gpa.free(prev_then_body); |
| 4230 | // const cmp_ok = try case_block.addBinOp(.cmp_eq, operand, item); | 4215 | |
| 4231 | // if (any_ok) |some| { | 4216 | var multi_i: usize = 0; |
| 4232 | // any_ok = try case_block.addBinOp(.bool_or, some, cmp_ok); | 4217 | while (multi_i < multi_cases_len) : (multi_i += 1) { |
| 4233 | // } else { | 4218 | const items_len = sema.code.extra[extra_index]; |
| 4234 | // any_ok = cmp_ok; | 4219 | extra_index += 1; |
| 4235 | // } | 4220 | const ranges_len = sema.code.extra[extra_index]; |
| 4236 | // } | 4221 | extra_index += 1; |
| 4237 | | 4222 | const body_len = sema.code.extra[extra_index]; |
| 4238 | // var range_i: usize = 0; | 4223 | extra_index += 1; |
| 4239 | // while (range_i < ranges_len) : (range_i += 1) { | 4224 | const items = sema.code.refSlice(extra_index, items_len); |
| 4240 | // const first_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 4225 | extra_index += items_len; |
| 4241 | // extra_index += 1; | 4226 | |
| 4242 | // const last_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 4227 | case_block.instructions.shrinkRetainingCapacity(0); |
| 4243 | // extra_index += 1; | 4228 | |
| 4244 | | 4229 | var any_ok: Air.Inst.Ref = .none; |
| 4245 | // const item_first = sema.resolveInst(first_ref); | 4230 | |
| 4246 | // const item_last = sema.resolveInst(last_ref); | 4231 | // If there are any ranges, we have to put all the items into the |
| 4247 | | 4232 | // else prong. Otherwise, we can take advantage of multiple items |
| 4248 | // _ = try sema.resolveConstValue(&child_block, item_first.src, item_first); | 4233 | // mapping to the same body. |
| 4249 | // _ = try sema.resolveConstValue(&child_block, item_last.src, item_last); | 4234 | if (ranges_len == 0) { |
| 4250 | | 4235 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 4251 | // // operand >= first and operand <= last | 4236 | extra_index += body_len; |
| 4252 | // const range_first_ok = try case_block.addBinOp( | 4237 | _ = try sema.analyzeBody(&case_block, body); |
| 4253 | // .cmp_gte, | 4238 | |
| 4254 | // operand, | 4239 | try cases_extra.ensureUnusedCapacity(gpa, 2 + items.len + |
| 4255 | // item_first, | 4240 | case_block.instructions.items.len); |
| 4256 | // ); | 4241 | |
| 4257 | // const range_last_ok = try case_block.addBinOp( | 4242 | cases_extra.appendAssumeCapacity(1); // items_len |
| 4258 | // .cmp_lte, | 4243 | cases_extra.appendAssumeCapacity(@intCast(u32, case_block.instructions.items.len)); |
| 4259 | // operand, | 4244 | |
| 4260 | // item_last, | 4245 | for (items) |item_ref| { |
| 4261 | // ); | 4246 | const item = sema.resolveInst(item_ref); |
| 4262 | // const range_ok = try case_block.addBinOp( | 4247 | cases_extra.appendAssumeCapacity(@enumToInt(item)); |
| 4263 | // .bool_and, | 4248 | } |
| 4264 | // range_first_ok, | 4249 | |
| 4265 | // range_last_ok, | 4250 | cases_extra.appendSliceAssumeCapacity(case_block.instructions.items); |
| 4266 | // ); | 4251 | } else { |
| 4267 | // if (any_ok) |some| { | 4252 | for (items) |item_ref| { |
| 4268 | // any_ok = try case_block.addBinOp(.bool_or, some, range_ok); | 4253 | const item = sema.resolveInst(item_ref); |
| 4269 | // } else { | 4254 | const cmp_ok = try case_block.addBinOp(.cmp_eq, operand, item); |
| 4270 | // any_ok = range_ok; | 4255 | if (any_ok != .none) { |
| 4271 | // } | 4256 | any_ok = try case_block.addBinOp(.bool_or, any_ok, cmp_ok); |
| 4272 | // } | 4257 | } else { |
| 4273 | | 4258 | any_ok = cmp_ok; |
| 4274 | // const new_condbr = try sema.arena.create(Inst.CondBr); | 4259 | } |
| 4275 | // new_condbr.* = .{ | 4260 | } |
| 4276 | // .base = .{ | 4261 | |
| 4277 | // .tag = .condbr, | 4262 | var range_i: usize = 0; |
| 4278 | // .ty = Type.initTag(.noreturn), | 4263 | while (range_i < ranges_len) : (range_i += 1) { |
| 4279 | // .src = src, | 4264 | const first_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 4280 | // }, | 4265 | extra_index += 1; |
| 4281 | // .condition = any_ok.?, | 4266 | const last_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 4282 | // .then_body = undefined, | 4267 | extra_index += 1; |
| 4283 | // .else_body = undefined, | 4268 | |
| 4284 | // }; | 4269 | const item_first = sema.resolveInst(first_ref); |
| 4285 | // try case_block.instructions.append(gpa, &new_condbr.base); | 4270 | const item_last = sema.resolveInst(last_ref); |
| 4286 | | 4271 | |
| 4287 | // const cond_body: Body = .{ | 4272 | // operand >= first and operand <= last |
| 4288 | // .instructions = try sema.arena.dupe(Air.Inst.Index, case_block.instructions.items), | 4273 | const range_first_ok = try case_block.addBinOp( |
| 4289 | // }; | 4274 | .cmp_gte, |
| 4290 | | 4275 | operand, |
| 4291 | // case_block.instructions.shrinkRetainingCapacity(0); | 4276 | item_first, |
| 4292 | // const body = sema.code.extra[extra_index..][0..body_len]; | 4277 | ); |
| 4293 | // extra_index += body_len; | 4278 | const range_last_ok = try case_block.addBinOp( |
| 4294 | // _ = try sema.analyzeBody(&case_block, body); | 4279 | .cmp_lte, |
| 4295 | // new_condbr.then_body = .{ | 4280 | operand, |
| 4296 | // .instructions = try sema.arena.dupe(Air.Inst.Index, case_block.instructions.items), | 4281 | item_last, |
| 4297 | // }; | 4282 | ); |
| 4298 | // if (prev_condbr) |condbr| { | 4283 | const range_ok = try case_block.addBinOp( |
| 4299 | // condbr.else_body = cond_body; | 4284 | .bool_and, |
| 4300 | // } else { | 4285 | range_first_ok, |
| 4301 | // first_else_body = cond_body; | 4286 | range_last_ok, |
| 4302 | // } | 4287 | ); |
| 4303 | // prev_condbr = new_condbr; | 4288 | if (any_ok != .none) { |
| 4304 | //} | 4289 | any_ok = try case_block.addBinOp(.bool_or, any_ok, range_ok); |
| 4305 | | 4290 | } else { |
| 4306 | //const final_else_body: Body = blk: { | 4291 | any_ok = range_ok; |
| 4307 | // if (special.body.len != 0) { | 4292 | } |
| 4308 | // case_block.instructions.shrinkRetainingCapacity(0); | 4293 | } |
| 4309 | // _ = try sema.analyzeBody(&case_block, special.body); | 4294 | |
| 4310 | // const else_body: Body = .{ | 4295 | const new_cond_br = try case_block.addInstAsIndex(.{ .tag = .cond_br, .data = .{ |
| 4311 | // .instructions = try sema.arena.dupe(Air.Inst.Index, case_block.instructions.items), | 4296 | .pl_op = .{ |
| 4312 | // }; | 4297 | .operand = any_ok, |
| 4313 | // if (prev_condbr) |condbr| { | 4298 | .payload = undefined, |
| 4314 | // condbr.else_body = else_body; | 4299 | }, |
| 4315 | // break :blk first_else_body; | 4300 | } }); |
| 4316 | // } else { | 4301 | var cond_body = case_block.instructions.toOwnedSlice(gpa); |
| 4317 | // break :blk else_body; | 4302 | defer gpa.free(cond_body); |
| 4318 | // } | 4303 | |
| 4319 | // } else { | 4304 | case_block.instructions.shrinkRetainingCapacity(0); |
| 4320 | // break :blk .{ .instructions = &.{} }; | 4305 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 4321 | // } | 4306 | extra_index += body_len; |
| 4322 | //}; | 4307 | _ = try sema.analyzeBody(&case_block, body); |
| 4323 | | 4308 | |
| 4324 | //_ = try child_block.addSwitchBr(src, operand, cases, final_else_body); | 4309 | if (is_first) { |
| 4325 | //return sema.analyzeBlockBody(block, src, &child_block, merges); | 4310 | is_first = false; |
| | 4311 | first_else_body = cond_body; |
| | 4312 | cond_body = &.{}; |
| | 4313 | } else { |
| | 4314 | try sema.air_extra.ensureUnusedCapacity( |
| | 4315 | gpa, |
| | 4316 | @typeInfo(Air.CondBr).Struct.fields.len + prev_then_body.len + cond_body.len, |
| | 4317 | ); |
| | 4318 | |
| | 4319 | sema.air_instructions.items(.data)[prev_cond_br].pl_op.payload = |
| | 4320 | sema.addExtraAssumeCapacity(Air.CondBr{ |
| | 4321 | .then_body_len = @intCast(u32, prev_then_body.len), |
| | 4322 | .else_body_len = @intCast(u32, cond_body.len), |
| | 4323 | }); |
| | 4324 | sema.air_extra.appendSliceAssumeCapacity(prev_then_body); |
| | 4325 | sema.air_extra.appendSliceAssumeCapacity(cond_body); |
| | 4326 | } |
| | 4327 | prev_then_body = case_block.instructions.toOwnedSlice(gpa); |
| | 4328 | prev_cond_br = new_cond_br; |
| | 4329 | } |
| | 4330 | } |
| | 4331 | |
| | 4332 | var final_else_body: []const Air.Inst.Index = &.{}; |
| | 4333 | if (special.body.len != 0) { |
| | 4334 | case_block.instructions.shrinkRetainingCapacity(0); |
| | 4335 | _ = try sema.analyzeBody(&case_block, special.body); |
| | 4336 | |
| | 4337 | if (is_first) { |
| | 4338 | final_else_body = case_block.instructions.items; |
| | 4339 | } else { |
| | 4340 | try sema.air_extra.ensureUnusedCapacity(gpa, prev_then_body.len + |
| | 4341 | @typeInfo(Air.CondBr).Struct.fields.len + case_block.instructions.items.len); |
| | 4342 | |
| | 4343 | sema.air_instructions.items(.data)[prev_cond_br].pl_op.payload = |
| | 4344 | sema.addExtraAssumeCapacity(Air.CondBr{ |
| | 4345 | .then_body_len = @intCast(u32, prev_then_body.len), |
| | 4346 | .else_body_len = @intCast(u32, case_block.instructions.items.len), |
| | 4347 | }); |
| | 4348 | sema.air_extra.appendSliceAssumeCapacity(prev_then_body); |
| | 4349 | sema.air_extra.appendSliceAssumeCapacity(case_block.instructions.items); |
| | 4350 | final_else_body = first_else_body; |
| | 4351 | } |
| | 4352 | } |
| | 4353 | |
| | 4354 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr).Struct.fields.len + |
| | 4355 | cases_extra.items.len); |
| | 4356 | |
| | 4357 | _ = try child_block.addInst(.{ .tag = .switch_br, .data = .{ .pl_op = .{ |
| | 4358 | .operand = operand, |
| | 4359 | .payload = sema.addExtraAssumeCapacity(Air.SwitchBr{ |
| | 4360 | .cases_len = @intCast(u32, scalar_cases_len + multi_cases_len), |
| | 4361 | .else_body_len = @intCast(u32, final_else_body.len), |
| | 4362 | }), |
| | 4363 | } } }); |
| | 4364 | sema.air_extra.appendSliceAssumeCapacity(cases_extra.items); |
| | 4365 | sema.air_extra.appendSliceAssumeCapacity(final_else_body); |
| | 4366 | |
| | 4367 | return sema.analyzeBlockBody(block, src, &child_block, merges); |
| 4326 | } | 4368 | } |
| 4327 | | 4369 | |
| 4328 | fn resolveSwitchItemVal( | 4370 | fn resolveSwitchItemVal( |