| ... | @@ -4,10 +4,11 @@ const fmtIntSizeBin = std.fmt.fmtIntSizeBin; | ... | @@ -4,10 +4,11 @@ const fmtIntSizeBin = std.fmt.fmtIntSizeBin; |
| 4 | | 4 | |
| 5 | const Module = @import("Module.zig"); | 5 | const Module = @import("Module.zig"); |
| 6 | const Value = @import("value.zig").Value; | 6 | const Value = @import("value.zig").Value; |
| | 7 | const Zir = @import("Zir.zig"); |
| 7 | const Air = @import("Air.zig"); | 8 | const Air = @import("Air.zig"); |
| 8 | const Liveness = @import("Liveness.zig"); | 9 | const Liveness = @import("Liveness.zig"); |
| 9 | | 10 | |
| 10 | pub fn dump(gpa: *Allocator, air: Air, liveness: Liveness) void { | 11 | pub fn dump(gpa: *Allocator, air: Air, zir: Zir, liveness: Liveness) void { |
| 11 | const instruction_bytes = air.instructions.len * | 12 | const instruction_bytes = air.instructions.len * |
| 12 | // Here we don't use @sizeOf(Air.Inst.Data) because it would include | 13 | // Here we don't use @sizeOf(Air.Inst.Data) because it would include |
| 13 | // the debug safety tag but we want to measure release size. | 14 | // the debug safety tag but we want to measure release size. |
| ... | @@ -51,11 +52,13 @@ pub fn dump(gpa: *Allocator, air: Air, liveness: Liveness) void { | ... | @@ -51,11 +52,13 @@ pub fn dump(gpa: *Allocator, air: Air, liveness: Liveness) void { |
| 51 | .gpa = gpa, | 52 | .gpa = gpa, |
| 52 | .arena = &arena.allocator, | 53 | .arena = &arena.allocator, |
| 53 | .air = air, | 54 | .air = air, |
| | 55 | .zir = zir, |
| 54 | .liveness = liveness, | 56 | .liveness = liveness, |
| 55 | .indent = 0, | 57 | .indent = 2, |
| 56 | }; | 58 | }; |
| 57 | const stream = std.io.getStdErr().writer(); | 59 | const stream = std.io.getStdErr().writer(); |
| 58 | writer.writeAllConstants(stream) catch return; | 60 | writer.writeAllConstants(stream) catch return; |
| | 61 | stream.writeByte('\n') catch return; |
| 59 | writer.writeBody(stream, air.getMainBody()) catch return; | 62 | writer.writeBody(stream, air.getMainBody()) catch return; |
| 60 | } | 63 | } |
| 61 | | 64 | |
| ... | @@ -63,6 +66,7 @@ const Writer = struct { | ... | @@ -63,6 +66,7 @@ const Writer = struct { |
| 63 | gpa: *Allocator, | 66 | gpa: *Allocator, |
| 64 | arena: *Allocator, | 67 | arena: *Allocator, |
| 65 | air: Air, | 68 | air: Air, |
| | 69 | zir: Zir, |
| 66 | liveness: Liveness, | 70 | liveness: Liveness, |
| 67 | indent: usize, | 71 | indent: usize, |
| 68 | | 72 | |
| ... | @@ -84,13 +88,13 @@ const Writer = struct { | ... | @@ -84,13 +88,13 @@ const Writer = struct { |
| 84 | fn writeBody(w: *Writer, s: anytype, body: []const Air.Inst.Index) @TypeOf(s).Error!void { | 88 | fn writeBody(w: *Writer, s: anytype, body: []const Air.Inst.Index) @TypeOf(s).Error!void { |
| 85 | for (body) |inst| { | 89 | for (body) |inst| { |
| 86 | try s.writeByteNTimes(' ', w.indent); | 90 | try s.writeByteNTimes(' ', w.indent); |
| 87 | try s.print("%{d} ", .{inst}); | | |
| 88 | try w.writeInst(s, inst); | | |
| 89 | if (w.liveness.isUnused(inst)) { | 91 | if (w.liveness.isUnused(inst)) { |
| 90 | try s.writeAll(") unused\n"); | 92 | try s.print("%{d}!", .{inst}); |
| 91 | } else { | 93 | } else { |
| 92 | try s.writeAll(")\n"); | 94 | try s.print("%{d} ", .{inst}); |
| 93 | } | 95 | } |
| | 96 | try w.writeInst(s, inst); |
| | 97 | try s.writeAll(")\n"); |
| 94 | } | 98 | } |
| 95 | } | 99 | } |
| 96 | | 100 | |
| ... | @@ -176,21 +180,21 @@ const Writer = struct { | ... | @@ -176,21 +180,21 @@ const Writer = struct { |
| 176 | } | 180 | } |
| 177 | | 181 | |
| 178 | fn writeTyStr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 182 | fn writeTyStr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 179 | _ = w; | 183 | const ty_str = w.air.instructions.items(.data)[inst].ty_str; |
| 180 | _ = inst; | 184 | const name = w.zir.nullTerminatedString(ty_str.str); |
| 181 | try s.writeAll("TODO"); | 185 | try s.print("\"{}\", {}", .{ std.zig.fmtEscapes(name), ty_str.ty }); |
| 182 | } | 186 | } |
| 183 | | 187 | |
| 184 | fn writeBinOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 188 | fn writeBinOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 185 | const bin_op = w.air.instructions.items(.data)[inst].bin_op; | 189 | const bin_op = w.air.instructions.items(.data)[inst].bin_op; |
| 186 | try w.writeInstRef(s, bin_op.lhs); | 190 | try w.writeOperand(s, inst, 0, bin_op.lhs); |
| 187 | try s.writeAll(", "); | 191 | try s.writeAll(", "); |
| 188 | try w.writeInstRef(s, bin_op.rhs); | 192 | try w.writeOperand(s, inst, 1, bin_op.rhs); |
| 189 | } | 193 | } |
| 190 | | 194 | |
| 191 | fn writeUnOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 195 | fn writeUnOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 192 | const un_op = w.air.instructions.items(.data)[inst].un_op; | 196 | const un_op = w.air.instructions.items(.data)[inst].un_op; |
| 193 | try w.writeInstRef(s, un_op); | 197 | try w.writeOperand(s, inst, 0, un_op); |
| 194 | } | 198 | } |
| 195 | | 199 | |
| 196 | fn writeNoOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 200 | fn writeNoOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| ... | @@ -208,7 +212,7 @@ const Writer = struct { | ... | @@ -208,7 +212,7 @@ const Writer = struct { |
| 208 | fn writeTyOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 212 | fn writeTyOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 209 | const ty_op = w.air.instructions.items(.data)[inst].ty_op; | 213 | const ty_op = w.air.instructions.items(.data)[inst].ty_op; |
| 210 | try s.print("{}, ", .{w.air.getRefType(ty_op.ty)}); | 214 | try s.print("{}, ", .{w.air.getRefType(ty_op.ty)}); |
| 211 | try w.writeInstRef(s, ty_op.operand); | 215 | try w.writeOperand(s, inst, 0, ty_op.operand); |
| 212 | } | 216 | } |
| 213 | | 217 | |
| 214 | fn writeBlock(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 218 | fn writeBlock(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| ... | @@ -229,7 +233,7 @@ const Writer = struct { | ... | @@ -229,7 +233,7 @@ const Writer = struct { |
| 229 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; | 233 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; |
| 230 | const extra = w.air.extraData(Air.StructField, ty_pl.payload); | 234 | const extra = w.air.extraData(Air.StructField, ty_pl.payload); |
| 231 | | 235 | |
| 232 | try w.writeInstRef(s, extra.data.struct_ptr); | 236 | try w.writeOperand(s, inst, 0, extra.data.struct_ptr); |
| 233 | try s.print(", {d}", .{extra.data.field_index}); | 237 | try s.print(", {d}", .{extra.data.field_index}); |
| 234 | } | 238 | } |
| 235 | | 239 | |
| ... | @@ -259,21 +263,21 @@ const Writer = struct { | ... | @@ -259,21 +263,21 @@ const Writer = struct { |
| 259 | fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 263 | fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 260 | const pl_op = w.air.instructions.items(.data)[inst].pl_op; | 264 | const pl_op = w.air.instructions.items(.data)[inst].pl_op; |
| 261 | const extra = w.air.extraData(Air.Call, pl_op.payload); | 265 | const extra = w.air.extraData(Air.Call, pl_op.payload); |
| 262 | const args = w.air.extra[extra.end..][0..extra.data.args_len]; | 266 | const args = @bitCast([]const Air.Inst.Ref, w.air.extra[extra.end..][0..extra.data.args_len]); |
| 263 | try w.writeInstRef(s, pl_op.operand); | 267 | try w.writeOperand(s, inst, 0, pl_op.operand); |
| 264 | try s.writeAll(", ["); | 268 | try s.writeAll(", ["); |
| 265 | for (args) |arg, i| { | 269 | for (args) |arg, i| { |
| 266 | if (i != 0) try s.writeAll(", "); | 270 | if (i != 0) try s.writeAll(", "); |
| 267 | try w.writeInstRef(s, @intToEnum(Air.Inst.Ref, arg)); | 271 | try w.writeOperand(s, inst, 1 + i, arg); |
| 268 | } | 272 | } |
| 269 | try s.writeAll("]"); | 273 | try s.writeAll("]"); |
| 270 | } | 274 | } |
| 271 | | 275 | |
| 272 | fn writeBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 276 | fn writeBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 273 | const br = w.air.instructions.items(.data)[inst].br; | 277 | const br = w.air.instructions.items(.data)[inst].br; |
| 274 | try w.writeInstIndex(s, br.block_inst); | 278 | try w.writeInstIndex(s, br.block_inst, false); |
| 275 | try s.writeAll(", "); | 279 | try s.writeAll(", "); |
| 276 | try w.writeInstRef(s, br.operand); | 280 | try w.writeOperand(s, inst, 0, br.operand); |
| 277 | } | 281 | } |
| 278 | | 282 | |
| 279 | fn writeCondBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 283 | fn writeCondBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| ... | @@ -281,16 +285,35 @@ const Writer = struct { | ... | @@ -281,16 +285,35 @@ const Writer = struct { |
| 281 | const extra = w.air.extraData(Air.CondBr, pl_op.payload); | 285 | const extra = w.air.extraData(Air.CondBr, pl_op.payload); |
| 282 | const then_body = w.air.extra[extra.end..][0..extra.data.then_body_len]; | 286 | const then_body = w.air.extra[extra.end..][0..extra.data.then_body_len]; |
| 283 | const else_body = w.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; | 287 | const else_body = w.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; |
| | 288 | const liveness_condbr = w.liveness.getCondBr(inst); |
| 284 | | 289 | |
| 285 | try w.writeInstRef(s, pl_op.operand); | 290 | try w.writeOperand(s, inst, 0, pl_op.operand); |
| 286 | try s.writeAll(", {\n"); | 291 | try s.writeAll(", {\n"); |
| 287 | const old_indent = w.indent; | 292 | const old_indent = w.indent; |
| 288 | w.indent += 2; | 293 | w.indent += 2; |
| 289 | | 294 | |
| | 295 | if (liveness_condbr.then_deaths.len != 0) { |
| | 296 | try s.writeByteNTimes(' ', w.indent); |
| | 297 | for (liveness_condbr.then_deaths) |operand, i| { |
| | 298 | if (i != 0) try s.writeAll(" "); |
| | 299 | try s.print("%{d}!", .{operand}); |
| | 300 | } |
| | 301 | try s.writeAll("\n"); |
| | 302 | } |
| | 303 | |
| 290 | try w.writeBody(s, then_body); | 304 | try w.writeBody(s, then_body); |
| 291 | try s.writeByteNTimes(' ', old_indent); | 305 | try s.writeByteNTimes(' ', old_indent); |
| 292 | try s.writeAll("}, {\n"); | 306 | try s.writeAll("}, {\n"); |
| 293 | | 307 | |
| | 308 | if (liveness_condbr.else_deaths.len != 0) { |
| | 309 | try s.writeByteNTimes(' ', w.indent); |
| | 310 | for (liveness_condbr.else_deaths) |operand, i| { |
| | 311 | if (i != 0) try s.writeAll(" "); |
| | 312 | try s.print("%{d}!", .{operand}); |
| | 313 | } |
| | 314 | try s.writeAll("\n"); |
| | 315 | } |
| | 316 | |
| 294 | try w.writeBody(s, else_body); | 317 | try w.writeBody(s, else_body); |
| 295 | w.indent = old_indent; | 318 | w.indent = old_indent; |
| 296 | | 319 | |
| ... | @@ -304,7 +327,7 @@ const Writer = struct { | ... | @@ -304,7 +327,7 @@ const Writer = struct { |
| 304 | var extra_index: usize = switch_br.end; | 327 | var extra_index: usize = switch_br.end; |
| 305 | var case_i: u32 = 0; | 328 | var case_i: u32 = 0; |
| 306 | | 329 | |
| 307 | try w.writeInstRef(s, pl_op.operand); | 330 | try w.writeOperand(s, inst, 0, pl_op.operand); |
| 308 | const old_indent = w.indent; | 331 | const old_indent = w.indent; |
| 309 | w.indent += 2; | 332 | w.indent += 2; |
| 310 | | 333 | |
| ... | @@ -317,7 +340,7 @@ const Writer = struct { | ... | @@ -317,7 +340,7 @@ const Writer = struct { |
| 317 | try s.writeAll(", ["); | 340 | try s.writeAll(", ["); |
| 318 | for (items) |item, item_i| { | 341 | for (items) |item, item_i| { |
| 319 | if (item_i != 0) try s.writeAll(", "); | 342 | if (item_i != 0) try s.writeAll(", "); |
| 320 | try w.writeInstRef(s, item); | 343 | try w.writeInstRef(s, item, false); |
| 321 | } | 344 | } |
| 322 | try s.writeAll("] => {\n"); | 345 | try s.writeAll("] => {\n"); |
| 323 | w.indent += 2; | 346 | w.indent += 2; |
| ... | @@ -342,19 +365,49 @@ const Writer = struct { | ... | @@ -342,19 +365,49 @@ const Writer = struct { |
| 342 | try s.writeAll("}"); | 365 | try s.writeAll("}"); |
| 343 | } | 366 | } |
| 344 | | 367 | |
| 345 | fn writeInstRef(w: *Writer, s: anytype, inst: Air.Inst.Ref) @TypeOf(s).Error!void { | 368 | fn writeOperand( |
| 346 | var i: usize = @enumToInt(inst); | 369 | w: *Writer, |
| | 370 | s: anytype, |
| | 371 | inst: Air.Inst.Index, |
| | 372 | op_index: usize, |
| | 373 | operand: Air.Inst.Ref, |
| | 374 | ) @TypeOf(s).Error!void { |
| | 375 | const dies = if (op_index < Liveness.bpi - 1) |
| | 376 | w.liveness.operandDies(inst, @intCast(Liveness.OperandInt, op_index)) |
| | 377 | else blk: { |
| | 378 | // TODO |
| | 379 | break :blk false; |
| | 380 | }; |
| | 381 | return w.writeInstRef(s, operand, dies); |
| | 382 | } |
| | 383 | |
| | 384 | fn writeInstRef( |
| | 385 | w: *Writer, |
| | 386 | s: anytype, |
| | 387 | operand: Air.Inst.Ref, |
| | 388 | dies: bool, |
| | 389 | ) @TypeOf(s).Error!void { |
| | 390 | var i: usize = @enumToInt(operand); |
| 347 | | 391 | |
| 348 | if (i < Air.Inst.Ref.typed_value_map.len) { | 392 | if (i < Air.Inst.Ref.typed_value_map.len) { |
| 349 | return s.print("@{}", .{inst}); | 393 | return s.print("@{}", .{operand}); |
| 350 | } | 394 | } |
| 351 | i -= Air.Inst.Ref.typed_value_map.len; | 395 | i -= Air.Inst.Ref.typed_value_map.len; |
| 352 | | 396 | |
| 353 | return w.writeInstIndex(s, @intCast(Air.Inst.Index, i)); | 397 | return w.writeInstIndex(s, @intCast(Air.Inst.Index, i), dies); |
| 354 | } | 398 | } |
| 355 | | 399 | |
| 356 | fn writeInstIndex(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 400 | fn writeInstIndex( |
| | 401 | w: *Writer, |
| | 402 | s: anytype, |
| | 403 | inst: Air.Inst.Index, |
| | 404 | dies: bool, |
| | 405 | ) @TypeOf(s).Error!void { |
| 357 | _ = w; | 406 | _ = w; |
| 358 | return s.print("%{d}", .{inst}); | 407 | if (dies) { |
| | 408 | try s.print("%{d}!", .{inst}); |
| | 409 | } else { |
| | 410 | try s.print("%{d}", .{inst}); |
| | 411 | } |
| 359 | } | 412 | } |
| 360 | }; | 413 | }; |