authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-19 19:33:11-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-19 19:33:11-07:00
log937c43ddf1297f355cc535adf3ec08f9f741b6c8
tree99005ced8d66d9816048b79b0028537d694b1c45
parent0357cd86537f708d915976398a38837feb1a5528

stage2: first pass at repairing ZIR printing


2 files changed, 423 insertions(+), 45 deletions(-)

src/Module.zig+5-5
......@@ -1826,7 +1826,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool {
18261826
18271827 const code = try gen_scope.finish();
18281828 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
1829 code.dump(mod.gpa, "comptime_block", decl.name) catch {};
1829 code.dump(mod.gpa, "comptime_block", decl.name, 0) catch {};
18301830 }
18311831 break :blk code;
18321832 };
......@@ -2047,7 +2047,7 @@ fn astgenAndSemaFn(
20472047
20482048 const fn_type_code = try fn_type_scope.finish();
20492049 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
2050 fn_type_code.dump(mod.gpa, "fn_type", decl.name) catch {};
2050 fn_type_code.dump(mod.gpa, "fn_type", decl.name, 0) catch {};
20512051 }
20522052
20532053 var fn_type_sema: Sema = .{
......@@ -2170,7 +2170,7 @@ fn astgenAndSemaFn(
21702170
21712171 const code = try gen_scope.finish();
21722172 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
2173 code.dump(mod.gpa, "fn_body", decl.name) catch {};
2173 code.dump(mod.gpa, "fn_body", decl.name, param_count) catch {};
21742174 }
21752175
21762176 break :blk code;
......@@ -2347,7 +2347,7 @@ fn astgenAndSemaVarDecl(
23472347 );
23482348 const code = try gen_scope.finish();
23492349 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
2350 code.dump(mod.gpa, "var_init", decl.name) catch {};
2350 code.dump(mod.gpa, "var_init", decl.name, 0) catch {};
23512351 }
23522352
23532353 var sema: Sema = .{
......@@ -2409,7 +2409,7 @@ fn astgenAndSemaVarDecl(
24092409 const var_type = try astgen.typeExpr(mod, &type_scope.base, var_decl.ast.type_node);
24102410 const code = try type_scope.finish();
24112411 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
2412 code.dump(mod.gpa, "var_type", decl.name) catch {};
2412 code.dump(mod.gpa, "var_type", decl.name, 0) catch {};
24132413 }
24142414
24152415 var sema: Sema = .{
src/zir.zig+418-40
......@@ -68,58 +68,35 @@ pub const Code = struct {
6868 }
6969
7070 /// For debugging purposes, like dumpFn but for unanalyzed zir blocks
71 pub fn dump(code: Code, gpa: *Allocator, kind: []const u8, decl_name: [*:0]const u8) !void {
71 pub fn dump(
72 code: Code,
73 gpa: *Allocator,
74 kind: []const u8,
75 decl_name: [*:0]const u8,
76 param_count: usize,
77 ) !void {
7278 var arena = std.heap.ArenaAllocator.init(gpa);
7379 defer arena.deinit();
7480
75 if (true) @panic("TODO fix this function for zir-memory-layout branch");
76
7781 var writer: Writer = .{
7882 .gpa = gpa,
7983 .arena = &arena.allocator,
8084 .code = code,
81 .inst_map = try arena.allocator.alloc(*ir.Inst, code.instructions.len),
82 .owner_decl = decl,
83 .func = null,
84 .param_inst_list = &.{},
85 };
86 var write = Writer{
87 .inst_table = InstPtrTable.init(gpa),
88 .block_table = std.AutoHashMap(*Inst.Block, []const u8).init(gpa),
89 .loop_table = std.AutoHashMap(*Inst.Loop, []const u8).init(gpa),
90 .arena = std.heap.ArenaAllocator.init(gpa),
9185 .indent = 4,
92 .next_instr_index = 0,
86 .param_count = param_count,
9387 };
94 defer write.arena.deinit();
95 defer write.inst_table.deinit();
96 defer write.block_table.deinit();
97 defer write.loop_table.deinit();
98
99 try write.inst_table.ensureCapacity(@intCast(u32, instructions.len));
10088
10189 const stderr = std.io.getStdErr().writer();
102 try stderr.print("{s} {s} {{ // unanalyzed\n", .{ kind, decl_name });
103
104 for (instructions) |inst| {
105 const my_i = write.next_instr_index;
106 write.next_instr_index += 1;
107
108 if (inst.cast(Inst.Block)) |block| {
109 const name = try std.fmt.allocPrint(&write.arena.allocator, "label_{d}", .{my_i});
110 try write.block_table.put(block, name);
111 } else if (inst.cast(Inst.Loop)) |loop| {
112 const name = try std.fmt.allocPrint(&write.arena.allocator, "loop_{d}", .{my_i});
113 try write.loop_table.put(loop, name);
114 }
90 try stderr.print("ZIR {s} {s} {{\n", .{ kind, decl_name });
11591
116 try write.inst_table.putNoClobber(inst, .{ .inst = inst, .index = my_i, .name = "inst" });
117 try stderr.print(" %{d} ", .{my_i});
118 try write.writeInstToStream(stderr, inst);
92 const root_body = code.extra[code.root_start..][0..code.root_len];
93 for (root_body) |inst| {
94 try stderr.print(" %{d} ", .{inst});
95 try writer.writeInstToStream(stderr, inst);
11996 try stderr.writeByte('\n');
12097 }
12198
122 try stderr.print("}} // {s} {s}\n\n", .{ kind, decl_name });
99 try stderr.print("}} // ZIR {s} {s}\n\n", .{ kind, decl_name });
123100 }
124101};
125102
......@@ -679,10 +656,10 @@ pub const Inst = struct {
679656 /// Resume an async function.
680657 @"resume",
681658 /// Obtains a pointer to the return value.
682 /// lhs and rhs unused.
659 /// Uses the `node` union field.
683660 ret_ptr,
684661 /// Obtains the return type of the in-scope function.
685 /// lhs and rhs unused.
662 /// Uses the `node` union field.
686663 ret_type,
687664 /// Sends control flow back to the function's callee.
688665 /// Includes an operand as the return value.
......@@ -821,7 +798,7 @@ pub const Inst = struct {
821798 /// Uses the `un_node` union field.
822799 suspend_block_one,
823800 /// Suspend an async function. The suspend block has any number of statements in it.
824 /// Uses the `block` union field.
801 /// Uses the `pl_node` union field. Payload is `MultiOp`.
825802 suspend_block,
826803 // /// A switch expression.
827804 // /// lhs is target, SwitchBr[rhs]
......@@ -1266,3 +1243,404 @@ pub const Inst = struct {
12661243 field_name: Ref,
12671244 };
12681245};
1246
1247const Writer = struct {
1248 gpa: *Allocator,
1249 arena: *Allocator,
1250 code: Code,
1251 indent: usize,
1252 param_count: usize,
1253
1254 fn writeInstToStream(
1255 self: *Writer,
1256 stream: anytype,
1257 inst: Inst.Index,
1258 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1259 const tags = self.code.instructions.items(.tag);
1260 const tag = tags[inst];
1261 try stream.print("= {s}(", .{@tagName(tags[inst])});
1262 switch (tag) {
1263 .add,
1264 .addwrap,
1265 .array_cat,
1266 .array_mul,
1267 .mul,
1268 .mulwrap,
1269 .sub,
1270 .subwrap,
1271 .array_type,
1272 .bit_and,
1273 .bit_or,
1274 .as,
1275 .bool_and,
1276 .bool_or,
1277 .@"break",
1278 .cmp_lt,
1279 .cmp_lte,
1280 .cmp_eq,
1281 .cmp_gte,
1282 .cmp_gt,
1283 .cmp_neq,
1284 .coerce_result_ptr,
1285 .div,
1286 .mod_rem,
1287 .shl,
1288 .shr,
1289 .xor,
1290 .elem_ptr,
1291 .elem_val,
1292 .intcast,
1293 .int_type,
1294 .merge_error_sets,
1295 => try self.writeBin(stream, inst),
1296
1297 .alloc,
1298 .alloc_mut,
1299 .alloc_inferred,
1300 .alloc_inferred_mut,
1301 .anyframe_type,
1302 .indexable_ptr_len,
1303 .@"await",
1304 .bit_not,
1305 .call_none,
1306 .compile_error,
1307 .deref_node,
1308 .ensure_result_used,
1309 .ensure_result_non_error,
1310 .import,
1311 .ptrtoint,
1312 .ret_node,
1313 .set_eval_branch_quota,
1314 .resolve_inferred_alloc,
1315 .suspend_block_one,
1316 => try self.writeUnNode(stream, inst),
1317
1318 .bool_not,
1319 .break_void_tok,
1320 .is_non_null,
1321 .is_null,
1322 .is_non_null_ptr,
1323 .is_null_ptr,
1324 .is_err,
1325 .is_err_ptr,
1326 .ref,
1327 .ret_tok,
1328 .typeof,
1329 .optional_type,
1330 .optional_type_from_ptr_elem,
1331 .optional_payload_safe,
1332 .optional_payload_unsafe,
1333 .optional_payload_safe_ptr,
1334 .optional_payload_unsafe_ptr,
1335 .err_union_payload_safe,
1336 .err_union_payload_unsafe,
1337 .err_union_payload_safe_ptr,
1338 .err_union_payload_unsafe_ptr,
1339 .err_union_code,
1340 .err_union_code_ptr,
1341 .ensure_err_payload_void,
1342 => try self.writeUnTok(stream, inst),
1343
1344 .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
1345 .@"const" => try self.writeConst(stream, inst),
1346 .param_type => try self.writeParamType(stream, inst),
1347 .ptr_type_simple => try self.writePtrTypeSimple(stream, inst),
1348 .ptr_type => try self.writePtrType(stream, inst),
1349 .int => try self.writeInt(stream, inst),
1350 .str => try self.writeStr(stream, inst),
1351
1352 .@"asm",
1353 .asm_volatile,
1354 .block,
1355 .block_flat,
1356 .block_comptime,
1357 .block_comptime_flat,
1358 .call,
1359 .call_async_kw,
1360 .call_no_async,
1361 .call_compile_time,
1362 .compile_log,
1363 .condbr,
1364 .elem_ptr_node,
1365 .elem_val_node,
1366 .field_ptr,
1367 .field_val,
1368 .field_ptr_named,
1369 .field_val_named,
1370 .floatcast,
1371 .loop,
1372 .slice_start,
1373 .slice_end,
1374 .slice_sentinel,
1375 .typeof_peer,
1376 .suspend_block,
1377 => try self.writePlNode(stream, inst),
1378
1379 .breakpoint,
1380 .dbg_stmt_node,
1381 .ret_ptr,
1382 .ret_type,
1383 .unreachable_unsafe,
1384 .unreachable_safe,
1385 => try self.writeNode(stream, inst),
1386
1387 .decl_ref,
1388 .decl_val,
1389 => try self.writeDecl(stream, inst),
1390
1391 .error_value,
1392 .enum_literal,
1393 => try self.writeStrTok(stream, inst),
1394
1395 .fn_type => try self.writeFnType(stream, inst, false),
1396 .fn_type_cc => try self.writeFnTypeCc(stream, inst, false),
1397 .fn_type_var_args => try self.writeFnType(stream, inst, true),
1398 .fn_type_cc_var_args => try self.writeFnTypeCc(stream, inst, true),
1399
1400 .enum_literal_small => try self.writeSmallStr(stream, inst),
1401
1402 .bitcast,
1403 .bitcast_ref,
1404 .bitcast_result_ptr,
1405 .error_union_type,
1406 .error_set,
1407 .nosuspend_await,
1408 .@"resume",
1409 .store,
1410 .store_to_block_ptr,
1411 .store_to_inferred_ptr,
1412 => try stream.writeAll("TODO)"),
1413 }
1414 }
1415
1416 fn writeBin(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1417 const inst_data = self.code.instructions.items(.data)[inst].bin;
1418 try self.writeInstRef(stream, inst_data.lhs);
1419 try stream.writeAll(", ");
1420 try self.writeInstRef(stream, inst_data.rhs);
1421 try stream.writeByte(')');
1422 }
1423
1424 fn writeUnNode(
1425 self: *Writer,
1426 stream: anytype,
1427 inst: Inst.Index,
1428 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1429 const inst_data = self.code.instructions.items(.data)[inst].un_node;
1430 try self.writeInstRef(stream, inst_data.operand);
1431 try stream.writeAll(") ");
1432 try self.writeSrc(stream, inst_data.src());
1433 }
1434
1435 fn writeUnTok(
1436 self: *Writer,
1437 stream: anytype,
1438 inst: Inst.Index,
1439 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1440 const inst_data = self.code.instructions.items(.data)[inst].un_tok;
1441 try self.writeInstRef(stream, inst_data.operand);
1442 try stream.writeAll(") ");
1443 try self.writeSrc(stream, inst_data.src());
1444 }
1445
1446 fn writeArrayTypeSentinel(
1447 self: *Writer,
1448 stream: anytype,
1449 inst: Inst.Index,
1450 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1451 const inst_data = self.code.instructions.items(.data)[inst].array_type_sentinel;
1452 try stream.writeAll("TODO)");
1453 }
1454
1455 fn writeConst(
1456 self: *Writer,
1457 stream: anytype,
1458 inst: Inst.Index,
1459 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1460 const inst_data = self.code.instructions.items(.data)[inst].@"const";
1461 try stream.writeAll("TODO)");
1462 }
1463
1464 fn writeParamType(
1465 self: *Writer,
1466 stream: anytype,
1467 inst: Inst.Index,
1468 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1469 const inst_data = self.code.instructions.items(.data)[inst].param_type;
1470 try stream.writeAll("TODO)");
1471 }
1472
1473 fn writePtrTypeSimple(
1474 self: *Writer,
1475 stream: anytype,
1476 inst: Inst.Index,
1477 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1478 const inst_data = self.code.instructions.items(.data)[inst].ptr_type_simple;
1479 try stream.writeAll("TODO)");
1480 }
1481
1482 fn writePtrType(
1483 self: *Writer,
1484 stream: anytype,
1485 inst: Inst.Index,
1486 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1487 const inst_data = self.code.instructions.items(.data)[inst].ptr_type;
1488 try stream.writeAll("TODO)");
1489 }
1490
1491 fn writeInt(
1492 self: *Writer,
1493 stream: anytype,
1494 inst: Inst.Index,
1495 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1496 const inst_data = self.code.instructions.items(.data)[inst].int;
1497 try stream.print("{d})", .{inst_data});
1498 }
1499
1500 fn writeStr(
1501 self: *Writer,
1502 stream: anytype,
1503 inst: Inst.Index,
1504 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1505 const inst_data = self.code.instructions.items(.data)[inst].str;
1506 const str = inst_data.get(self.code);
1507 try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)});
1508 }
1509
1510 fn writePlNode(
1511 self: *Writer,
1512 stream: anytype,
1513 inst: Inst.Index,
1514 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1515 const inst_data = self.code.instructions.items(.data)[inst].pl_node;
1516 try stream.writeAll("TODO) ");
1517 try self.writeSrc(stream, inst_data.src());
1518 }
1519
1520 fn writeNode(
1521 self: *Writer,
1522 stream: anytype,
1523 inst: Inst.Index,
1524 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1525 const src_node = self.code.instructions.items(.data)[inst].node;
1526 const src: LazySrcLoc = .{ .node_offset = src_node };
1527 try stream.writeAll(") ");
1528 try self.writeSrc(stream, src);
1529 }
1530
1531 fn writeDecl(
1532 self: *Writer,
1533 stream: anytype,
1534 inst: Inst.Index,
1535 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1536 const inst_data = self.code.instructions.items(.data)[inst].decl;
1537 try stream.writeAll("TODO)");
1538 }
1539
1540 fn writeStrTok(
1541 self: *Writer,
1542 stream: anytype,
1543 inst: Inst.Index,
1544 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1545 const inst_data = self.code.instructions.items(.data)[inst].str_tok;
1546 const str = inst_data.get(self.code);
1547 try stream.print("\"{}\") ", .{std.zig.fmtEscapes(str)});
1548 try self.writeSrc(stream, inst_data.src());
1549 }
1550
1551 fn writeFnType(
1552 self: *Writer,
1553 stream: anytype,
1554 inst: Inst.Index,
1555 var_args: bool,
1556 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1557 const inst_data = self.code.instructions.items(.data)[inst].fn_type;
1558 const extra = self.code.extraData(Inst.FnType, inst_data.payload_index);
1559 const param_types = self.code.extra[extra.end..][0..extra.data.param_types_len];
1560 const cc: Inst.Ref = 0;
1561 return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, cc);
1562 }
1563
1564 fn writeFnTypeCc(
1565 self: *Writer,
1566 stream: anytype,
1567 inst: Inst.Index,
1568 var_args: bool,
1569 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1570 const inst_data = self.code.instructions.items(.data)[inst].fn_type;
1571 const extra = self.code.extraData(Inst.FnTypeCc, inst_data.payload_index);
1572 const param_types = self.code.extra[extra.end..][0..extra.data.param_types_len];
1573 const cc = extra.data.cc;
1574 return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, cc);
1575 }
1576
1577 fn writeFnTypeCommon(
1578 self: *Writer,
1579 stream: anytype,
1580 param_types: []const Inst.Ref,
1581 ret_ty: Inst.Ref,
1582 var_args: bool,
1583 cc: Inst.Ref,
1584 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1585 try stream.writeAll("(");
1586 for (param_types) |param_type, i| {
1587 if (i != 0) try stream.writeAll(", ");
1588 try self.writeInstRef(stream, param_type);
1589 }
1590 try stream.writeAll("), ");
1591 try self.writeInstRef(stream, ret_ty);
1592 try self.writeOptionalInstRef(stream, ", cc=", cc);
1593 try self.writeFlag(stream, ", var_args", var_args);
1594 try stream.writeAll(")");
1595 }
1596
1597 fn writeSmallStr(
1598 self: *Writer,
1599 stream: anytype,
1600 inst: Inst.Index,
1601 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
1602 const str = self.code.instructions.items(.data)[inst].small_str.get();
1603 try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)});
1604 }
1605
1606 fn writeInstRef(self: *Writer, stream: anytype, inst: Inst.Index) !void {
1607 var i: usize = inst;
1608
1609 if (i < const_inst_list.len) {
1610 return stream.print("@{d}", .{i});
1611 }
1612 i -= const_inst_list.len;
1613
1614 if (i < self.param_count) {
1615 return stream.print("${d}", .{i});
1616 }
1617 i -= self.param_count;
1618
1619 return stream.print("%{d}", .{i});
1620 }
1621
1622 fn writeOptionalInstRef(
1623 self: *Writer,
1624 stream: anytype,
1625 prefix: []const u8,
1626 inst: Inst.Index,
1627 ) !void {
1628 if (inst == 0) return;
1629 try stream.writeAll(prefix);
1630 try self.writeInstRef(stream, inst);
1631 }
1632
1633 fn writeFlag(
1634 self: *Writer,
1635 stream: anytype,
1636 name: []const u8,
1637 flag: bool,
1638 ) !void {
1639 if (!flag) return;
1640 try stream.writeAll(name);
1641 }
1642
1643 fn writeSrc(self: *Writer, stream: anytype, src: LazySrcLoc) !void {
1644 try stream.print("TODOsrc({s})", .{@tagName(src)});
1645 }
1646};