mirror of
https://github.com/ziglang/zig.git
synced 2026-02-06 14:37:04 +00:00
stage2: mapping old to new ZIR recursively
now it walks into functions and blocks to find decls.
This commit is contained in:
parent
c714a3250f
commit
9b1aac8a65
@ -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],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
116
src/Zir.zig
116
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);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user