authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-17 22:20:49-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-18 16:56:12-07:00
log32edb9b55d0e41a58a11e0437149c4a9705c4699
treec0497c52c28ae9f97a9fcb5c57fa89e33838f5bd
parentdee96e2e2f464c3b8edc8ec3a63cd3b1860e3a9d

stage2: eliminate ZIR arg instruction references to ZIR

Prior to this commit, the AIR arg instruction kept a reference to a ZIR string index for the corresponding parameter name. This is used by DWARF emitting code. However, this is a design flaw because we want AIR objects to be independent from ZIR. This commit saves the parameter names into memory managed by `Module.Fn`. This is sub-optimal because we should be able to get the parameter names from the ZIR for a function without having them redundantly stored along with `Fn` memory. However the current way that ZIR param instructions are encoded does not support this case. They appear in the same ZIR body as the function instruction, just before it. Instead, they should be embedded within the function instruction, which will allow this TODO to be solved. That improvement is too big for this commit, however. After this there is one last dependency to untangle, which is for inline assembly. The issue for that is #10784.

7 files changed, 48 insertions(+), 52 deletions(-)

src/Air.zig+2-9
......@@ -32,8 +32,7 @@ pub const Inst = struct {
3232 /// The first N instructions in the main block must be one arg instruction per
3333 /// function parameter. This makes function parameters participate in
3434 /// liveness analysis without any special handling.
35 /// Uses the `ty_str` field.
36 /// The string is the parameter name.
35 /// Uses the `ty` field.
3736 arg,
3837 /// Float or integer addition. For integers, wrapping is undefined behavior.
3938 /// Both operands are guaranteed to be the same type, and the result type
......@@ -615,11 +614,6 @@ pub const Inst = struct {
615614 // Index into a different array.
616615 payload: u32,
617616 },
618 ty_str: struct {
619 ty: Ref,
620 // ZIR string table index.
621 str: u32,
622 },
623617 br: struct {
624618 block_inst: Index,
625619 operand: Ref,
......@@ -759,8 +753,6 @@ pub fn typeOf(air: Air, inst: Air.Inst.Ref) Type {
759753pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
760754 const datas = air.instructions.items(.data);
761755 switch (air.instructions.items(.tag)[inst]) {
762 .arg => return air.getRefType(datas[inst].ty_str.ty),
763
764756 .add,
765757 .addwrap,
766758 .add_sat,
......@@ -827,6 +819,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
827819
828820 .alloc,
829821 .ret_ptr,
822 .arg,
830823 => return datas[inst].ty,
831824
832825 .assembly,
src/Module.zig+21-5
......@@ -1370,6 +1370,14 @@ pub const Fn = struct {
13701370 /// ZIR instruction.
13711371 zir_body_inst: Zir.Inst.Index,
13721372
1373 /// Prefer to use `getParamName` to access this because of the future improvement
1374 /// we want to do mentioned in the TODO below.
1375 /// Stored in gpa.
1376 /// TODO: change param ZIR instructions to be embedded inside the function
1377 /// ZIR instruction instead of before it, so that `zir_body_inst` can be used to
1378 /// determine param names rather than redundantly storing them here.
1379 param_names: []const [:0]const u8,
1380
13731381 /// Relative to owner Decl.
13741382 lbrace_line: u32,
13751383 /// Relative to owner Decl.
......@@ -1466,6 +1474,18 @@ pub const Fn = struct {
14661474 gpa.destroy(node);
14671475 it = next;
14681476 }
1477
1478 for (func.param_names) |param_name| {
1479 gpa.free(param_name);
1480 }
1481 gpa.free(func.param_names);
1482 }
1483
1484 pub fn getParamName(func: Fn, index: u32) [:0]const u8 {
1485 // TODO rework ZIR of parameters so that this function looks up
1486 // param names in ZIR instead of redundantly saving them into Fn.
1487 // const zir = func.owner_decl.getFileScope().zir;
1488 return func.param_names[index];
14691489 }
14701490};
14711491
......@@ -4606,15 +4626,11 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: Allocator) Sem
46064626 runtime_param_index += 1;
46074627 continue;
46084628 }
4609 const ty_ref = try sema.addType(param_type);
46104629 const arg_index = @intCast(u32, sema.air_instructions.len);
46114630 inner_block.instructions.appendAssumeCapacity(arg_index);
46124631 sema.air_instructions.appendAssumeCapacity(.{
46134632 .tag = .arg,
4614 .data = .{ .ty_str = .{
4615 .ty = ty_ref,
4616 .str = param.name,
4617 } },
4633 .data = .{ .ty = param_type },
46184634 });
46194635 sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(arg_index));
46204636 total_param_index += 1;
src/Sema.zig+14-14
......@@ -134,6 +134,7 @@ pub const Block = struct {
134134 /// `noreturn` means `anytype`.
135135 ty: Type,
136136 is_comptime: bool,
137 name: []const u8,
137138 };
138139
139140 /// This `Block` maps a block ZIR instruction to the corresponding
......@@ -284,13 +285,10 @@ pub const Block = struct {
284285 });
285286 }
286287
287 fn addArg(block: *Block, ty: Type, name: u32) error{OutOfMemory}!Air.Inst.Ref {
288 fn addArg(block: *Block, ty: Type) error{OutOfMemory}!Air.Inst.Ref {
288289 return block.addInst(.{
289290 .tag = .arg,
290 .data = .{ .ty_str = .{
291 .ty = try block.sema.addType(ty),
292 .str = name,
293 } },
291 .data = .{ .ty = ty },
294292 });
295293 }
296294
......@@ -4645,7 +4643,7 @@ fn analyzeCall(
46454643 } else {
46464644 // We insert into the map an instruction which is runtime-known
46474645 // but has the type of the argument.
4648 const child_arg = try child_block.addArg(arg_ty, 0);
4646 const child_arg = try child_block.addArg(arg_ty);
46494647 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
46504648 }
46514649 }
......@@ -5712,6 +5710,11 @@ fn funcCommon(
57125710 break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;
57135711 } else null;
57145712
5713 const param_names = try sema.gpa.alloc([:0]const u8, block.params.items.len);
5714 for (param_names) |*param_name, i| {
5715 param_name.* = try sema.gpa.dupeZ(u8, block.params.items[i].name);
5716 }
5717
57155718 const fn_payload = try sema.arena.create(Value.Payload.Function);
57165719 new_func.* = .{
57175720 .state = anal_state,
......@@ -5722,6 +5725,7 @@ fn funcCommon(
57225725 .rbrace_line = src_locs.rbrace_line,
57235726 .lbrace_column = @truncate(u16, src_locs.columns),
57245727 .rbrace_column = @truncate(u16, src_locs.columns >> 16),
5728 .param_names = param_names,
57255729 };
57265730 if (maybe_inferred_error_set_node) |node| {
57275731 new_func.inferred_error_sets.prepend(node);
......@@ -5746,10 +5750,6 @@ fn zirParam(
57465750 const param_name = sema.code.nullTerminatedString(extra.data.name);
57475751 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
57485752
5749 // TODO check if param_name shadows a Decl. This only needs to be done if
5750 // usingnamespace is implemented.
5751 _ = param_name;
5752
57535753 // We could be in a generic function instantiation, or we could be evaluating a generic
57545754 // function without any comptime args provided.
57555755 const param_ty = param_ty: {
......@@ -5776,6 +5776,7 @@ fn zirParam(
57765776 try block.params.append(sema.gpa, .{
57775777 .ty = Type.initTag(.generic_poison),
57785778 .is_comptime = comptime_syntax,
5779 .name = param_name,
57795780 });
57805781 try sema.inst_map.putNoClobber(sema.gpa, inst, .generic_poison);
57815782 return;
......@@ -5801,6 +5802,7 @@ fn zirParam(
58015802 try block.params.append(sema.gpa, .{
58025803 .ty = param_ty,
58035804 .is_comptime = is_comptime,
5805 .name = param_name,
58045806 });
58055807 const result = try sema.addConstant(param_ty, Value.initTag(.generic_poison));
58065808 try sema.inst_map.putNoClobber(sema.gpa, inst, result);
......@@ -5816,10 +5818,6 @@ fn zirParamAnytype(
58165818 const src = inst_data.src();
58175819 const param_name = inst_data.get(sema.code);
58185820
5819 // TODO check if param_name shadows a Decl. This only needs to be done if
5820 // usingnamespace is implemented.
5821 _ = param_name;
5822
58235821 if (sema.inst_map.get(inst)) |air_ref| {
58245822 const param_ty = sema.typeOf(air_ref);
58255823 if (comptime_syntax or try sema.typeRequiresComptime(block, src, param_ty)) {
......@@ -5831,6 +5829,7 @@ fn zirParamAnytype(
58315829 try block.params.append(sema.gpa, .{
58325830 .ty = param_ty,
58335831 .is_comptime = false,
5832 .name = param_name,
58345833 });
58355834 return;
58365835 }
......@@ -5840,6 +5839,7 @@ fn zirParamAnytype(
58405839 try block.params.append(sema.gpa, .{
58415840 .ty = Type.initTag(.generic_poison),
58425841 .is_comptime = comptime_syntax,
5842 .name = param_name,
58435843 });
58445844 try sema.inst_map.put(sema.gpa, inst, .generic_poison);
58455845}
src/arch/arm/Emit.zig+2-4
......@@ -393,11 +393,9 @@ fn addDbgInfoTypeReloc(self: *Emit, ty: Type) !void {
393393fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
394394 const mcv = self.function.args[arg_index];
395395
396 const ty_str = self.function.air.instructions.items(.data)[inst].ty_str;
397 const zir = &self.function.mod_fn.owner_decl.getFileScope().zir;
398 const name = zir.nullTerminatedString(ty_str.str);
396 const ty = self.function.air.instructions.items(.data)[inst].ty;
397 const name = self.function.mod_fn.getParamName(arg_index);
399398 const name_with_null = name.ptr[0 .. name.len + 1];
400 const ty = self.function.air.getRefType(ty_str.ty);
401399
402400 switch (mcv) {
403401 .register => |reg| {
src/arch/riscv64/CodeGen.zig+4-6
......@@ -1340,12 +1340,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
13401340 //return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none });
13411341}
13421342
1343fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue) !void {
1344 const ty_str = self.air.instructions.items(.data)[inst].ty_str;
1345 const zir = &self.mod_fn.owner_decl.getFileScope().zir;
1346 const name = zir.nullTerminatedString(ty_str.str);
1343fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32) !void {
1344 const ty = self.air.instructions.items(.data)[inst].ty;
1345 const name = self.mod_fn.getParamName(arg_index);
13471346 const name_with_null = name.ptr[0 .. name.len + 1];
1348 const ty = self.air.getRefType(ty_str.ty);
13491347
13501348 switch (mcv) {
13511349 .register => |reg| {
......@@ -1388,7 +1386,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
13881386 // TODO support stack-only arguments
13891387 // TODO Copy registers to the stack
13901388 const mcv = result;
1391 try self.genArgDbgInfo(inst, mcv);
1389 try self.genArgDbgInfo(inst, mcv, @intCast(u32, arg_index));
13921390
13931391 if (self.liveness.isUnused(inst))
13941392 return self.finishAirBookkeeping();
src/arch/x86_64/Emit.zig+4-6
......@@ -946,15 +946,13 @@ fn mirArgDbgInfo(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
946946 const payload = emit.mir.instructions.items(.data)[inst].payload;
947947 const arg_dbg_info = emit.mir.extraData(Mir.ArgDbgInfo, payload).data;
948948 const mcv = emit.mir.function.args[arg_dbg_info.arg_index];
949 try emit.genArgDbgInfo(arg_dbg_info.air_inst, mcv, arg_dbg_info.max_stack);
949 try emit.genArgDbgInfo(arg_dbg_info.air_inst, mcv, arg_dbg_info.max_stack, arg_dbg_info.arg_index);
950950}
951951
952fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32) !void {
953 const ty_str = emit.mir.function.air.instructions.items(.data)[inst].ty_str;
954 const zir = &emit.mir.function.mod_fn.owner_decl.getFileScope().zir;
955 const name = zir.nullTerminatedString(ty_str.str);
952fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32, arg_index: u32) !void {
953 const ty = emit.mir.function.air.instructions.items(.data)[inst].ty;
954 const name = emit.mir.function.mod_fn.getParamName(arg_index);
956955 const name_with_null = name.ptr[0 .. name.len + 1];
957 const ty = emit.mir.function.air.getRefType(ty_str.ty);
958956
959957 switch (mcv) {
960958 .register => |reg| {
src/print_air.zig+1-8
......@@ -100,8 +100,6 @@ const Writer = struct {
100100 const tag = tags[inst];
101101 try s.print("= {s}(", .{@tagName(tags[inst])});
102102 switch (tag) {
103 .arg => try w.writeTyStr(s, inst),
104
105103 .add,
106104 .addwrap,
107105 .add_sat,
......@@ -181,6 +179,7 @@ const Writer = struct {
181179 .const_ty,
182180 .alloc,
183181 .ret_ptr,
182 .arg,
184183 => try w.writeTy(s, inst),
185184
186185 .not,
......@@ -257,12 +256,6 @@ const Writer = struct {
257256 }
258257 }
259258
260 fn writeTyStr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
261 const ty_str = w.air.instructions.items(.data)[inst].ty_str;
262 const name = w.zir.nullTerminatedString(ty_str.str);
263 try s.print("\"{}\", {}", .{ std.zig.fmtEscapes(name), w.air.getRefType(ty_str.ty) });
264 }
265
266259 fn writeBinOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
267260 const bin_op = w.air.instructions.items(.data)[inst].bin_op;
268261 try w.writeOperand(s, inst, 0, bin_op.lhs);