| author | |
| committer | |
| log | eadbee2041bba1cd03b24d8f30161025af8e3590 |
| tree | aebad285c7cd852fcc1c9d62f3beeb4395c6d04e |
| parent | 12c10139e3e0166e91d2dbb1801c2054ca12d413 |
* some instructions are not implemented yet
* fix off-by-1 in Air.getMainBody
* Compilation: use `@import("builtin")` rather than `std.builtin`
for the values that are different for different build configurations.
* Sema: avoid calling `addType` in between
air_instructions.ensureUnusedCapacity and corresponding
appendAssumeCapacity because it can possibly add an instruction.
* Value: functions print their names7 files changed, 307 insertions(+), 574 deletions(-)
BRANCH_TODO deleted-566| ... | @@ -1,566 +0,0 @@ | ||
| 1 | * be sure to test debug info of parameters | ||
| 2 | |||
| 3 | |||
| 4 | pub fn specialOperandDeaths(self: Inst) bool { | ||
| 5 | return (self.deaths & (1 << deaths_bits)) != 0; | ||
| 6 | } | ||
| 7 | |||
| 8 | /// Returns `null` if runtime-known. | ||
| 9 | /// Should be called by codegen, not by Sema. Sema functions should call | ||
| 10 | /// `resolvePossiblyUndefinedValue` or `resolveDefinedValue` instead. | ||
| 11 | /// TODO audit Sema code for violations to the above guidance. | ||
| 12 | pub fn value(base: *Inst) ?Value { | ||
| 13 | if (base.ty.onePossibleValue()) |opv| return opv; | ||
| 14 | |||
| 15 | const inst = base.castTag(.constant) orelse return null; | ||
| 16 | return inst.val; | ||
| 17 | } | ||
| 18 | |||
| 19 | |||
| 20 | |||
| 21 | /// For debugging purposes, prints a function representation to stderr. | ||
| 22 | pub fn dumpFn(old_module: Module, module_fn: *Module.Fn) void { | ||
| 23 | const allocator = old_module.gpa; | ||
| 24 | var ctx: DumpAir = .{ | ||
| 25 | .allocator = allocator, | ||
| 26 | .arena = std.heap.ArenaAllocator.init(allocator), | ||
| 27 | .old_module = &old_module, | ||
| 28 | .module_fn = module_fn, | ||
| 29 | .indent = 2, | ||
| 30 | .inst_table = DumpAir.InstTable.init(allocator), | ||
| 31 | .partial_inst_table = DumpAir.InstTable.init(allocator), | ||
| 32 | .const_table = DumpAir.InstTable.init(allocator), | ||
| 33 | }; | ||
| 34 | defer ctx.inst_table.deinit(); | ||
| 35 | defer ctx.partial_inst_table.deinit(); | ||
| 36 | defer ctx.const_table.deinit(); | ||
| 37 | defer ctx.arena.deinit(); | ||
| 38 | |||
| 39 | switch (module_fn.state) { | ||
| 40 | .queued => std.debug.print("(queued)", .{}), | ||
| 41 | .inline_only => std.debug.print("(inline_only)", .{}), | ||
| 42 | .in_progress => std.debug.print("(in_progress)", .{}), | ||
| 43 | .sema_failure => std.debug.print("(sema_failure)", .{}), | ||
| 44 | .dependency_failure => std.debug.print("(dependency_failure)", .{}), | ||
| 45 | .success => { | ||
| 46 | const writer = std.io.getStdErr().writer(); | ||
| 47 | ctx.dump(module_fn.body, writer) catch @panic("failed to dump AIR"); | ||
| 48 | }, | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | const DumpAir = struct { | ||
| 53 | allocator: *std.mem.Allocator, | ||
| 54 | arena: std.heap.ArenaAllocator, | ||
| 55 | old_module: *const Module, | ||
| 56 | module_fn: *Module.Fn, | ||
| 57 | indent: usize, | ||
| 58 | inst_table: InstTable, | ||
| 59 | partial_inst_table: InstTable, | ||
| 60 | const_table: InstTable, | ||
| 61 | next_index: usize = 0, | ||
| 62 | next_partial_index: usize = 0, | ||
| 63 | next_const_index: usize = 0, | ||
| 64 | |||
| 65 | const InstTable = std.AutoArrayHashMap(*Inst, usize); | ||
| 66 | |||
| 67 | /// TODO: Improve this code to include a stack of Body and store the instructions | ||
| 68 | /// in there. Now we are putting all the instructions in a function local table, | ||
| 69 | /// however instructions that are in a Body can be thown away when the Body ends. | ||
| 70 | fn dump(dtz: *DumpAir, body: Body, writer: std.fs.File.Writer) !void { | ||
| 71 | // First pass to pre-populate the table so that we can show even invalid references. | ||
| 72 | // Must iterate the same order we iterate the second time. | ||
| 73 | // We also look for constants and put them in the const_table. | ||
| 74 | try dtz.fetchInstsAndResolveConsts(body); | ||
| 75 | |||
| 76 | std.debug.print("Module.Function(name={s}):\n", .{dtz.module_fn.owner_decl.name}); | ||
| 77 | |||
| 78 | var it = dtz.const_table.iterator(); | ||
| 79 | while (it.next()) |entry| { | ||
| 80 | const constant = entry.key_ptr.*.castTag(.constant).?; | ||
| 81 | try writer.print(" @{d}: {} = {};\n", .{ | ||
| 82 | entry.value_ptr.*, constant.base.ty, constant.val, | ||
| 83 | }); | ||
| 84 | } | ||
| 85 | |||
| 86 | return dtz.dumpBody(body, writer); | ||
| 87 | } | ||
| 88 | |||
| 89 | fn fetchInstsAndResolveConsts(dtz: *DumpAir, body: Body) error{OutOfMemory}!void { | ||
| 90 | for (body.instructions) |inst| { | ||
| 91 | try dtz.inst_table.put(inst, dtz.next_index); | ||
| 92 | dtz.next_index += 1; | ||
| 93 | switch (inst.tag) { | ||
| 94 | .alloc, | ||
| 95 | .retvoid, | ||
| 96 | .unreach, | ||
| 97 | .breakpoint, | ||
| 98 | .dbg_stmt, | ||
| 99 | .arg, | ||
| 100 | => {}, | ||
| 101 | |||
| 102 | .ref, | ||
| 103 | .ret, | ||
| 104 | .bitcast, | ||
| 105 | .not, | ||
| 106 | .is_non_null, | ||
| 107 | .is_non_null_ptr, | ||
| 108 | .is_null, | ||
| 109 | .is_null_ptr, | ||
| 110 | .is_err, | ||
| 111 | .is_non_err, | ||
| 112 | .is_err_ptr, | ||
| 113 | .is_non_err_ptr, | ||
| 114 | .ptrtoint, | ||
| 115 | .floatcast, | ||
| 116 | .intcast, | ||
| 117 | .load, | ||
| 118 | .optional_payload, | ||
| 119 | .optional_payload_ptr, | ||
| 120 | .wrap_optional, | ||
| 121 | .wrap_errunion_payload, | ||
| 122 | .wrap_errunion_err, | ||
| 123 | .unwrap_errunion_payload, | ||
| 124 | .unwrap_errunion_err, | ||
| 125 | .unwrap_errunion_payload_ptr, | ||
| 126 | .unwrap_errunion_err_ptr, | ||
| 127 | => { | ||
| 128 | const un_op = inst.cast(Inst.UnOp).?; | ||
| 129 | try dtz.findConst(un_op.operand); | ||
| 130 | }, | ||
| 131 | |||
| 132 | .add, | ||
| 133 | .addwrap, | ||
| 134 | .sub, | ||
| 135 | .subwrap, | ||
| 136 | .mul, | ||
| 137 | .mulwrap, | ||
| 138 | .div, | ||
| 139 | .cmp_lt, | ||
| 140 | .cmp_lte, | ||
| 141 | .cmp_eq, | ||
| 142 | .cmp_gte, | ||
| 143 | .cmp_gt, | ||
| 144 | .cmp_neq, | ||
| 145 | .store, | ||
| 146 | .bool_and, | ||
| 147 | .bool_or, | ||
| 148 | .bit_and, | ||
| 149 | .bit_or, | ||
| 150 | .xor, | ||
| 151 | => { | ||
| 152 | const bin_op = inst.cast(Inst.BinOp).?; | ||
| 153 | try dtz.findConst(bin_op.lhs); | ||
| 154 | try dtz.findConst(bin_op.rhs); | ||
| 155 | }, | ||
| 156 | |||
| 157 | .br => { | ||
| 158 | const br = inst.castTag(.br).?; | ||
| 159 | try dtz.findConst(&br.block.base); | ||
| 160 | try dtz.findConst(br.operand); | ||
| 161 | }, | ||
| 162 | |||
| 163 | .br_block_flat => { | ||
| 164 | const br_block_flat = inst.castTag(.br_block_flat).?; | ||
| 165 | try dtz.findConst(&br_block_flat.block.base); | ||
| 166 | try dtz.fetchInstsAndResolveConsts(br_block_flat.body); | ||
| 167 | }, | ||
| 168 | |||
| 169 | .br_void => { | ||
| 170 | const br_void = inst.castTag(.br_void).?; | ||
| 171 | try dtz.findConst(&br_void.block.base); | ||
| 172 | }, | ||
| 173 | |||
| 174 | .block => { | ||
| 175 | const block = inst.castTag(.block).?; | ||
| 176 | try dtz.fetchInstsAndResolveConsts(block.body); | ||
| 177 | }, | ||
| 178 | |||
| 179 | .condbr => { | ||
| 180 | const condbr = inst.castTag(.condbr).?; | ||
| 181 | try dtz.findConst(condbr.condition); | ||
| 182 | try dtz.fetchInstsAndResolveConsts(condbr.then_body); | ||
| 183 | try dtz.fetchInstsAndResolveConsts(condbr.else_body); | ||
| 184 | }, | ||
| 185 | .switchbr => { | ||
| 186 | const switchbr = inst.castTag(.switchbr).?; | ||
| 187 | try dtz.findConst(switchbr.target); | ||
| 188 | try dtz.fetchInstsAndResolveConsts(switchbr.else_body); | ||
| 189 | for (switchbr.cases) |case| { | ||
| 190 | try dtz.fetchInstsAndResolveConsts(case.body); | ||
| 191 | } | ||
| 192 | }, | ||
| 193 | |||
| 194 | .loop => { | ||
| 195 | const loop = inst.castTag(.loop).?; | ||
| 196 | try dtz.fetchInstsAndResolveConsts(loop.body); | ||
| 197 | }, | ||
| 198 | .call => { | ||
| 199 | const call = inst.castTag(.call).?; | ||
| 200 | try dtz.findConst(call.func); | ||
| 201 | for (call.args) |arg| { | ||
| 202 | try dtz.findConst(arg); | ||
| 203 | } | ||
| 204 | }, | ||
| 205 | .struct_field_ptr => { | ||
| 206 | const struct_field_ptr = inst.castTag(.struct_field_ptr).?; | ||
| 207 | try dtz.findConst(struct_field_ptr.struct_ptr); | ||
| 208 | }, | ||
| 209 | |||
| 210 | // TODO fill out this debug printing | ||
| 211 | .assembly, | ||
| 212 | .constant, | ||
| 213 | .varptr, | ||
| 214 | => {}, | ||
| 215 | } | ||
| 216 | } | ||
| 217 | } | ||
| 218 | |||
| 219 | fn dumpBody(dtz: *DumpAir, body: Body, writer: std.fs.File.Writer) (std.fs.File.WriteError || error{OutOfMemory})!void { | ||
| 220 | for (body.instructions) |inst| { | ||
| 221 | const my_index = dtz.next_partial_index; | ||
| 222 | try dtz.partial_inst_table.put(inst, my_index); | ||
| 223 | dtz.next_partial_index += 1; | ||
| 224 | |||
| 225 | try writer.writeByteNTimes(' ', dtz.indent); | ||
| 226 | try writer.print("%{d}: {} = {s}(", .{ | ||
| 227 | my_index, inst.ty, @tagName(inst.tag), | ||
| 228 | }); | ||
| 229 | switch (inst.tag) { | ||
| 230 | .alloc, | ||
| 231 | .retvoid, | ||
| 232 | .unreach, | ||
| 233 | .breakpoint, | ||
| 234 | .dbg_stmt, | ||
| 235 | => try writer.writeAll(")\n"), | ||
| 236 | |||
| 237 | .ref, | ||
| 238 | .ret, | ||
| 239 | .bitcast, | ||
| 240 | .not, | ||
| 241 | .is_non_null, | ||
| 242 | .is_non_null_ptr, | ||
| 243 | .is_null, | ||
| 244 | .is_null_ptr, | ||
| 245 | .is_err, | ||
| 246 | .is_err_ptr, | ||
| 247 | .is_non_err, | ||
| 248 | .is_non_err_ptr, | ||
| 249 | .ptrtoint, | ||
| 250 | .floatcast, | ||
| 251 | .intcast, | ||
| 252 | .load, | ||
| 253 | .optional_payload, | ||
| 254 | .optional_payload_ptr, | ||
| 255 | .wrap_optional, | ||
| 256 | .wrap_errunion_err, | ||
| 257 | .wrap_errunion_payload, | ||
| 258 | .unwrap_errunion_err, | ||
| 259 | .unwrap_errunion_payload, | ||
| 260 | .unwrap_errunion_payload_ptr, | ||
| 261 | .unwrap_errunion_err_ptr, | ||
| 262 | => { | ||
| 263 | const un_op = inst.cast(Inst.UnOp).?; | ||
| 264 | const kinky = try dtz.writeInst(writer, un_op.operand); | ||
| 265 | if (kinky != null) { | ||
| 266 | try writer.writeAll(") // Instruction does not dominate all uses!\n"); | ||
| 267 | } else { | ||
| 268 | try writer.writeAll(")\n"); | ||
| 269 | } | ||
| 270 | }, | ||
| 271 | |||
| 272 | .add, | ||
| 273 | .addwrap, | ||
| 274 | .sub, | ||
| 275 | .subwrap, | ||
| 276 | .mul, | ||
| 277 | .mulwrap, | ||
| 278 | .div, | ||
| 279 | .cmp_lt, | ||
| 280 | .cmp_lte, | ||
| 281 | .cmp_eq, | ||
| 282 | .cmp_gte, | ||
| 283 | .cmp_gt, | ||
| 284 | .cmp_neq, | ||
| 285 | .store, | ||
| 286 | .bool_and, | ||
| 287 | .bool_or, | ||
| 288 | .bit_and, | ||
| 289 | .bit_or, | ||
| 290 | .xor, | ||
| 291 | => { | ||
| 292 | const bin_op = inst.cast(Inst.BinOp).?; | ||
| 293 | |||
| 294 | const lhs_kinky = try dtz.writeInst(writer, bin_op.lhs); | ||
| 295 | try writer.writeAll(", "); | ||
| 296 | const rhs_kinky = try dtz.writeInst(writer, bin_op.rhs); | ||
| 297 | |||
| 298 | if (lhs_kinky != null or rhs_kinky != null) { | ||
| 299 | try writer.writeAll(") // Instruction does not dominate all uses!"); | ||
| 300 | if (lhs_kinky) |lhs| { | ||
| 301 | try writer.print(" %{d}", .{lhs}); | ||
| 302 | } | ||
| 303 | if (rhs_kinky) |rhs| { | ||
| 304 | try writer.print(" %{d}", .{rhs}); | ||
| 305 | } | ||
| 306 | try writer.writeAll("\n"); | ||
| 307 | } else { | ||
| 308 | try writer.writeAll(")\n"); | ||
| 309 | } | ||
| 310 | }, | ||
| 311 | |||
| 312 | .arg => { | ||
| 313 | const arg = inst.castTag(.arg).?; | ||
| 314 | try writer.print("{s})\n", .{arg.name}); | ||
| 315 | }, | ||
| 316 | |||
| 317 | .br => { | ||
| 318 | const br = inst.castTag(.br).?; | ||
| 319 | |||
| 320 | const lhs_kinky = try dtz.writeInst(writer, &br.block.base); | ||
| 321 | try writer.writeAll(", "); | ||
| 322 | const rhs_kinky = try dtz.writeInst(writer, br.operand); | ||
| 323 | |||
| 324 | if (lhs_kinky != null or rhs_kinky != null) { | ||
| 325 | try writer.writeAll(") // Instruction does not dominate all uses!"); | ||
| 326 | if (lhs_kinky) |lhs| { | ||
| 327 | try writer.print(" %{d}", .{lhs}); | ||
| 328 | } | ||
| 329 | if (rhs_kinky) |rhs| { | ||
| 330 | try writer.print(" %{d}", .{rhs}); | ||
| 331 | } | ||
| 332 | try writer.writeAll("\n"); | ||
| 333 | } else { | ||
| 334 | try writer.writeAll(")\n"); | ||
| 335 | } | ||
| 336 | }, | ||
| 337 | |||
| 338 | .br_block_flat => { | ||
| 339 | const br_block_flat = inst.castTag(.br_block_flat).?; | ||
| 340 | const block_kinky = try dtz.writeInst(writer, &br_block_flat.block.base); | ||
| 341 | if (block_kinky != null) { | ||
| 342 | try writer.writeAll(", { // Instruction does not dominate all uses!\n"); | ||
| 343 | } else { | ||
| 344 | try writer.writeAll(", {\n"); | ||
| 345 | } | ||
| 346 | |||
| 347 | const old_indent = dtz.indent; | ||
| 348 | dtz.indent += 2; | ||
| 349 | try dtz.dumpBody(br_block_flat.body, writer); | ||
| 350 | dtz.indent = old_indent; | ||
| 351 | |||
| 352 | try writer.writeByteNTimes(' ', dtz.indent); | ||
| 353 | try writer.writeAll("})\n"); | ||
| 354 | }, | ||
| 355 | |||
| 356 | .br_void => { | ||
| 357 | const br_void = inst.castTag(.br_void).?; | ||
| 358 | const kinky = try dtz.writeInst(writer, &br_void.block.base); | ||
| 359 | if (kinky) |_| { | ||
| 360 | try writer.writeAll(") // Instruction does not dominate all uses!\n"); | ||
| 361 | } else { | ||
| 362 | try writer.writeAll(")\n"); | ||
| 363 | } | ||
| 364 | }, | ||
| 365 | |||
| 366 | .block => { | ||
| 367 | const block = inst.castTag(.block).?; | ||
| 368 | |||
| 369 | try writer.writeAll("{\n"); | ||
| 370 | |||
| 371 | const old_indent = dtz.indent; | ||
| 372 | dtz.indent += 2; | ||
| 373 | try dtz.dumpBody(block.body, writer); | ||
| 374 | dtz.indent = old_indent; | ||
| 375 | |||
| 376 | try writer.writeByteNTimes(' ', dtz.indent); | ||
| 377 | try writer.writeAll("})\n"); | ||
| 378 | }, | ||
| 379 | |||
| 380 | .condbr => { | ||
| 381 | const condbr = inst.castTag(.condbr).?; | ||
| 382 | |||
| 383 | const condition_kinky = try dtz.writeInst(writer, condbr.condition); | ||
| 384 | if (condition_kinky != null) { | ||
| 385 | try writer.writeAll(", { // Instruction does not dominate all uses!\n"); | ||
| 386 | } else { | ||
| 387 | try writer.writeAll(", {\n"); | ||
| 388 | } | ||
| 389 | |||
| 390 | const old_indent = dtz.indent; | ||
| 391 | dtz.indent += 2; | ||
| 392 | try dtz.dumpBody(condbr.then_body, writer); | ||
| 393 | |||
| 394 | try writer.writeByteNTimes(' ', old_indent); | ||
| 395 | try writer.writeAll("}, {\n"); | ||
| 396 | |||
| 397 | try dtz.dumpBody(condbr.else_body, writer); | ||
| 398 | dtz.indent = old_indent; | ||
| 399 | |||
| 400 | try writer.writeByteNTimes(' ', old_indent); | ||
| 401 | try writer.writeAll("})\n"); | ||
| 402 | }, | ||
| 403 | |||
| 404 | .switchbr => { | ||
| 405 | const switchbr = inst.castTag(.switchbr).?; | ||
| 406 | |||
| 407 | const condition_kinky = try dtz.writeInst(writer, switchbr.target); | ||
| 408 | if (condition_kinky != null) { | ||
| 409 | try writer.writeAll(", { // Instruction does not dominate all uses!\n"); | ||
| 410 | } else { | ||
| 411 | try writer.writeAll(", {\n"); | ||
| 412 | } | ||
| 413 | const old_indent = dtz.indent; | ||
| 414 | |||
| 415 | if (switchbr.else_body.instructions.len != 0) { | ||
| 416 | dtz.indent += 2; | ||
| 417 | try dtz.dumpBody(switchbr.else_body, writer); | ||
| 418 | |||
| 419 | try writer.writeByteNTimes(' ', old_indent); | ||
| 420 | try writer.writeAll("}, {\n"); | ||
| 421 | dtz.indent = old_indent; | ||
| 422 | } | ||
| 423 | for (switchbr.cases) |case| { | ||
| 424 | dtz.indent += 2; | ||
| 425 | try dtz.dumpBody(case.body, writer); | ||
| 426 | |||
| 427 | try writer.writeByteNTimes(' ', old_indent); | ||
| 428 | try writer.writeAll("}, {\n"); | ||
| 429 | dtz.indent = old_indent; | ||
| 430 | } | ||
| 431 | |||
| 432 | try writer.writeByteNTimes(' ', old_indent); | ||
| 433 | try writer.writeAll("})\n"); | ||
| 434 | }, | ||
| 435 | |||
| 436 | .loop => { | ||
| 437 | const loop = inst.castTag(.loop).?; | ||
| 438 | |||
| 439 | try writer.writeAll("{\n"); | ||
| 440 | |||
| 441 | const old_indent = dtz.indent; | ||
| 442 | dtz.indent += 2; | ||
| 443 | try dtz.dumpBody(loop.body, writer); | ||
| 444 | dtz.indent = old_indent; | ||
| 445 | |||
| 446 | try writer.writeByteNTimes(' ', dtz.indent); | ||
| 447 | try writer.writeAll("})\n"); | ||
| 448 | }, | ||
| 449 | |||
| 450 | .call => { | ||
| 451 | const call = inst.castTag(.call).?; | ||
| 452 | |||
| 453 | const args_kinky = try dtz.allocator.alloc(?usize, call.args.len); | ||
| 454 | defer dtz.allocator.free(args_kinky); | ||
| 455 | std.mem.set(?usize, args_kinky, null); | ||
| 456 | var any_kinky_args = false; | ||
| 457 | |||
| 458 | const func_kinky = try dtz.writeInst(writer, call.func); | ||
| 459 | |||
| 460 | for (call.args) |arg, i| { | ||
| 461 | try writer.writeAll(", "); | ||
| 462 | |||
| 463 | args_kinky[i] = try dtz.writeInst(writer, arg); | ||
| 464 | any_kinky_args = any_kinky_args or args_kinky[i] != null; | ||
| 465 | } | ||
| 466 | |||
| 467 | if (func_kinky != null or any_kinky_args) { | ||
| 468 | try writer.writeAll(") // Instruction does not dominate all uses!"); | ||
| 469 | if (func_kinky) |func_index| { | ||
| 470 | try writer.print(" %{d}", .{func_index}); | ||
| 471 | } | ||
| 472 | for (args_kinky) |arg_kinky| { | ||
| 473 | if (arg_kinky) |arg_index| { | ||
| 474 | try writer.print(" %{d}", .{arg_index}); | ||
| 475 | } | ||
| 476 | } | ||
| 477 | try writer.writeAll("\n"); | ||
| 478 | } else { | ||
| 479 | try writer.writeAll(")\n"); | ||
| 480 | } | ||
| 481 | }, | ||
| 482 | |||
| 483 | .struct_field_ptr => { | ||
| 484 | const struct_field_ptr = inst.castTag(.struct_field_ptr).?; | ||
| 485 | const kinky = try dtz.writeInst(writer, struct_field_ptr.struct_ptr); | ||
| 486 | if (kinky != null) { | ||
| 487 | try writer.print("{d}) // Instruction does not dominate all uses!\n", .{ | ||
| 488 | struct_field_ptr.field_index, | ||
| 489 | }); | ||
| 490 | } else { | ||
| 491 | try writer.print("{d})\n", .{struct_field_ptr.field_index}); | ||
| 492 | } | ||
| 493 | }, | ||
| 494 | |||
| 495 | // TODO fill out this debug printing | ||
| 496 | .assembly, | ||
| 497 | .constant, | ||
| 498 | .varptr, | ||
| 499 | => { | ||
| 500 | try writer.writeAll("!TODO!)\n"); | ||
| 501 | }, | ||
| 502 | } | ||
| 503 | } | ||
| 504 | } | ||
| 505 | |||
| 506 | fn writeInst(dtz: *DumpAir, writer: std.fs.File.Writer, inst: *Inst) !?usize { | ||
| 507 | if (dtz.partial_inst_table.get(inst)) |operand_index| { | ||
| 508 | try writer.print("%{d}", .{operand_index}); | ||
| 509 | return null; | ||
| 510 | } else if (dtz.const_table.get(inst)) |operand_index| { | ||
| 511 | try writer.print("@{d}", .{operand_index}); | ||
| 512 | return null; | ||
| 513 | } else if (dtz.inst_table.get(inst)) |operand_index| { | ||
| 514 | try writer.print("%{d}", .{operand_index}); | ||
| 515 | return operand_index; | ||
| 516 | } else { | ||
| 517 | try writer.writeAll("!BADREF!"); | ||
| 518 | return null; | ||
| 519 | } | ||
| 520 | } | ||
| 521 | |||
| 522 | fn findConst(dtz: *DumpAir, operand: *Inst) !void { | ||
| 523 | if (operand.tag == .constant) { | ||
| 524 | try dtz.const_table.put(operand, dtz.next_const_index); | ||
| 525 | dtz.next_const_index += 1; | ||
| 526 | } | ||
| 527 | } | ||
| 528 | }; | ||
| 529 | |||
| 530 | pub fn dumpInst(mod: *Module, scope: *Scope, inst: *ir.Inst) void { | ||
| 531 | const zir_module = scope.namespace(); | ||
| 532 | const source = zir_module.getSource(mod) catch @panic("dumpInst failed to get source"); | ||
| 533 | const loc = std.zig.findLineColumn(source, inst.src); | ||
| 534 | if (inst.tag == .constant) { | ||
| 535 | std.debug.print("constant ty={} val={} src={s}:{d}:{d}\n", .{ | ||
| 536 | inst.ty, | ||
| 537 | inst.castTag(.constant).?.val, | ||
| 538 | zir_module.subFilePath(), | ||
| 539 | loc.line + 1, | ||
| 540 | loc.column + 1, | ||
| 541 | }); | ||
| 542 | } else if (inst.deaths == 0) { | ||
| 543 | std.debug.print("{s} ty={} src={s}:{d}:{d}\n", .{ | ||
| 544 | @tagName(inst.tag), | ||
| 545 | inst.ty, | ||
| 546 | zir_module.subFilePath(), | ||
| 547 | loc.line + 1, | ||
| 548 | loc.column + 1, | ||
| 549 | }); | ||
| 550 | } else { | ||
| 551 | std.debug.print("{s} ty={} deaths={b} src={s}:{d}:{d}\n", .{ | ||
| 552 | @tagName(inst.tag), | ||
| 553 | inst.ty, | ||
| 554 | inst.deaths, | ||
| 555 | zir_module.subFilePath(), | ||
| 556 | loc.line + 1, | ||
| 557 | loc.column + 1, | ||
| 558 | }); | ||
| 559 | } | ||
| 560 | } | ||
| 561 | |||
| 562 | /// For debugging purposes. | ||
| 563 | pub fn dump(func: *Fn, mod: Module) void { | ||
| 564 | ir.dumpFn(mod, func); | ||
| 565 | } | ||
| 566 | |||
src/Air.zig+2-2| ... | @@ -374,8 +374,8 @@ pub const Asm = struct { | ... | @@ -374,8 +374,8 @@ pub const Asm = struct { |
| 374 | 374 | ||
| 375 | pub fn getMainBody(air: Air) []const Air.Inst.Index { | 375 | pub fn getMainBody(air: Air) []const Air.Inst.Index { |
| 376 | const body_index = air.extra[@enumToInt(ExtraIndex.main_block)]; | 376 | const body_index = air.extra[@enumToInt(ExtraIndex.main_block)]; |
| 377 | const body_len = air.extra[body_index]; | 377 | const extra = air.extraData(Block, body_index); |
| 378 | return air.extra[body_index..][0..body_len]; | 378 | return air.extra[extra.end..][0..extra.data.body_len]; |
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | pub fn getType(air: Air, inst: Air.Inst.Index) Type { | 381 | pub fn getType(air: Air, inst: Air.Inst.Index) Type { |
src/Compilation.zig+6-3| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const Compilation = @This(); | 1 | const Compilation = @This(); |
| 2 | 2 | ||
| 3 | const std = @import("std"); | 3 | const std = @import("std"); |
| 4 | const builtin = @import("builtin"); | ||
| 4 | const mem = std.mem; | 5 | const mem = std.mem; |
| 5 | const Allocator = std.mem.Allocator; | 6 | const Allocator = std.mem.Allocator; |
| 6 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| ... | @@ -907,7 +908,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -907,7 +908,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 907 | // comptime conditions | 908 | // comptime conditions |
| 908 | ((build_options.have_llvm and comptime std.Target.current.isDarwin()) and | 909 | ((build_options.have_llvm and comptime std.Target.current.isDarwin()) and |
| 909 | // runtime conditions | 910 | // runtime conditions |
| 910 | (use_lld and std.builtin.os.tag == .macos and options.target.isDarwin())); | 911 | (use_lld and builtin.os.tag == .macos and options.target.isDarwin())); |
| 911 | 912 | ||
| 912 | const sysroot = blk: { | 913 | const sysroot = blk: { |
| 913 | if (options.sysroot) |sysroot| { | 914 | if (options.sysroot) |sysroot| { |
| ... | @@ -2026,8 +2027,10 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor | ... | @@ -2026,8 +2027,10 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor |
| 2026 | var liveness = try Liveness.analyze(gpa, air, decl.namespace.file_scope.zir); | 2027 | var liveness = try Liveness.analyze(gpa, air, decl.namespace.file_scope.zir); |
| 2027 | defer liveness.deinit(gpa); | 2028 | defer liveness.deinit(gpa); |
| 2028 | 2029 | ||
| 2029 | if (std.builtin.mode == .Debug and self.verbose_air) { | 2030 | if (builtin.mode == .Debug and self.verbose_air) { |
| 2030 | @panic("TODO implement dumping AIR and liveness"); | 2031 | std.debug.print("# Begin Function AIR: {s}:\n", .{decl.name}); |
| 2032 | @import("print_air.zig").dump(gpa, air, liveness); | ||
| 2033 | std.debug.print("# End Function AIR: {s}:\n", .{decl.name}); | ||
| 2031 | } | 2034 | } |
| 2032 | 2035 | ||
| 2033 | assert(decl.ty.hasCodeGenBits()); | 2036 | assert(decl.ty.hasCodeGenBits()); |
src/Module.zig+2-1| ... | @@ -3551,7 +3551,8 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air { | ... | @@ -3551,7 +3551,8 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air { |
| 3551 | try sema.analyzeFnBody(&inner_block, func.zir_body_inst); | 3551 | try sema.analyzeFnBody(&inner_block, func.zir_body_inst); |
| 3552 | 3552 | ||
| 3553 | // Copy the block into place and mark that as the main block. | 3553 | // Copy the block into place and mark that as the main block. |
| 3554 | try sema.air_extra.ensureUnusedCapacity(gpa, inner_block.instructions.items.len + 1); | 3554 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + |
| 3555 | inner_block.instructions.items.len); | ||
| 3555 | const main_block_index = sema.addExtraAssumeCapacity(Air.Block{ | 3556 | const main_block_index = sema.addExtraAssumeCapacity(Air.Block{ |
| 3556 | .body_len = @intCast(u32, inner_block.instructions.items.len), | 3557 | .body_len = @intCast(u32, inner_block.instructions.items.len), |
| 3557 | }); | 3558 | }); |
src/Sema.zig+2-1| ... | @@ -2028,6 +2028,7 @@ fn analyzeBlockBody( | ... | @@ -2028,6 +2028,7 @@ fn analyzeBlockBody( |
| 2028 | refToIndex(coerced_operand).?); | 2028 | refToIndex(coerced_operand).?); |
| 2029 | 2029 | ||
| 2030 | // Convert the br operand to a block. | 2030 | // Convert the br operand to a block. |
| 2031 | const br_operand_ty_ref = try sema.addType(br_operand_ty); | ||
| 2031 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + | 2032 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + |
| 2032 | coerce_block.instructions.items.len); | 2033 | coerce_block.instructions.items.len); |
| 2033 | try sema.air_instructions.ensureUnusedCapacity(gpa, 2); | 2034 | try sema.air_instructions.ensureUnusedCapacity(gpa, 2); |
| ... | @@ -2037,7 +2038,7 @@ fn analyzeBlockBody( | ... | @@ -2037,7 +2038,7 @@ fn analyzeBlockBody( |
| 2037 | sema.air_instructions.appendAssumeCapacity(.{ | 2038 | sema.air_instructions.appendAssumeCapacity(.{ |
| 2038 | .tag = .block, | 2039 | .tag = .block, |
| 2039 | .data = .{ .ty_pl = .{ | 2040 | .data = .{ .ty_pl = .{ |
| 2040 | .ty = try sema.addType(br_operand_ty), | 2041 | .ty = br_operand_ty_ref, |
| 2041 | .payload = sema.addExtraAssumeCapacity(Air.Block{ | 2042 | .payload = sema.addExtraAssumeCapacity(Air.Block{ |
| 2042 | .body_len = @intCast(u32, coerce_block.instructions.items.len), | 2043 | .body_len = @intCast(u32, coerce_block.instructions.items.len), |
| 2043 | }), | 2044 | }), |
src/print_air.zig created+294| ... | @@ -0,0 +1,294 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const Allocator = std.mem.Allocator; | ||
| 3 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; | ||
| 4 | |||
| 5 | const Module = @import("Module.zig"); | ||
| 6 | const Value = @import("value.zig").Value; | ||
| 7 | const Air = @import("Air.zig"); | ||
| 8 | const Liveness = @import("Liveness.zig"); | ||
| 9 | |||
| 10 | pub fn dump(gpa: *Allocator, air: Air, liveness: Liveness) void { | ||
| 11 | const instruction_bytes = air.instructions.len * | ||
| 12 | // 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 | (@sizeOf(Air.Inst.Tag) + 8); | ||
| 15 | const extra_bytes = air.extra.len * @sizeOf(u32); | ||
| 16 | const values_bytes = air.values.len * @sizeOf(Value); | ||
| 17 | const variables_bytes = air.variables.len * @sizeOf(*Module.Var); | ||
| 18 | const tomb_bytes = liveness.tomb_bits.len * @sizeOf(usize); | ||
| 19 | const liveness_extra_bytes = liveness.extra.len * @sizeOf(u32); | ||
| 20 | const liveness_special_bytes = liveness.special.count() * 8; | ||
| 21 | const total_bytes = @sizeOf(Air) + instruction_bytes + extra_bytes + | ||
| 22 | values_bytes * variables_bytes + @sizeOf(Liveness) + liveness_extra_bytes + | ||
| 23 | liveness_special_bytes + tomb_bytes; | ||
| 24 | |||
| 25 | // zig fmt: off | ||
| 26 | std.debug.print( | ||
| 27 | \\# Total AIR+Liveness bytes: {} | ||
| 28 | \\# AIR Instructions: {d} ({}) | ||
| 29 | \\# AIR Extra Data: {d} ({}) | ||
| 30 | \\# AIR Values Bytes: {d} ({}) | ||
| 31 | \\# AIR Variables Bytes: {d} ({}) | ||
| 32 | \\# Liveness tomb_bits: {} | ||
| 33 | \\# Liveness Extra Data: {d} ({}) | ||
| 34 | \\# Liveness special table: {d} ({}) | ||
| 35 | \\ | ||
| 36 | , .{ | ||
| 37 | fmtIntSizeBin(total_bytes), | ||
| 38 | air.instructions.len, fmtIntSizeBin(instruction_bytes), | ||
| 39 | air.extra.len, fmtIntSizeBin(extra_bytes), | ||
| 40 | air.values.len, fmtIntSizeBin(values_bytes), | ||
| 41 | air.variables.len, fmtIntSizeBin(variables_bytes), | ||
| 42 | fmtIntSizeBin(tomb_bytes), | ||
| 43 | liveness.extra.len, fmtIntSizeBin(liveness_extra_bytes), | ||
| 44 | liveness.special.count(), fmtIntSizeBin(liveness_special_bytes), | ||
| 45 | }); | ||
| 46 | // zig fmt: on | ||
| 47 | var arena = std.heap.ArenaAllocator.init(gpa); | ||
| 48 | defer arena.deinit(); | ||
| 49 | |||
| 50 | var writer: Writer = .{ | ||
| 51 | .gpa = gpa, | ||
| 52 | .arena = &arena.allocator, | ||
| 53 | .air = air, | ||
| 54 | .liveness = liveness, | ||
| 55 | .indent = 0, | ||
| 56 | }; | ||
| 57 | const stream = std.io.getStdErr().writer(); | ||
| 58 | writer.writeAllConstants(stream) catch return; | ||
| 59 | writer.writeBody(stream, air.getMainBody()) catch return; | ||
| 60 | } | ||
| 61 | |||
| 62 | const Writer = struct { | ||
| 63 | gpa: *Allocator, | ||
| 64 | arena: *Allocator, | ||
| 65 | air: Air, | ||
| 66 | liveness: Liveness, | ||
| 67 | indent: usize, | ||
| 68 | |||
| 69 | fn writeAllConstants(w: *Writer, s: anytype) @TypeOf(s).Error!void { | ||
| 70 | for (w.air.instructions.items(.tag)) |tag, i| { | ||
| 71 | const inst = @intCast(u32, i); | ||
| 72 | switch (tag) { | ||
| 73 | .constant, .const_ty => { | ||
| 74 | try s.writeByteNTimes(' ', w.indent); | ||
| 75 | try s.print("%{d} ", .{inst}); | ||
| 76 | try w.writeInst(s, inst); | ||
| 77 | try s.writeAll(")\n"); | ||
| 78 | }, | ||
| 79 | else => continue, | ||
| 80 | } | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | fn writeBody(w: *Writer, s: anytype, body: []const Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 85 | for (body) |inst| { | ||
| 86 | try s.writeByteNTimes(' ', w.indent); | ||
| 87 | try s.print("%{d} ", .{inst}); | ||
| 88 | try w.writeInst(s, inst); | ||
| 89 | if (w.liveness.isUnused(inst)) { | ||
| 90 | try s.writeAll(") unused\n"); | ||
| 91 | } else { | ||
| 92 | try s.writeAll("\n"); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | fn writeInst(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 98 | const tags = w.air.instructions.items(.tag); | ||
| 99 | const tag = tags[inst]; | ||
| 100 | try s.print("= {s}(", .{@tagName(tags[inst])}); | ||
| 101 | switch (tag) { | ||
| 102 | .arg => try w.writeTyStr(s, inst), | ||
| 103 | |||
| 104 | .add, | ||
| 105 | .addwrap, | ||
| 106 | .sub, | ||
| 107 | .subwrap, | ||
| 108 | .mul, | ||
| 109 | .mulwrap, | ||
| 110 | .div, | ||
| 111 | .bit_and, | ||
| 112 | .bit_or, | ||
| 113 | .xor, | ||
| 114 | .cmp_lt, | ||
| 115 | .cmp_lte, | ||
| 116 | .cmp_eq, | ||
| 117 | .cmp_gte, | ||
| 118 | .cmp_gt, | ||
| 119 | .cmp_neq, | ||
| 120 | .bool_and, | ||
| 121 | .bool_or, | ||
| 122 | .store, | ||
| 123 | => try w.writeBinOp(s, inst), | ||
| 124 | |||
| 125 | .is_null, | ||
| 126 | .is_non_null, | ||
| 127 | .is_null_ptr, | ||
| 128 | .is_non_null_ptr, | ||
| 129 | .is_err, | ||
| 130 | .is_non_err, | ||
| 131 | .is_err_ptr, | ||
| 132 | .is_non_err_ptr, | ||
| 133 | .ptrtoint, | ||
| 134 | .ret, | ||
| 135 | => try w.writeUnOp(s, inst), | ||
| 136 | |||
| 137 | .breakpoint, | ||
| 138 | .unreach, | ||
| 139 | => try w.writeNoOp(s, inst), | ||
| 140 | |||
| 141 | .const_ty, | ||
| 142 | .alloc, | ||
| 143 | => try w.writeTy(s, inst), | ||
| 144 | |||
| 145 | .not, | ||
| 146 | .bitcast, | ||
| 147 | .load, | ||
| 148 | .ref, | ||
| 149 | .floatcast, | ||
| 150 | .intcast, | ||
| 151 | .optional_payload, | ||
| 152 | .optional_payload_ptr, | ||
| 153 | .wrap_optional, | ||
| 154 | .unwrap_errunion_payload, | ||
| 155 | .unwrap_errunion_err, | ||
| 156 | .unwrap_errunion_payload_ptr, | ||
| 157 | .unwrap_errunion_err_ptr, | ||
| 158 | .wrap_errunion_payload, | ||
| 159 | .wrap_errunion_err, | ||
| 160 | => try w.writeTyOp(s, inst), | ||
| 161 | |||
| 162 | .block, | ||
| 163 | .loop, | ||
| 164 | => try w.writeBlock(s, inst), | ||
| 165 | |||
| 166 | .struct_field_ptr => try w.writeStructFieldPtr(s, inst), | ||
| 167 | .varptr => try w.writeVarPtr(s, inst), | ||
| 168 | .constant => try w.writeConstant(s, inst), | ||
| 169 | .assembly => try w.writeAssembly(s, inst), | ||
| 170 | .dbg_stmt => try w.writeDbgStmt(s, inst), | ||
| 171 | .call => try w.writeCall(s, inst), | ||
| 172 | .br => try w.writeBr(s, inst), | ||
| 173 | .cond_br => try w.writeCondBr(s, inst), | ||
| 174 | .switch_br => try w.writeSwitchBr(s, inst), | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | fn writeTyStr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 179 | _ = w; | ||
| 180 | _ = inst; | ||
| 181 | try s.writeAll("TODO"); | ||
| 182 | } | ||
| 183 | |||
| 184 | fn writeBinOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 185 | _ = w; | ||
| 186 | _ = inst; | ||
| 187 | try s.writeAll("TODO"); | ||
| 188 | } | ||
| 189 | |||
| 190 | fn writeUnOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 191 | _ = w; | ||
| 192 | _ = inst; | ||
| 193 | try s.writeAll("TODO"); | ||
| 194 | } | ||
| 195 | |||
| 196 | fn writeNoOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 197 | _ = w; | ||
| 198 | _ = inst; | ||
| 199 | try s.writeAll("TODO"); | ||
| 200 | } | ||
| 201 | |||
| 202 | fn writeTy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 203 | const ty = w.air.instructions.items(.data)[inst].ty; | ||
| 204 | try s.print("{}", .{ty}); | ||
| 205 | } | ||
| 206 | |||
| 207 | fn writeTyOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 208 | _ = w; | ||
| 209 | _ = inst; | ||
| 210 | try s.writeAll("TODO"); | ||
| 211 | } | ||
| 212 | |||
| 213 | fn writeBlock(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 214 | _ = w; | ||
| 215 | _ = inst; | ||
| 216 | try s.writeAll("TODO"); | ||
| 217 | } | ||
| 218 | |||
| 219 | fn writeStructFieldPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 220 | _ = w; | ||
| 221 | _ = inst; | ||
| 222 | try s.writeAll("TODO"); | ||
| 223 | } | ||
| 224 | |||
| 225 | fn writeVarPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 226 | _ = w; | ||
| 227 | _ = inst; | ||
| 228 | try s.writeAll("TODO"); | ||
| 229 | } | ||
| 230 | |||
| 231 | fn writeConstant(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 232 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; | ||
| 233 | const val = w.air.values[ty_pl.payload]; | ||
| 234 | try s.print("{}, {}", .{ ty_pl.ty, val }); | ||
| 235 | } | ||
| 236 | |||
| 237 | fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 238 | _ = w; | ||
| 239 | _ = inst; | ||
| 240 | try s.writeAll("TODO"); | ||
| 241 | } | ||
| 242 | |||
| 243 | fn writeDbgStmt(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 244 | const dbg_stmt = w.air.instructions.items(.data)[inst].dbg_stmt; | ||
| 245 | try s.print("{d}:{d}", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); | ||
| 246 | } | ||
| 247 | |||
| 248 | fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 249 | const pl_op = w.air.instructions.items(.data)[inst].pl_op; | ||
| 250 | const extra = w.air.extraData(Air.Call, pl_op.payload); | ||
| 251 | const args = w.air.extra[extra.end..][0..extra.data.args_len]; | ||
| 252 | try w.writeInstRef(s, pl_op.operand); | ||
| 253 | try s.writeAll(", ["); | ||
| 254 | for (args) |arg, i| { | ||
| 255 | if (i != 0) try s.writeAll(", "); | ||
| 256 | try w.writeInstRef(s, @intToEnum(Air.Inst.Ref, arg)); | ||
| 257 | } | ||
| 258 | try s.writeAll("]"); | ||
| 259 | } | ||
| 260 | |||
| 261 | fn writeBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 262 | _ = w; | ||
| 263 | _ = inst; | ||
| 264 | try s.writeAll("TODO"); | ||
| 265 | } | ||
| 266 | |||
| 267 | fn writeCondBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 268 | _ = w; | ||
| 269 | _ = inst; | ||
| 270 | try s.writeAll("TODO"); | ||
| 271 | } | ||
| 272 | |||
| 273 | fn writeSwitchBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 274 | _ = w; | ||
| 275 | _ = inst; | ||
| 276 | try s.writeAll("TODO"); | ||
| 277 | } | ||
| 278 | |||
| 279 | fn writeInstRef(w: *Writer, s: anytype, inst: Air.Inst.Ref) @TypeOf(s).Error!void { | ||
| 280 | var i: usize = @enumToInt(inst); | ||
| 281 | |||
| 282 | if (i < Air.Inst.Ref.typed_value_map.len) { | ||
| 283 | return s.print("@{}", .{inst}); | ||
| 284 | } | ||
| 285 | i -= Air.Inst.Ref.typed_value_map.len; | ||
| 286 | |||
| 287 | return w.writeInstIndex(s, @intCast(Air.Inst.Index, i)); | ||
| 288 | } | ||
| 289 | |||
| 290 | fn writeInstIndex(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 291 | _ = w; | ||
| 292 | return s.print("%{d}", .{inst}); | ||
| 293 | } | ||
| 294 | }; | ||
src/value.zig+1-1| ... | @@ -573,7 +573,7 @@ pub const Value = extern union { | ... | @@ -573,7 +573,7 @@ pub const Value = extern union { |
| 573 | .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", options, out_stream), | 573 | .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", options, out_stream), |
| 574 | .int_big_positive => return out_stream.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}), | 574 | .int_big_positive => return out_stream.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}), |
| 575 | .int_big_negative => return out_stream.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}), | 575 | .int_big_negative => return out_stream.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}), |
| 576 | .function => return out_stream.writeAll("(function)"), | 576 | .function => return out_stream.print("(function '{s}')", .{val.castTag(.function).?.data.owner_decl.name}), |
| 577 | .extern_fn => return out_stream.writeAll("(extern function)"), | 577 | .extern_fn => return out_stream.writeAll("(extern function)"), |
| 578 | .variable => return out_stream.writeAll("(variable)"), | 578 | .variable => return out_stream.writeAll("(variable)"), |
| 579 | .ref_val => { | 579 | .ref_val => { |