authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-05 16:56:24-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-05 16:56:24-07:00
log9b1aac8a654d1ee3515e2de8d477cf1909e63fdf
treebfd2fe07757b34890e712e4c60810350be0823af
parentc714a3250f57817ea565f0390cecf12025655376

stage2: mapping old to new ZIR recursively

now it walks into functions and blocks to find decls.

2 files changed, 152 insertions(+), 11 deletions(-)

src/Module.zig+36-11
...@@ -438,13 +438,24 @@ pub const Decl = struct {...@@ -438,13 +438,24 @@ pub const Decl = struct {
438438
439 /// If the Decl has a value and it is a struct, return it,439 /// If the Decl has a value and it is a struct, return it,
440 /// otherwise null.440 /// otherwise null.
441 pub fn getStruct(decl: Decl) ?*Struct {441 pub fn getStruct(decl: *Decl) ?*Struct {
442 if (!decl.has_tv) return null;442 if (!decl.has_tv) return null;
443 const ty = (decl.val.castTag(.ty) orelse return null).data;443 const ty = (decl.val.castTag(.ty) orelse return null).data;
444 const struct_obj = (ty.castTag(.@"struct") orelse return null).data;444 const struct_obj = (ty.castTag(.@"struct") orelse return null).data;
445 if (struct_obj.owner_decl != decl) return null;
445 return struct_obj;446 return struct_obj;
446 }447 }
447448
449 /// If the Decl has a value and it is a function, return it,
450 /// otherwise null.
451 pub fn getFunction(decl: *Decl) ?*Fn {
452 if (!decl.has_tv) return null;
453 if (decl.ty.zigTypeTag() != .Fn) return null;
454 const func = (decl.val.castTag(.function) orelse return null).data;
455 if (func.owner_decl != decl) return null;
456 return func;
457 }
458
448 pub fn dump(decl: *Decl) void {459 pub fn dump(decl: *Decl) void {
449 const loc = std.zig.findLineColumn(decl.scope.source.bytes, decl.src);460 const loc = std.zig.findLineColumn(decl.scope.source.bytes, decl.src);
450 std.debug.print("{s}:{d}:{d} name={s} status={s}", .{461 std.debug.print("{s}:{d}:{d} name={s} status={s}", .{
...@@ -2378,6 +2389,7 @@ const UpdateChangeList = struct {...@@ -2378,6 +2389,7 @@ const UpdateChangeList = struct {
23782389
2379/// Patch ups:2390/// Patch ups:
2380/// * Struct.zir_index2391/// * Struct.zir_index
2392/// * Fn.zir_body_inst
2381/// * Decl.zir_decl_index2393/// * Decl.zir_decl_index
2382/// * Decl.name2394/// * Decl.name
2383/// * Namespace.decl keys2395/// * Namespace.decl keys
...@@ -2454,6 +2466,13 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !UpdateChange...@@ -2454,6 +2466,13 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !UpdateChange
2454 };2466 };
2455 }2467 }
24562468
2469 if (decl.getFunction()) |func| {
2470 func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse {
2471 try deleted_decls.append(gpa, decl);
2472 continue;
2473 };
2474 }
2475
2457 if (decl.val.getTypeNamespace()) |namespace| {2476 if (decl.val.getTypeNamespace()) |namespace| {
2458 for (namespace.decls.items()) |*entry| {2477 for (namespace.decls.items()) |*entry| {
2459 const sub_decl = entry.value;2478 const sub_decl = entry.value;
...@@ -2503,6 +2522,11 @@ pub fn mapOldZirToNew(...@@ -2503,6 +2522,11 @@ pub fn mapOldZirToNew(
2503 .new_inst = new_main_struct_inst,2522 .new_inst = new_main_struct_inst,
2504 });2523 });
25052524
2525 var old_decls = std.ArrayList(Zir.Inst.Index).init(gpa);
2526 defer old_decls.deinit();
2527 var new_decls = std.ArrayList(Zir.Inst.Index).init(gpa);
2528 defer new_decls.deinit();
2529
2506 while (match_stack.popOrNull()) |match_item| {2530 while (match_stack.popOrNull()) |match_item| {
2507 try inst_map.put(gpa, match_item.old_inst, match_item.new_inst);2531 try inst_map.put(gpa, match_item.old_inst, match_item.new_inst);
25082532
...@@ -2523,16 +2547,17 @@ pub fn mapOldZirToNew(...@@ -2523,16 +2547,17 @@ pub fn mapOldZirToNew(
2523 const new_extra_index = new_decl.sub_index;2547 const new_extra_index = new_decl.sub_index;
2524 try extra_map.put(gpa, old_extra_index, new_extra_index);2548 try extra_map.put(gpa, old_extra_index, new_extra_index);
25252549
2526 //var old_it = declInstIterator(old_zir, old_extra_index);2550 try old_zir.findDecls(&old_decls, old_extra_index);
2527 //var new_it = declInstIterator(new_zir, new_extra_index);2551 try new_zir.findDecls(&new_decls, new_extra_index);
2528 //while (true) {2552 var i: usize = 0;
2529 // const old_decl_inst = old_it.next() orelse break;2553 while (true) : (i += 1) {
2530 // const new_decl_inst = new_it.next() orelse break;2554 if (i >= old_decls.items.len) break;
2531 // try match_stack.append(gpa, .{2555 if (i >= new_decls.items.len) break;
2532 // .old_inst = old_decl_inst,2556 try match_stack.append(gpa, .{
2533 // .new_inst = new_decl_inst,2557 .old_inst = old_decls.items[i],
2534 // });2558 .new_inst = new_decls.items[i],
2535 //}2559 });
2560 }
2536 }2561 }
2537 }2562 }
2538}2563}
src/Zir.zig+116
...@@ -4427,6 +4427,15 @@ pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator {...@@ -4427,6 +4427,15 @@ pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator {
4427 };4427 };
4428 },4428 },
44294429
4430 // Functions are allowed and yield no iterations.
4431 .func,
4432 .func_inferred,
4433 .extended, // assume also a function
4434 => .{
4435 .extra_index = 0,
4436 .decls_len = 0,
4437 },
4438
4430 else => unreachable,4439 else => unreachable,
4431 };4440 };
44324441
...@@ -4441,3 +4450,110 @@ pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator {...@@ -4441,3 +4450,110 @@ pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator {
4441 .decls_len = decl_info.decls_len,4450 .decls_len = decl_info.decls_len,
4442 };4451 };
4443}4452}
4453
4454/// The iterator would have to allocate memory anyway to iterate. So here we populate
4455/// an ArrayList as the result.
4456pub fn findDecls(zir: Zir, list: *std.ArrayList(Zir.Inst.Index), decl_sub_index: u32) !void {
4457 const block_inst = zir.extra[decl_sub_index + 6];
4458 list.clearRetainingCapacity();
4459
4460 return zir.findDeclsInner(list, block_inst);
4461}
4462
4463fn findDeclsInner(
4464 zir: Zir,
4465 list: *std.ArrayList(Zir.Inst.Index),
4466 inst: Zir.Inst.Index,
4467) Allocator.Error!void {
4468 const tags = zir.instructions.items(.tag);
4469 const datas = zir.instructions.items(.data);
4470
4471 switch (tags[inst]) {
4472 // Decl instructions are interesting but have no body.
4473 .struct_decl,
4474 .struct_decl_packed,
4475 .struct_decl_extern,
4476 .union_decl,
4477 .union_decl_packed,
4478 .union_decl_extern,
4479 .enum_decl,
4480 .enum_decl_nonexhaustive,
4481 .opaque_decl,
4482 => return list.append(inst),
4483
4484 // Functions instructions are interesting and have a body.
4485 .func,
4486 .func_inferred,
4487 => {
4488 try list.append(inst);
4489
4490 const inst_data = datas[inst].pl_node;
4491 const extra = zir.extraData(Inst.Func, inst_data.payload_index);
4492 const param_types_len = extra.data.param_types_len;
4493 const body = zir.extra[extra.end + param_types_len ..][0..extra.data.body_len];
4494 return zir.findDeclsBody(list, body);
4495 },
4496 .extended => {
4497 const extended = datas[inst].extended;
4498 if (extended.opcode != .func) return;
4499
4500 try list.append(inst);
4501
4502 const extra = zir.extraData(Inst.ExtendedFunc, extended.operand);
4503 const small = @bitCast(Inst.ExtendedFunc.Small, extended.small);
4504 var extra_index: usize = extra.end;
4505 extra_index += @boolToInt(small.has_lib_name);
4506 extra_index += @boolToInt(small.has_cc);
4507 extra_index += @boolToInt(small.has_align);
4508 extra_index += extra.data.param_types_len;
4509 const body = zir.extra[extra_index..][0..extra.data.body_len];
4510 return zir.findDeclsBody(list, body);
4511 },
4512
4513 // Block instructions, recurse over the bodies.
4514
4515 .block, .block_inline => {
4516 const inst_data = datas[inst].pl_node;
4517 const extra = zir.extraData(Inst.Block, inst_data.payload_index);
4518 const body = zir.extra[extra.end..][0..extra.data.body_len];
4519 return zir.findDeclsBody(list, body);
4520 },
4521 .condbr, .condbr_inline => {
4522 const inst_data = datas[inst].pl_node;
4523 const extra = zir.extraData(Inst.CondBr, inst_data.payload_index);
4524 const then_body = zir.extra[extra.end..][0..extra.data.then_body_len];
4525 const else_body = zir.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
4526 try zir.findDeclsBody(list, then_body);
4527 try zir.findDeclsBody(list, else_body);
4528 },
4529 .switch_block,
4530 .switch_block_else,
4531 .switch_block_under,
4532 .switch_block_ref,
4533 .switch_block_ref_else,
4534 .switch_block_ref_under,
4535 => @panic("TODO iterate switch block"),
4536
4537 .switch_block_multi,
4538 .switch_block_else_multi,
4539 .switch_block_under_multi,
4540 .switch_block_ref_multi,
4541 .switch_block_ref_else_multi,
4542 .switch_block_ref_under_multi,
4543 => @panic("TODO iterate switch block multi"),
4544
4545 .suspend_block => @panic("TODO iterate suspend block"),
4546
4547 else => return, // Regular instruction, not interesting.
4548 }
4549}
4550
4551fn findDeclsBody(
4552 zir: Zir,
4553 list: *std.ArrayList(Zir.Inst.Index),
4554 body: []const Zir.Inst.Index,
4555) Allocator.Error!void {
4556 for (body) |member| {
4557 try zir.findDeclsInner(list, member);
4558 }
4559}