From 9b1aac8a654d1ee3515e2de8d477cf1909e63fdf Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 5 May 2021 16:56:24 -0700 Subject: stage2: mapping old to new ZIR recursively now it walks into functions and blocks to find decls. --- src/Module.zig | 47 +++++++++++++++++------ src/Zir.zig | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/Module.zig b/src/Module.zig index 8a41375a6a..d78b9c95e6 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -438,13 +438,24 @@ pub const Decl = struct { /// If the Decl has a value and it is a struct, return it, /// otherwise null. - pub fn getStruct(decl: Decl) ?*Struct { + pub fn getStruct(decl: *Decl) ?*Struct { if (!decl.has_tv) return null; const ty = (decl.val.castTag(.ty) orelse return null).data; const struct_obj = (ty.castTag(.@"struct") orelse return null).data; + if (struct_obj.owner_decl != decl) return null; return struct_obj; } + /// If the Decl has a value and it is a function, return it, + /// otherwise null. + pub fn getFunction(decl: *Decl) ?*Fn { + if (!decl.has_tv) return null; + if (decl.ty.zigTypeTag() != .Fn) return null; + const func = (decl.val.castTag(.function) orelse return null).data; + if (func.owner_decl != decl) return null; + return func; + } + pub fn dump(decl: *Decl) void { const loc = std.zig.findLineColumn(decl.scope.source.bytes, decl.src); std.debug.print("{s}:{d}:{d} name={s} status={s}", .{ @@ -2378,6 +2389,7 @@ const UpdateChangeList = struct { /// Patch ups: /// * Struct.zir_index +/// * Fn.zir_body_inst /// * Decl.zir_decl_index /// * Decl.name /// * Namespace.decl keys @@ -2454,6 +2466,13 @@ fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !UpdateChange }; } + if (decl.getFunction()) |func| { + func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse { + try deleted_decls.append(gpa, decl); + continue; + }; + } + if (decl.val.getTypeNamespace()) |namespace| { for (namespace.decls.items()) |*entry| { const sub_decl = entry.value; @@ -2503,6 +2522,11 @@ pub fn mapOldZirToNew( .new_inst = new_main_struct_inst, }); + var old_decls = std.ArrayList(Zir.Inst.Index).init(gpa); + defer old_decls.deinit(); + var new_decls = std.ArrayList(Zir.Inst.Index).init(gpa); + defer new_decls.deinit(); + while (match_stack.popOrNull()) |match_item| { try inst_map.put(gpa, match_item.old_inst, match_item.new_inst); @@ -2523,16 +2547,17 @@ pub fn mapOldZirToNew( const new_extra_index = new_decl.sub_index; try extra_map.put(gpa, old_extra_index, new_extra_index); - //var old_it = declInstIterator(old_zir, old_extra_index); - //var new_it = declInstIterator(new_zir, new_extra_index); - //while (true) { - // const old_decl_inst = old_it.next() orelse break; - // const new_decl_inst = new_it.next() orelse break; - // try match_stack.append(gpa, .{ - // .old_inst = old_decl_inst, - // .new_inst = new_decl_inst, - // }); - //} + try old_zir.findDecls(&old_decls, old_extra_index); + try new_zir.findDecls(&new_decls, new_extra_index); + var i: usize = 0; + while (true) : (i += 1) { + if (i >= old_decls.items.len) break; + if (i >= new_decls.items.len) break; + try match_stack.append(gpa, .{ + .old_inst = old_decls.items[i], + .new_inst = new_decls.items[i], + }); + } } } } diff --git a/src/Zir.zig b/src/Zir.zig index c2fb387a2c..8b2dff0e45 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -4427,6 +4427,15 @@ pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator { }; }, + // Functions are allowed and yield no iterations. + .func, + .func_inferred, + .extended, // assume also a function + => .{ + .extra_index = 0, + .decls_len = 0, + }, + else => unreachable, }; @@ -4441,3 +4450,110 @@ pub fn declIterator(zir: Zir, decl_inst: u32) DeclIterator { .decls_len = decl_info.decls_len, }; } + +/// The iterator would have to allocate memory anyway to iterate. So here we populate +/// an ArrayList as the result. +pub fn findDecls(zir: Zir, list: *std.ArrayList(Zir.Inst.Index), decl_sub_index: u32) !void { + const block_inst = zir.extra[decl_sub_index + 6]; + list.clearRetainingCapacity(); + + return zir.findDeclsInner(list, block_inst); +} + +fn findDeclsInner( + zir: Zir, + list: *std.ArrayList(Zir.Inst.Index), + inst: Zir.Inst.Index, +) Allocator.Error!void { + const tags = zir.instructions.items(.tag); + const datas = zir.instructions.items(.data); + + switch (tags[inst]) { + // Decl instructions are interesting but have no body. + .struct_decl, + .struct_decl_packed, + .struct_decl_extern, + .union_decl, + .union_decl_packed, + .union_decl_extern, + .enum_decl, + .enum_decl_nonexhaustive, + .opaque_decl, + => return list.append(inst), + + // Functions instructions are interesting and have a body. + .func, + .func_inferred, + => { + try list.append(inst); + + const inst_data = datas[inst].pl_node; + const extra = zir.extraData(Inst.Func, inst_data.payload_index); + const param_types_len = extra.data.param_types_len; + const body = zir.extra[extra.end + param_types_len ..][0..extra.data.body_len]; + return zir.findDeclsBody(list, body); + }, + .extended => { + const extended = datas[inst].extended; + if (extended.opcode != .func) return; + + try list.append(inst); + + const extra = zir.extraData(Inst.ExtendedFunc, extended.operand); + const small = @bitCast(Inst.ExtendedFunc.Small, extended.small); + var extra_index: usize = extra.end; + extra_index += @boolToInt(small.has_lib_name); + extra_index += @boolToInt(small.has_cc); + extra_index += @boolToInt(small.has_align); + extra_index += extra.data.param_types_len; + const body = zir.extra[extra_index..][0..extra.data.body_len]; + return zir.findDeclsBody(list, body); + }, + + // Block instructions, recurse over the bodies. + + .block, .block_inline => { + const inst_data = datas[inst].pl_node; + const extra = zir.extraData(Inst.Block, inst_data.payload_index); + const body = zir.extra[extra.end..][0..extra.data.body_len]; + return zir.findDeclsBody(list, body); + }, + .condbr, .condbr_inline => { + const inst_data = datas[inst].pl_node; + const extra = zir.extraData(Inst.CondBr, inst_data.payload_index); + const then_body = zir.extra[extra.end..][0..extra.data.then_body_len]; + const else_body = zir.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; + try zir.findDeclsBody(list, then_body); + try zir.findDeclsBody(list, else_body); + }, + .switch_block, + .switch_block_else, + .switch_block_under, + .switch_block_ref, + .switch_block_ref_else, + .switch_block_ref_under, + => @panic("TODO iterate switch block"), + + .switch_block_multi, + .switch_block_else_multi, + .switch_block_under_multi, + .switch_block_ref_multi, + .switch_block_ref_else_multi, + .switch_block_ref_under_multi, + => @panic("TODO iterate switch block multi"), + + .suspend_block => @panic("TODO iterate suspend block"), + + else => return, // Regular instruction, not interesting. + } +} + +fn findDeclsBody( + zir: Zir, + list: *std.ArrayList(Zir.Inst.Index), + body: []const Zir.Inst.Index, +) Allocator.Error!void { + for (body) |member| { + try zir.findDeclsInner(list, member); + } +} -- cgit v1.2.3