authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-26 02:25:09-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-26 02:30:14-04:00
log130c7fd23b9f23aa5afad2eb1744ffab9e193715
treeb39e5cf093a901c7713009d4c4448e0702d4ead7
parente820678ca1c1a66b561e760fb6aae4df4babf8ba

self-hosted: working towards conditional branching test case

New features: * Functions can have parameters in semantic analysis. Codegen is not implemented yet. * Support for i8, i16, i32, i64, u8, u16, u32, u64 primitive identifiers. * New ZIR instructions: arg, block, and breakvoid Implementation details: * Move Module.Body to ir.Body * Scope.Block gains a parent field and an optional Label field * Fix bug in integer type equality comparison. Here's the test case I'm working towards: ``` @void = primitive(void) @i32 = primitive(i32) @fnty = fntype([@i32, @i32], @void) @0 = str("entry") @1 = export(@0, "entry") @entry = fn(@fnty, { %0 = arg(0) %1 = arg(1) %2 = add(%0, %1) %3 = int(7) %4 = block("if", { %neq = cmp(%2, neq, %3) %5 = condbr(%neq, { %6 = unreachable() }, { %7 = breakvoid("if") }) }) %11 = returnvoid() }) ``` $ ./zig-cache/bin/zig build-obj test.zir test.zir:9:12: error: TODO implement function parameters for Arch.x86_64 That's where I left off.

6 files changed, 841 insertions(+), 96 deletions(-)

src-self-hosted/Module.zig+204-46
...@@ -15,6 +15,7 @@ const ir = @import("ir.zig");...@@ -15,6 +15,7 @@ const ir = @import("ir.zig");
15const zir = @import("zir.zig");15const zir = @import("zir.zig");
16const Module = @This();16const Module = @This();
17const Inst = ir.Inst;17const Inst = ir.Inst;
18const Body = ir.Body;
18const ast = std.zig.ast;19const ast = std.zig.ast;
19const trace = @import("tracy.zig").trace;20const trace = @import("tracy.zig").trace;
2021
...@@ -649,11 +650,19 @@ pub const Scope = struct {...@@ -649,11 +650,19 @@ pub const Scope = struct {
649 pub const Block = struct {650 pub const Block = struct {
650 pub const base_tag: Tag = .block;651 pub const base_tag: Tag = .block;
651 base: Scope = Scope{ .tag = base_tag },652 base: Scope = Scope{ .tag = base_tag },
653 parent: ?*Block,
652 func: ?*Fn,654 func: ?*Fn,
653 decl: *Decl,655 decl: *Decl,
654 instructions: ArrayListUnmanaged(*Inst),656 instructions: ArrayListUnmanaged(*Inst),
655 /// Points to the arena allocator of DeclAnalysis657 /// Points to the arena allocator of DeclAnalysis
656 arena: *Allocator,658 arena: *Allocator,
659 label: ?Label = null,
660
661 pub const Label = struct {
662 name: []const u8,
663 results: ArrayListUnmanaged(*Inst),
664 block_inst: *Inst.Block,
665 };
657 };666 };
658667
659 /// This is a temporary structure, references to it are valid only668 /// This is a temporary structure, references to it are valid only
...@@ -676,10 +685,6 @@ pub const Scope = struct {...@@ -676,10 +685,6 @@ pub const Scope = struct {
676 };685 };
677};686};
678687
679pub const Body = struct {
680 instructions: []*Inst,
681};
682
683pub const AllErrors = struct {688pub const AllErrors = struct {
684 arena: std.heap.ArenaAllocator.State,689 arena: std.heap.ArenaAllocator.State,
685 list: []const Message,690 list: []const Message,
...@@ -1139,13 +1144,16 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1139,13 +1144,16 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
11391144
1140 const body_node = fn_proto.body_node orelse1145 const body_node = fn_proto.body_node orelse
1141 return self.failTok(&fn_type_scope.base, fn_proto.fn_token, "TODO implement extern functions", .{});1146 return self.failTok(&fn_type_scope.base, fn_proto.fn_token, "TODO implement extern functions", .{});
1142 if (fn_proto.params_len != 0) {1147
1143 return self.failTok(1148 const param_decls = fn_proto.params();
1144 &fn_type_scope.base,1149 const param_types = try fn_type_scope.arena.allocator.alloc(*zir.Inst, param_decls.len);
1145 fn_proto.params()[0].name_token.?,1150 for (param_decls) |param_decl, i| {
1146 "TODO implement function parameters",1151 const param_type_node = switch (param_decl.param_type) {
1147 .{},1152 .var_type => |node| return self.failNode(&fn_type_scope.base, node, "TODO implement anytype parameter", .{}),
1148 );1153 .var_args => |tok| return self.failTok(&fn_type_scope.base, tok, "TODO implement var args", .{}),
1154 .type_expr => |node| node,
1155 };
1156 param_types[i] = try self.astGenExpr(&fn_type_scope.base, param_type_node);
1149 }1157 }
1150 if (fn_proto.lib_name) |lib_name| {1158 if (fn_proto.lib_name) |lib_name| {
1151 return self.failNode(&fn_type_scope.base, lib_name, "TODO implement function library name", .{});1159 return self.failNode(&fn_type_scope.base, lib_name, "TODO implement function library name", .{});
...@@ -1174,7 +1182,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1174,7 +1182,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1174 const fn_src = tree.token_locs[fn_proto.fn_token].start;1182 const fn_src = tree.token_locs[fn_proto.fn_token].start;
1175 const fn_type_inst = try self.addZIRInst(&fn_type_scope.base, fn_src, zir.Inst.FnType, .{1183 const fn_type_inst = try self.addZIRInst(&fn_type_scope.base, fn_src, zir.Inst.FnType, .{
1176 .return_type = return_type_inst,1184 .return_type = return_type_inst,
1177 .param_types = &[0]*zir.Inst{},1185 .param_types = param_types,
1178 }, .{});1186 }, .{});
1179 _ = try self.addZIRInst(&fn_type_scope.base, fn_src, zir.Inst.Return, .{ .operand = fn_type_inst }, .{});1187 _ = try self.addZIRInst(&fn_type_scope.base, fn_src, zir.Inst.Return, .{ .operand = fn_type_inst }, .{});
11801188
...@@ -1184,6 +1192,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1184,6 +1192,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1184 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);1192 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
11851193
1186 var block_scope: Scope.Block = .{1194 var block_scope: Scope.Block = .{
1195 .parent = null,
1187 .func = null,1196 .func = null,
1188 .decl = decl,1197 .decl = decl,
1189 .instructions = .{},1198 .instructions = .{},
...@@ -1302,10 +1311,25 @@ fn astGenExpr(self: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir...@@ -1302,10 +1311,25 @@ fn astGenExpr(self: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir
1302 .Call => return self.astGenCall(scope, @fieldParentPtr(ast.Node.Call, "base", ast_node)),1311 .Call => return self.astGenCall(scope, @fieldParentPtr(ast.Node.Call, "base", ast_node)),
1303 .Unreachable => return self.astGenUnreachable(scope, @fieldParentPtr(ast.Node.Unreachable, "base", ast_node)),1312 .Unreachable => return self.astGenUnreachable(scope, @fieldParentPtr(ast.Node.Unreachable, "base", ast_node)),
1304 .ControlFlowExpression => return self.astGenControlFlowExpression(scope, @fieldParentPtr(ast.Node.ControlFlowExpression, "base", ast_node)),1313 .ControlFlowExpression => return self.astGenControlFlowExpression(scope, @fieldParentPtr(ast.Node.ControlFlowExpression, "base", ast_node)),
1314 .If => return self.astGenIf(scope, @fieldParentPtr(ast.Node.If, "base", ast_node)),
1305 else => return self.failNode(scope, ast_node, "TODO implement astGenExpr for {}", .{@tagName(ast_node.id)}),1315 else => return self.failNode(scope, ast_node, "TODO implement astGenExpr for {}", .{@tagName(ast_node.id)}),
1306 }1316 }
1307}1317}
13081318
1319fn astGenIf(self: *Module, scope: *Scope, if_node: *ast.Node.If) InnerError!*zir.Inst {
1320 if (if_node.payload) |payload| {
1321 return self.failNode(scope, payload, "TODO implement astGenIf for optionals", .{});
1322 }
1323 if (if_node.@"else") |else_node| {
1324 if (else_node.payload) |payload| {
1325 return self.failNode(scope, payload, "TODO implement astGenIf for error unions", .{});
1326 }
1327 }
1328 const cond = try self.astGenExpr(scope, if_node.condition);
1329 const body = try self.astGenExpr(scope, if_node.condition);
1330 return self.failNode(scope, if_node.condition, "TODO implement astGenIf", .{});
1331}
1332
1309fn astGenControlFlowExpression(1333fn astGenControlFlowExpression(
1310 self: *Module,1334 self: *Module,
1311 scope: *Scope,1335 scope: *Scope,
...@@ -1351,7 +1375,18 @@ fn astGenIdent(self: *Module, scope: *Scope, ident: *ast.Node.Identifier) InnerE...@@ -1351,7 +1375,18 @@ fn astGenIdent(self: *Module, scope: *Scope, ident: *ast.Node.Identifier) InnerE
1351 ),1375 ),
1352 error.InvalidCharacter => break :integer,1376 error.InvalidCharacter => break :integer,
1353 };1377 };
1354 return self.failNode(scope, &ident.base, "TODO implement arbitrary integer bitwidth types", .{});1378 const val = switch (bit_count) {
1379 8 => if (is_signed) Value.initTag(.i8_type) else Value.initTag(.u8_type),
1380 16 => if (is_signed) Value.initTag(.i16_type) else Value.initTag(.u16_type),
1381 32 => if (is_signed) Value.initTag(.i32_type) else Value.initTag(.u32_type),
1382 64 => if (is_signed) Value.initTag(.i64_type) else Value.initTag(.u64_type),
1383 else => return self.failNode(scope, &ident.base, "TODO implement arbitrary integer bitwidth types", .{}),
1384 };
1385 const src = tree.token_locs[ident.token].start;
1386 return self.addZIRInstConst(scope, src, .{
1387 .ty = Type.initTag(.type),
1388 .val = val,
1389 });
1355 }1390 }
1356 }1391 }
13571392
...@@ -1494,16 +1529,18 @@ fn astGenBuiltinCall(self: *Module, scope: *Scope, call: *ast.Node.BuiltinCall)...@@ -1494,16 +1529,18 @@ fn astGenBuiltinCall(self: *Module, scope: *Scope, call: *ast.Node.BuiltinCall)
14941529
1495fn astGenCall(self: *Module, scope: *Scope, call: *ast.Node.Call) InnerError!*zir.Inst {1530fn astGenCall(self: *Module, scope: *Scope, call: *ast.Node.Call) InnerError!*zir.Inst {
1496 const tree = scope.tree();1531 const tree = scope.tree();
1532 const lhs = try self.astGenExpr(scope, call.lhs);
14971533
1498 if (call.params_len != 0) {1534 const param_nodes = call.params();
1499 return self.failNode(scope, &call.base, "TODO implement fn calls with parameters", .{});1535 const args = try scope.cast(Scope.GenZIR).?.arena.allocator.alloc(*zir.Inst, param_nodes.len);
1536 for (param_nodes) |param_node, i| {
1537 args[i] = try self.astGenExpr(scope, param_node);
1500 }1538 }
1501 const lhs = try self.astGenExpr(scope, call.lhs);
15021539
1503 const src = tree.token_locs[call.lhs.firstToken()].start;1540 const src = tree.token_locs[call.lhs.firstToken()].start;
1504 return self.addZIRInst(scope, src, zir.Inst.Call, .{1541 return self.addZIRInst(scope, src, zir.Inst.Call, .{
1505 .func = lhs,1542 .func = lhs,
1506 .args = &[0]*zir.Inst{},1543 .args = args,
1507 }, .{});1544 }, .{});
1508}1545}
15091546
...@@ -1871,6 +1908,7 @@ fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {...@@ -1871,6 +1908,7 @@ fn analyzeFnBody(self: *Module, decl: *Decl, func: *Fn) !void {
1871 var arena = decl.typed_value.most_recent.arena.?.promote(self.allocator);1908 var arena = decl.typed_value.most_recent.arena.?.promote(self.allocator);
1872 defer decl.typed_value.most_recent.arena.?.* = arena.state;1909 defer decl.typed_value.most_recent.arena.?.* = arena.state;
1873 var inner_block: Scope.Block = .{1910 var inner_block: Scope.Block = .{
1911 .parent = null,
1874 .func = func,1912 .func = func,
1875 .decl = decl,1913 .decl = decl,
1876 .instructions = .{},1914 .instructions = .{},
...@@ -2323,7 +2361,10 @@ fn analyzeInstConst(self: *Module, scope: *Scope, const_inst: *zir.Inst.Const) I...@@ -2323,7 +2361,10 @@ fn analyzeInstConst(self: *Module, scope: *Scope, const_inst: *zir.Inst.Const) I
23232361
2324fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Inst {2362fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Inst {
2325 switch (old_inst.tag) {2363 switch (old_inst.tag) {
2364 .arg => return self.analyzeInstArg(scope, old_inst.cast(zir.Inst.Arg).?),
2365 .block => return self.analyzeInstBlock(scope, old_inst.cast(zir.Inst.Block).?),
2326 .breakpoint => return self.analyzeInstBreakpoint(scope, old_inst.cast(zir.Inst.Breakpoint).?),2366 .breakpoint => return self.analyzeInstBreakpoint(scope, old_inst.cast(zir.Inst.Breakpoint).?),
2367 .breakvoid => return self.analyzeInstBreakVoid(scope, old_inst.cast(zir.Inst.BreakVoid).?),
2327 .call => return self.analyzeInstCall(scope, old_inst.cast(zir.Inst.Call).?),2368 .call => return self.analyzeInstCall(scope, old_inst.cast(zir.Inst.Call).?),
2328 .compileerror => return self.analyzeInstCompileError(scope, old_inst.cast(zir.Inst.CompileError).?),2369 .compileerror => return self.analyzeInstCompileError(scope, old_inst.cast(zir.Inst.CompileError).?),
2329 .@"const" => return self.analyzeInstConst(scope, old_inst.cast(zir.Inst.Const).?),2370 .@"const" => return self.analyzeInstConst(scope, old_inst.cast(zir.Inst.Const).?),
...@@ -2436,11 +2477,105 @@ fn analyzeInstCompileError(self: *Module, scope: *Scope, inst: *zir.Inst.Compile...@@ -2436,11 +2477,105 @@ fn analyzeInstCompileError(self: *Module, scope: *Scope, inst: *zir.Inst.Compile
2436 return self.fail(scope, inst.base.src, "{}", .{inst.positionals.msg});2477 return self.fail(scope, inst.base.src, "{}", .{inst.positionals.msg});
2437}2478}
24382479
2480fn analyzeInstArg(self: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*Inst {
2481 const b = try self.requireRuntimeBlock(scope, inst.base.src);
2482 const fn_ty = b.func.?.owner_decl.typed_value.most_recent.typed_value.ty;
2483 const param_count = fn_ty.fnParamLen();
2484 if (inst.positionals.index >= param_count) {
2485 return self.fail(scope, inst.base.src, "parameter index {} outside list of length {}", .{
2486 inst.positionals.index,
2487 param_count,
2488 });
2489 }
2490 const param_type = fn_ty.fnParamType(inst.positionals.index);
2491 return self.addNewInstArgs(b, inst.base.src, param_type, Inst.Arg, .{
2492 .index = inst.positionals.index,
2493 });
2494}
2495
2496fn analyzeInstBlock(self: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerError!*Inst {
2497 const parent_block = scope.cast(Scope.Block).?;
2498
2499 // Reserve space for a Block instruction so that generated Break instructions can
2500 // point to it, even if it doesn't end up getting used because the code ends up being
2501 // comptime evaluated.
2502 const block_inst = try parent_block.arena.create(Inst.Block);
2503 block_inst.* = .{
2504 .base = .{
2505 .tag = Inst.Block.base_tag,
2506 .ty = undefined, // Set after analysis.
2507 .src = inst.base.src,
2508 },
2509 .args = undefined,
2510 };
2511
2512 var child_block: Scope.Block = .{
2513 .parent = parent_block,
2514 .func = parent_block.func,
2515 .decl = parent_block.decl,
2516 .instructions = .{},
2517 .arena = parent_block.arena,
2518 // TODO @as here is working around a miscompilation compiler bug :(
2519 .label = @as(?Scope.Block.Label, Scope.Block.Label{
2520 .name = inst.positionals.label,
2521 .results = .{},
2522 .block_inst = block_inst,
2523 }),
2524 };
2525 const label = &child_block.label.?;
2526
2527 defer child_block.instructions.deinit(self.allocator);
2528 defer label.results.deinit(self.allocator);
2529
2530 try self.analyzeBody(&child_block.base, inst.positionals.body);
2531
2532 // Blocks must terminate with noreturn instruction.
2533 assert(child_block.instructions.items.len != 0);
2534 assert(child_block.instructions.items[child_block.instructions.items.len - 1].tag.isNoReturn());
2535
2536 if (label.results.items.len <= 1) {
2537 // No need to add the Block instruction; we can add the instructions to the parent block directly.
2538 // Blocks are terminated with a noreturn instruction which we do not want to include.
2539 const instrs = child_block.instructions.items;
2540 try parent_block.instructions.appendSlice(self.allocator, instrs[0 .. instrs.len - 1]);
2541 if (label.results.items.len == 1) {
2542 return label.results.items[0];
2543 } else {
2544 return self.constNoReturn(scope, inst.base.src);
2545 }
2546 }
2547
2548 // Need to set the type and emit the Block instruction. This allows machine code generation
2549 // to emit a jump instruction to after the block when it encounters the break.
2550 try parent_block.instructions.append(self.allocator, &block_inst.base);
2551 block_inst.base.ty = try self.resolvePeerTypes(scope, label.results.items);
2552 block_inst.args.body = .{ .instructions = try parent_block.arena.dupe(*Inst, child_block.instructions.items) };
2553 return &block_inst.base;
2554}
2555
2439fn analyzeInstBreakpoint(self: *Module, scope: *Scope, inst: *zir.Inst.Breakpoint) InnerError!*Inst {2556fn analyzeInstBreakpoint(self: *Module, scope: *Scope, inst: *zir.Inst.Breakpoint) InnerError!*Inst {
2440 const b = try self.requireRuntimeBlock(scope, inst.base.src);2557 const b = try self.requireRuntimeBlock(scope, inst.base.src);
2441 return self.addNewInstArgs(b, inst.base.src, Type.initTag(.void), Inst.Breakpoint, {});2558 return self.addNewInstArgs(b, inst.base.src, Type.initTag(.void), Inst.Breakpoint, {});
2442}2559}
24432560
2561fn analyzeInstBreakVoid(self: *Module, scope: *Scope, inst: *zir.Inst.BreakVoid) InnerError!*Inst {
2562 const label_name = inst.positionals.label;
2563 const void_inst = try self.constVoid(scope, inst.base.src);
2564
2565 var opt_block = scope.cast(Scope.Block);
2566 while (opt_block) |block| {
2567 if (block.label) |*label| {
2568 if (mem.eql(u8, label.name, label_name)) {
2569 try label.results.append(self.allocator, void_inst);
2570 return self.constNoReturn(scope, inst.base.src);
2571 }
2572 }
2573 opt_block = block.parent;
2574 } else {
2575 return self.fail(scope, inst.base.src, "use of undeclared label '{}'", .{label_name});
2576 }
2577}
2578
2444fn analyzeInstDeclRefStr(self: *Module, scope: *Scope, inst: *zir.Inst.DeclRefStr) InnerError!*Inst {2579fn analyzeInstDeclRefStr(self: *Module, scope: *Scope, inst: *zir.Inst.DeclRefStr) InnerError!*Inst {
2445 const decl_name = try self.resolveConstString(scope, inst.positionals.name);2580 const decl_name = try self.resolveConstString(scope, inst.positionals.name);
2446 return self.analyzeDeclRefByName(scope, inst.base.src, decl_name);2581 return self.analyzeDeclRefByName(scope, inst.base.src, decl_name);
...@@ -2602,35 +2737,38 @@ fn analyzeInstFn(self: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError...@@ -2602,35 +2737,38 @@ fn analyzeInstFn(self: *Module, scope: *Scope, fn_inst: *zir.Inst.Fn) InnerError
2602fn analyzeInstFnType(self: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {2737fn analyzeInstFnType(self: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {
2603 const return_type = try self.resolveType(scope, fntype.positionals.return_type);2738 const return_type = try self.resolveType(scope, fntype.positionals.return_type);
26042739
2605 if (return_type.zigTypeTag() == .NoReturn and2740 // Hot path for some common function types.
2606 fntype.positionals.param_types.len == 0 and2741 if (fntype.positionals.param_types.len == 0) {
2607 fntype.kw_args.cc == .Unspecified)2742 if (return_type.zigTypeTag() == .NoReturn and fntype.kw_args.cc == .Unspecified) {
2608 {2743 return self.constType(scope, fntype.base.src, Type.initTag(.fn_noreturn_no_args));
2609 return self.constType(scope, fntype.base.src, Type.initTag(.fn_noreturn_no_args));2744 }
2610 }
26112745
2612 if (return_type.zigTypeTag() == .Void and2746 if (return_type.zigTypeTag() == .Void and fntype.kw_args.cc == .Unspecified) {
2613 fntype.positionals.param_types.len == 0 and2747 return self.constType(scope, fntype.base.src, Type.initTag(.fn_void_no_args));
2614 fntype.kw_args.cc == .Unspecified)2748 }
2615 {
2616 return self.constType(scope, fntype.base.src, Type.initTag(.fn_void_no_args));
2617 }
26182749
2619 if (return_type.zigTypeTag() == .NoReturn and2750 if (return_type.zigTypeTag() == .NoReturn and fntype.kw_args.cc == .Naked) {
2620 fntype.positionals.param_types.len == 0 and2751 return self.constType(scope, fntype.base.src, Type.initTag(.fn_naked_noreturn_no_args));
2621 fntype.kw_args.cc == .Naked)2752 }
2622 {2753
2623 return self.constType(scope, fntype.base.src, Type.initTag(.fn_naked_noreturn_no_args));2754 if (return_type.zigTypeTag() == .Void and fntype.kw_args.cc == .C) {
2755 return self.constType(scope, fntype.base.src, Type.initTag(.fn_ccc_void_no_args));
2756 }
2624 }2757 }
26252758
2626 if (return_type.zigTypeTag() == .Void and2759 const arena = scope.arena();
2627 fntype.positionals.param_types.len == 0 and2760 const param_types = try arena.alloc(Type, fntype.positionals.param_types.len);
2628 fntype.kw_args.cc == .C)2761 for (fntype.positionals.param_types) |param_type, i| {
2629 {2762 param_types[i] = try self.resolveType(scope, param_type);
2630 return self.constType(scope, fntype.base.src, Type.initTag(.fn_ccc_void_no_args));
2631 }2763 }
26322764
2633 return self.fail(scope, fntype.base.src, "TODO implement fntype instruction more", .{});2765 const payload = try arena.create(Type.Payload.Function);
2766 payload.* = .{
2767 .cc = fntype.kw_args.cc,
2768 .return_type = return_type,
2769 .param_types = param_types,
2770 };
2771 return self.constType(scope, fntype.base.src, Type.initPayload(&payload.base));
2634}2772}
26352773
2636fn analyzeInstPrimitive(self: *Module, scope: *Scope, primitive: *zir.Inst.Primitive) InnerError!*Inst {2774fn analyzeInstPrimitive(self: *Module, scope: *Scope, primitive: *zir.Inst.Primitive) InnerError!*Inst {
...@@ -2757,10 +2895,17 @@ fn analyzeInstElemPtr(self: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inn...@@ -2757,10 +2895,17 @@ fn analyzeInstElemPtr(self: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inn
2757}2895}
27582896
2759fn analyzeInstAdd(self: *Module, scope: *Scope, inst: *zir.Inst.Add) InnerError!*Inst {2897fn analyzeInstAdd(self: *Module, scope: *Scope, inst: *zir.Inst.Add) InnerError!*Inst {
2898 const tracy = trace(@src());
2899 defer tracy.end();
2900
2760 const lhs = try self.resolveInst(scope, inst.positionals.lhs);2901 const lhs = try self.resolveInst(scope, inst.positionals.lhs);
2761 const rhs = try self.resolveInst(scope, inst.positionals.rhs);2902 const rhs = try self.resolveInst(scope, inst.positionals.rhs);
27622903
2763 if (lhs.ty.zigTypeTag() == .Int and rhs.ty.zigTypeTag() == .Int) {2904 if (lhs.ty.zigTypeTag() == .Int and rhs.ty.zigTypeTag() == .Int) {
2905 if (!lhs.ty.eql(rhs.ty)) {
2906 return self.fail(scope, inst.base.src, "TODO implement peer type resolution", .{});
2907 }
2908
2764 if (lhs.value()) |lhs_val| {2909 if (lhs.value()) |lhs_val| {
2765 if (rhs.value()) |rhs_val| {2910 if (rhs.value()) |rhs_val| {
2766 // TODO is this a performance issue? maybe we should try the operation without2911 // TODO is this a performance issue? maybe we should try the operation without
...@@ -2777,10 +2922,6 @@ fn analyzeInstAdd(self: *Module, scope: *Scope, inst: *zir.Inst.Add) InnerError!...@@ -2777,10 +2922,6 @@ fn analyzeInstAdd(self: *Module, scope: *Scope, inst: *zir.Inst.Add) InnerError!
2777 result_bigint.add(lhs_bigint, rhs_bigint);2922 result_bigint.add(lhs_bigint, rhs_bigint);
2778 const result_limbs = result_bigint.limbs[0..result_bigint.len];2923 const result_limbs = result_bigint.limbs[0..result_bigint.len];
27792924
2780 if (!lhs.ty.eql(rhs.ty)) {
2781 return self.fail(scope, inst.base.src, "TODO implement peer type resolution", .{});
2782 }
2783
2784 const val_payload = if (result_bigint.positive) blk: {2925 const val_payload = if (result_bigint.positive) blk: {
2785 const val_payload = try scope.arena().create(Value.Payload.IntBigPositive);2926 const val_payload = try scope.arena().create(Value.Payload.IntBigPositive);
2786 val_payload.* = .{ .limbs = result_limbs };2927 val_payload.* = .{ .limbs = result_limbs };
...@@ -2797,6 +2938,12 @@ fn analyzeInstAdd(self: *Module, scope: *Scope, inst: *zir.Inst.Add) InnerError!...@@ -2797,6 +2938,12 @@ fn analyzeInstAdd(self: *Module, scope: *Scope, inst: *zir.Inst.Add) InnerError!
2797 });2938 });
2798 }2939 }
2799 }2940 }
2941
2942 const b = try self.requireRuntimeBlock(scope, inst.base.src);
2943 return self.addNewInstArgs(b, inst.base.src, lhs.ty, Inst.Add, .{
2944 .lhs = lhs,
2945 .rhs = rhs,
2946 });
2800 }2947 }
28012948
2802 return self.fail(scope, inst.base.src, "TODO implement more analyze add", .{});2949 return self.fail(scope, inst.base.src, "TODO implement more analyze add", .{});
...@@ -2936,6 +3083,7 @@ fn analyzeInstCondBr(self: *Module, scope: *Scope, inst: *zir.Inst.CondBr) Inner...@@ -2936,6 +3083,7 @@ fn analyzeInstCondBr(self: *Module, scope: *Scope, inst: *zir.Inst.CondBr) Inner
2936 const parent_block = try self.requireRuntimeBlock(scope, inst.base.src);3083 const parent_block = try self.requireRuntimeBlock(scope, inst.base.src);
29373084
2938 var true_block: Scope.Block = .{3085 var true_block: Scope.Block = .{
3086 .parent = parent_block,
2939 .func = parent_block.func,3087 .func = parent_block.func,
2940 .decl = parent_block.decl,3088 .decl = parent_block.decl,
2941 .instructions = .{},3089 .instructions = .{},
...@@ -2945,6 +3093,7 @@ fn analyzeInstCondBr(self: *Module, scope: *Scope, inst: *zir.Inst.CondBr) Inner...@@ -2945,6 +3093,7 @@ fn analyzeInstCondBr(self: *Module, scope: *Scope, inst: *zir.Inst.CondBr) Inner
2945 try self.analyzeBody(&true_block.base, inst.positionals.true_body);3093 try self.analyzeBody(&true_block.base, inst.positionals.true_body);
29463094
2947 var false_block: Scope.Block = .{3095 var false_block: Scope.Block = .{
3096 .parent = parent_block,
2948 .func = parent_block.func,3097 .func = parent_block.func,
2949 .decl = parent_block.decl,3098 .decl = parent_block.decl,
2950 .instructions = .{},3099 .instructions = .{},
...@@ -3178,7 +3327,7 @@ fn cmpNumeric(...@@ -3178,7 +3327,7 @@ fn cmpNumeric(
3178 const casted_lhs = try self.coerce(scope, dest_type, lhs);3327 const casted_lhs = try self.coerce(scope, dest_type, lhs);
3179 const casted_rhs = try self.coerce(scope, dest_type, lhs);3328 const casted_rhs = try self.coerce(scope, dest_type, lhs);
31803329
3181 return self.addNewInstArgs(b, src, dest_type, Inst.Cmp, .{3330 return self.addNewInstArgs(b, src, Type.initTag(.bool), Inst.Cmp, .{
3182 .lhs = casted_lhs,3331 .lhs = casted_lhs,
3183 .rhs = casted_rhs,3332 .rhs = casted_rhs,
3184 .op = op,3333 .op = op,
...@@ -3197,6 +3346,12 @@ fn makeIntType(self: *Module, scope: *Scope, signed: bool, bits: u16) !Type {...@@ -3197,6 +3346,12 @@ fn makeIntType(self: *Module, scope: *Scope, signed: bool, bits: u16) !Type {
3197 }3346 }
3198}3347}
31993348
3349fn resolvePeerTypes(self: *Module, scope: *Scope, instructions: []*Inst) !Type {
3350 if (instructions.len == 0)
3351 return Type.initTag(.noreturn);
3352 return self.fail(scope, instructions[0].src, "TODO peer type resolution", .{});
3353}
3354
3200fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst {3355fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst {
3201 // If the types are the same, we can return the operand.3356 // If the types are the same, we can return the operand.
3202 if (dest_type.eql(inst.ty))3357 if (dest_type.eql(inst.ty))
...@@ -3238,7 +3393,10 @@ fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst {...@@ -3238,7 +3393,10 @@ fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst {
3238 if (inst.value()) |val| {3393 if (inst.value()) |val| {
3239 return self.constInst(scope, inst.src, .{ .ty = dest_type, .val = val });3394 return self.constInst(scope, inst.src, .{ .ty = dest_type, .val = val });
3240 } else {3395 } else {
3241 return self.fail(scope, inst.src, "TODO implement runtime integer widening", .{});3396 return self.fail(scope, inst.src, "TODO implement runtime integer widening ({} to {})", .{
3397 inst.ty,
3398 dest_type,
3399 });
3242 }3400 }
3243 } else {3401 } else {
3244 return self.fail(scope, inst.src, "TODO implement more int widening {} to {}", .{ inst.ty, dest_type });3402 return self.fail(scope, inst.src, "TODO implement more int widening {} to {}", .{ inst.ty, dest_type });
src-self-hosted/codegen.zig+22
...@@ -174,6 +174,9 @@ const Function = struct {...@@ -174,6 +174,9 @@ const Function = struct {
174174
175 fn genFuncInst(self: *Function, inst: *ir.Inst) !MCValue {175 fn genFuncInst(self: *Function, inst: *ir.Inst) !MCValue {
176 switch (inst.tag) {176 switch (inst.tag) {
177 .add => return self.genAdd(inst.cast(ir.Inst.Add).?),
178 .arg => return self.genArg(inst.src),
179 .block => return self.genBlock(inst.cast(ir.Inst.Block).?),
177 .breakpoint => return self.genBreakpoint(inst.src),180 .breakpoint => return self.genBreakpoint(inst.src),
178 .call => return self.genCall(inst.cast(ir.Inst.Call).?),181 .call => return self.genCall(inst.cast(ir.Inst.Call).?),
179 .unreach => return MCValue{ .unreach = {} },182 .unreach => return MCValue{ .unreach = {} },
...@@ -190,6 +193,19 @@ const Function = struct {...@@ -190,6 +193,19 @@ const Function = struct {
190 }193 }
191 }194 }
192195
196 fn genAdd(self: *Function, inst: *ir.Inst.Add) !MCValue {
197 switch (self.target.cpu.arch) {
198 else => return self.fail(inst.base.src, "TODO implement add for {}", .{self.target.cpu.arch}),
199 }
200 }
201
202 fn genArg(self: *Function, src: usize) !MCValue {
203 switch (self.target.cpu.arch) {
204 else => return self.fail(src, "TODO implement function parameters for {}", .{self.target.cpu.arch}),
205 }
206 return .none;
207 }
208
193 fn genBreakpoint(self: *Function, src: usize) !MCValue {209 fn genBreakpoint(self: *Function, src: usize) !MCValue {
194 switch (self.target.cpu.arch) {210 switch (self.target.cpu.arch) {
195 .i386, .x86_64 => {211 .i386, .x86_64 => {
...@@ -302,6 +318,12 @@ const Function = struct {...@@ -302,6 +318,12 @@ const Function = struct {
302 }318 }
303 }319 }
304320
321 fn genBlock(self: *Function, inst: *ir.Inst.Block) !MCValue {
322 switch (self.target.cpu.arch) {
323 else => return self.fail(inst.base.src, "TODO implement codegen Block for {}", .{self.target.cpu.arch}),
324 }
325 }
326
305 fn genAsm(self: *Function, inst: *ir.Inst.Assembly) !MCValue {327 fn genAsm(self: *Function, inst: *ir.Inst.Assembly) !MCValue {
306 // TODO convert to inline function328 // TODO convert to inline function
307 switch (self.target.cpu.arch) {329 switch (self.target.cpu.arch) {
src-self-hosted/ir.zig+63-2
...@@ -15,8 +15,11 @@ pub const Inst = struct {...@@ -15,8 +15,11 @@ pub const Inst = struct {
15 src: usize,15 src: usize,
1616
17 pub const Tag = enum {17 pub const Tag = enum {
18 add,
19 arg,
18 assembly,20 assembly,
19 bitcast,21 bitcast,
22 block,
20 breakpoint,23 breakpoint,
21 call,24 call,
22 cmp,25 cmp,
...@@ -28,6 +31,33 @@ pub const Inst = struct {...@@ -28,6 +31,33 @@ pub const Inst = struct {
28 ret,31 ret,
29 retvoid,32 retvoid,
30 unreach,33 unreach,
34
35 /// Returns whether the instruction is one of the control flow "noreturn" types.
36 /// Function calls do not count. When ZIR is generated, the compiler automatically
37 /// emits an `Unreach` after a function call with the `noreturn` return type.
38 pub fn isNoReturn(tag: Tag) bool {
39 return switch (tag) {
40 .add,
41 .arg,
42 .assembly,
43 .bitcast,
44 .block,
45 .breakpoint,
46 .cmp,
47 .constant,
48 .isnonnull,
49 .isnull,
50 .ptrtoint,
51 .call,
52 => false,
53
54 .condbr,
55 .ret,
56 .retvoid,
57 .unreach,
58 => true,
59 };
60 }
31 };61 };
3262
33 pub fn cast(base: *Inst, comptime T: type) ?*T {63 pub fn cast(base: *Inst, comptime T: type) ?*T {
...@@ -50,6 +80,25 @@ pub const Inst = struct {...@@ -50,6 +80,25 @@ pub const Inst = struct {
50 return inst.val;80 return inst.val;
51 }81 }
5282
83 pub const Add = struct {
84 pub const base_tag = Tag.add;
85 base: Inst,
86
87 args: struct {
88 lhs: *Inst,
89 rhs: *Inst,
90 },
91 };
92
93 pub const Arg = struct {
94 pub const base_tag = Tag.arg;
95 base: Inst,
96
97 args: struct {
98 index: usize,
99 },
100 };
101
53 pub const Assembly = struct {102 pub const Assembly = struct {
54 pub const base_tag = Tag.assembly;103 pub const base_tag = Tag.assembly;
55 base: Inst,104 base: Inst,
...@@ -73,6 +122,14 @@ pub const Inst = struct {...@@ -73,6 +122,14 @@ pub const Inst = struct {
73 },122 },
74 };123 };
75124
125 pub const Block = struct {
126 pub const base_tag = Tag.block;
127 base: Inst,
128 args: struct {
129 body: Body,
130 },
131 };
132
76 pub const Breakpoint = struct {133 pub const Breakpoint = struct {
77 pub const base_tag = Tag.breakpoint;134 pub const base_tag = Tag.breakpoint;
78 base: Inst,135 base: Inst,
...@@ -105,8 +162,8 @@ pub const Inst = struct {...@@ -105,8 +162,8 @@ pub const Inst = struct {
105 base: Inst,162 base: Inst,
106 args: struct {163 args: struct {
107 condition: *Inst,164 condition: *Inst,
108 true_body: Module.Body,165 true_body: Body,
109 false_body: Module.Body,166 false_body: Body,
110 },167 },
111 };168 };
112169
...@@ -164,3 +221,7 @@ pub const Inst = struct {...@@ -164,3 +221,7 @@ pub const Inst = struct {
164 args: void,221 args: void,
165 };222 };
166};223};
224
225pub const Body = struct {
226 instructions: []*Inst,
227};
src-self-hosted/type.zig+323-17
...@@ -21,8 +21,14 @@ pub const Type = extern union {...@@ -21,8 +21,14 @@ pub const Type = extern union {
21 switch (self.tag()) {21 switch (self.tag()) {
22 .u8,22 .u8,
23 .i8,23 .i8,
24 .isize,24 .u16,
25 .i16,
26 .u32,
27 .i32,
28 .u64,
29 .i64,
25 .usize,30 .usize,
31 .isize,
26 .c_short,32 .c_short,
27 .c_ushort,33 .c_ushort,
28 .c_int,34 .c_int,
...@@ -57,6 +63,7 @@ pub const Type = extern union {...@@ -57,6 +63,7 @@ pub const Type = extern union {
57 .fn_void_no_args => return .Fn,63 .fn_void_no_args => return .Fn,
58 .fn_naked_noreturn_no_args => return .Fn,64 .fn_naked_noreturn_no_args => return .Fn,
59 .fn_ccc_void_no_args => return .Fn,65 .fn_ccc_void_no_args => return .Fn,
66 .function => return .Fn,
6067
61 .array, .array_u8_sentinel_0 => return .Array,68 .array, .array_u8_sentinel_0 => return .Array,
62 .single_const_pointer => return .Pointer,69 .single_const_pointer => return .Pointer,
...@@ -126,10 +133,14 @@ pub const Type = extern union {...@@ -126,10 +133,14 @@ pub const Type = extern union {
126 @panic("TODO implement more pointer Type equality comparison");133 @panic("TODO implement more pointer Type equality comparison");
127 },134 },
128 .Int => {135 .Int => {
129 if (a.tag() != b.tag()) {136 // Detect that e.g. u64 != usize, even if the bits match on a particular target.
130 // Detect that e.g. u64 != usize, even if the bits match on a particular target.137 const a_is_named_int = a.isNamedInt();
138 const b_is_named_int = b.isNamedInt();
139 if (a_is_named_int != b_is_named_int)
131 return false;140 return false;
132 }141 if (a_is_named_int)
142 return a.tag() == b.tag();
143 // Remaining cases are arbitrary sized integers.
133 // The target will not be branched upon, because we handled target-dependent cases above.144 // The target will not be branched upon, because we handled target-dependent cases above.
134 const info_a = a.intInfo(@as(Target, undefined));145 const info_a = a.intInfo(@as(Target, undefined));
135 const info_b = b.intInfo(@as(Target, undefined));146 const info_b = b.intInfo(@as(Target, undefined));
...@@ -176,8 +187,14 @@ pub const Type = extern union {...@@ -176,8 +187,14 @@ pub const Type = extern union {
176 } else switch (self.ptr_otherwise.tag) {187 } else switch (self.ptr_otherwise.tag) {
177 .u8,188 .u8,
178 .i8,189 .i8,
179 .isize,190 .u16,
191 .i16,
192 .u32,
193 .i32,
194 .u64,
195 .i64,
180 .usize,196 .usize,
197 .isize,
181 .c_short,198 .c_short,
182 .c_ushort,199 .c_ushort,
183 .c_int,200 .c_int,
...@@ -231,6 +248,21 @@ pub const Type = extern union {...@@ -231,6 +248,21 @@ pub const Type = extern union {
231 },248 },
232 .int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned),249 .int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned),
233 .int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned),250 .int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned),
251 .function => {
252 const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise);
253 const new_payload = try allocator.create(Payload.Function);
254 const param_types = try allocator.alloc(Type, payload.param_types.len);
255 for (payload.param_types) |param_type, i| {
256 param_types[i] = try param_type.copy(allocator);
257 }
258 new_payload.* = .{
259 .base = payload.base,
260 .return_type = try payload.return_type.copy(allocator),
261 .param_types = param_types,
262 .cc = payload.cc,
263 };
264 return Type{ .ptr_otherwise = &new_payload.base };
265 },
234 }266 }
235 }267 }
236268
...@@ -246,7 +278,7 @@ pub const Type = extern union {...@@ -246,7 +278,7 @@ pub const Type = extern union {
246 comptime fmt: []const u8,278 comptime fmt: []const u8,
247 options: std.fmt.FormatOptions,279 options: std.fmt.FormatOptions,
248 out_stream: var,280 out_stream: var,
249 ) !void {281 ) @TypeOf(out_stream).Error!void {
250 comptime assert(fmt.len == 0);282 comptime assert(fmt.len == 0);
251 var ty = self;283 var ty = self;
252 while (true) {284 while (true) {
...@@ -254,8 +286,14 @@ pub const Type = extern union {...@@ -254,8 +286,14 @@ pub const Type = extern union {
254 switch (t) {286 switch (t) {
255 .u8,287 .u8,
256 .i8,288 .i8,
257 .isize,289 .u16,
290 .i16,
291 .u32,
292 .i32,
293 .u64,
294 .i64,
258 .usize,295 .usize,
296 .isize,
259 .c_short,297 .c_short,
260 .c_ushort,298 .c_ushort,
261 .c_int,299 .c_int,
...@@ -288,6 +326,16 @@ pub const Type = extern union {...@@ -288,6 +326,16 @@ pub const Type = extern union {
288 .fn_naked_noreturn_no_args => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),326 .fn_naked_noreturn_no_args => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),
289 .fn_ccc_void_no_args => return out_stream.writeAll("fn() callconv(.C) void"),327 .fn_ccc_void_no_args => return out_stream.writeAll("fn() callconv(.C) void"),
290 .single_const_pointer_to_comptime_int => return out_stream.writeAll("*const comptime_int"),328 .single_const_pointer_to_comptime_int => return out_stream.writeAll("*const comptime_int"),
329 .function => {
330 const payload = @fieldParentPtr(Payload.Function, "base", ty.ptr_otherwise);
331 try out_stream.writeAll("fn(");
332 for (payload.param_types) |param_type, i| {
333 if (i != 0) try out_stream.writeAll(", ");
334 try param_type.format("", .{}, out_stream);
335 }
336 try out_stream.writeAll(") ");
337 try payload.return_type.format("", .{}, out_stream);
338 },
291339
292 .array_u8_sentinel_0 => {340 .array_u8_sentinel_0 => {
293 const payload = @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", ty.ptr_otherwise);341 const payload = @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", ty.ptr_otherwise);
...@@ -322,8 +370,14 @@ pub const Type = extern union {...@@ -322,8 +370,14 @@ pub const Type = extern union {
322 switch (self.tag()) {370 switch (self.tag()) {
323 .u8 => return Value.initTag(.u8_type),371 .u8 => return Value.initTag(.u8_type),
324 .i8 => return Value.initTag(.i8_type),372 .i8 => return Value.initTag(.i8_type),
325 .isize => return Value.initTag(.isize_type),373 .u16 => return Value.initTag(.u16_type),
374 .i16 => return Value.initTag(.i16_type),
375 .u32 => return Value.initTag(.u32_type),
376 .i32 => return Value.initTag(.i32_type),
377 .u64 => return Value.initTag(.u64_type),
378 .i64 => return Value.initTag(.i64_type),
326 .usize => return Value.initTag(.usize_type),379 .usize => return Value.initTag(.usize_type),
380 .isize => return Value.initTag(.isize_type),
327 .c_short => return Value.initTag(.c_short_type),381 .c_short => return Value.initTag(.c_short_type),
328 .c_ushort => return Value.initTag(.c_ushort_type),382 .c_ushort => return Value.initTag(.c_ushort_type),
329 .c_int => return Value.initTag(.c_int_type),383 .c_int => return Value.initTag(.c_int_type),
...@@ -365,8 +419,14 @@ pub const Type = extern union {...@@ -365,8 +419,14 @@ pub const Type = extern union {
365 return switch (self.tag()) {419 return switch (self.tag()) {
366 .u8,420 .u8,
367 .i8,421 .i8,
368 .isize,422 .u16,
423 .i16,
424 .u32,
425 .i32,
426 .u64,
427 .i64,
369 .usize,428 .usize,
429 .isize,
370 .c_short,430 .c_short,
371 .c_ushort,431 .c_ushort,
372 .c_int,432 .c_int,
...@@ -386,6 +446,7 @@ pub const Type = extern union {...@@ -386,6 +446,7 @@ pub const Type = extern union {
386 .fn_void_no_args,446 .fn_void_no_args,
387 .fn_naked_noreturn_no_args,447 .fn_naked_noreturn_no_args,
388 .fn_ccc_void_no_args,448 .fn_ccc_void_no_args,
449 .function,
389 .single_const_pointer_to_comptime_int,450 .single_const_pointer_to_comptime_int,
390 .const_slice_u8,451 .const_slice_u8,
391 .array_u8_sentinel_0,452 .array_u8_sentinel_0,
...@@ -417,9 +478,14 @@ pub const Type = extern union {...@@ -417,9 +478,14 @@ pub const Type = extern union {
417 .fn_void_no_args, // represents machine code; not a pointer478 .fn_void_no_args, // represents machine code; not a pointer
418 .fn_naked_noreturn_no_args, // represents machine code; not a pointer479 .fn_naked_noreturn_no_args, // represents machine code; not a pointer
419 .fn_ccc_void_no_args, // represents machine code; not a pointer480 .fn_ccc_void_no_args, // represents machine code; not a pointer
481 .function, // represents machine code; not a pointer
420 .array_u8_sentinel_0,482 .array_u8_sentinel_0,
421 => return 1,483 => return 1,
422484
485 .i16, .u16 => return 2,
486 .i32, .u32 => return 4,
487 .i64, .u64 => return 8,
488
423 .isize,489 .isize,
424 .usize,490 .usize,
425 .single_const_pointer_to_comptime_int,491 .single_const_pointer_to_comptime_int,
...@@ -473,8 +539,14 @@ pub const Type = extern union {...@@ -473,8 +539,14 @@ pub const Type = extern union {
473 return switch (self.tag()) {539 return switch (self.tag()) {
474 .u8,540 .u8,
475 .i8,541 .i8,
476 .isize,542 .u16,
543 .i16,
544 .u32,
545 .i32,
546 .u64,
547 .i64,
477 .usize,548 .usize,
549 .isize,
478 .c_short,550 .c_short,
479 .c_ushort,551 .c_ushort,
480 .c_int,552 .c_int,
...@@ -505,6 +577,7 @@ pub const Type = extern union {...@@ -505,6 +577,7 @@ pub const Type = extern union {
505 .fn_void_no_args,577 .fn_void_no_args,
506 .fn_naked_noreturn_no_args,578 .fn_naked_noreturn_no_args,
507 .fn_ccc_void_no_args,579 .fn_ccc_void_no_args,
580 .function,
508 .int_unsigned,581 .int_unsigned,
509 .int_signed,582 .int_signed,
510 => false,583 => false,
...@@ -519,8 +592,14 @@ pub const Type = extern union {...@@ -519,8 +592,14 @@ pub const Type = extern union {
519 return switch (self.tag()) {592 return switch (self.tag()) {
520 .u8,593 .u8,
521 .i8,594 .i8,
522 .isize,595 .u16,
596 .i16,
597 .u32,
598 .i32,
599 .u64,
600 .i64,
523 .usize,601 .usize,
602 .isize,
524 .c_short,603 .c_short,
525 .c_ushort,604 .c_ushort,
526 .c_int,605 .c_int,
...@@ -552,6 +631,7 @@ pub const Type = extern union {...@@ -552,6 +631,7 @@ pub const Type = extern union {
552 .fn_void_no_args,631 .fn_void_no_args,
553 .fn_naked_noreturn_no_args,632 .fn_naked_noreturn_no_args,
554 .fn_ccc_void_no_args,633 .fn_ccc_void_no_args,
634 .function,
555 .int_unsigned,635 .int_unsigned,
556 .int_signed,636 .int_signed,
557 => false,637 => false,
...@@ -565,8 +645,14 @@ pub const Type = extern union {...@@ -565,8 +645,14 @@ pub const Type = extern union {
565 return switch (self.tag()) {645 return switch (self.tag()) {
566 .u8,646 .u8,
567 .i8,647 .i8,
568 .isize,648 .u16,
649 .i16,
650 .u32,
651 .i32,
652 .u64,
653 .i64,
569 .usize,654 .usize,
655 .isize,
570 .c_short,656 .c_short,
571 .c_ushort,657 .c_ushort,
572 .c_int,658 .c_int,
...@@ -596,6 +682,7 @@ pub const Type = extern union {...@@ -596,6 +682,7 @@ pub const Type = extern union {
596 .fn_void_no_args,682 .fn_void_no_args,
597 .fn_naked_noreturn_no_args,683 .fn_naked_noreturn_no_args,
598 .fn_ccc_void_no_args,684 .fn_ccc_void_no_args,
685 .function,
599 .int_unsigned,686 .int_unsigned,
600 .int_signed,687 .int_signed,
601 => unreachable,688 => unreachable,
...@@ -612,8 +699,14 @@ pub const Type = extern union {...@@ -612,8 +699,14 @@ pub const Type = extern union {
612 return switch (self.tag()) {699 return switch (self.tag()) {
613 .u8,700 .u8,
614 .i8,701 .i8,
615 .isize,702 .u16,
703 .i16,
704 .u32,
705 .i32,
706 .u64,
707 .i64,
616 .usize,708 .usize,
709 .isize,
617 .c_short,710 .c_short,
618 .c_ushort,711 .c_ushort,
619 .c_int,712 .c_int,
...@@ -641,6 +734,7 @@ pub const Type = extern union {...@@ -641,6 +734,7 @@ pub const Type = extern union {
641 .fn_void_no_args,734 .fn_void_no_args,
642 .fn_naked_noreturn_no_args,735 .fn_naked_noreturn_no_args,
643 .fn_ccc_void_no_args,736 .fn_ccc_void_no_args,
737 .function,
644 .int_unsigned,738 .int_unsigned,
645 .int_signed,739 .int_signed,
646 => unreachable,740 => unreachable,
...@@ -657,8 +751,14 @@ pub const Type = extern union {...@@ -657,8 +751,14 @@ pub const Type = extern union {
657 return switch (self.tag()) {751 return switch (self.tag()) {
658 .u8,752 .u8,
659 .i8,753 .i8,
660 .isize,754 .u16,
755 .i16,
756 .u32,
757 .i32,
758 .u64,
759 .i64,
661 .usize,760 .usize,
761 .isize,
662 .c_short,762 .c_short,
663 .c_ushort,763 .c_ushort,
664 .c_int,764 .c_int,
...@@ -686,6 +786,7 @@ pub const Type = extern union {...@@ -686,6 +786,7 @@ pub const Type = extern union {
686 .fn_void_no_args,786 .fn_void_no_args,
687 .fn_naked_noreturn_no_args,787 .fn_naked_noreturn_no_args,
688 .fn_ccc_void_no_args,788 .fn_ccc_void_no_args,
789 .function,
689 .single_const_pointer,790 .single_const_pointer,
690 .single_const_pointer_to_comptime_int,791 .single_const_pointer_to_comptime_int,
691 .const_slice_u8,792 .const_slice_u8,
...@@ -703,8 +804,14 @@ pub const Type = extern union {...@@ -703,8 +804,14 @@ pub const Type = extern union {
703 return switch (self.tag()) {804 return switch (self.tag()) {
704 .u8,805 .u8,
705 .i8,806 .i8,
706 .isize,807 .u16,
808 .i16,
809 .u32,
810 .i32,
811 .u64,
812 .i64,
707 .usize,813 .usize,
814 .isize,
708 .c_short,815 .c_short,
709 .c_ushort,816 .c_ushort,
710 .c_int,817 .c_int,
...@@ -732,6 +839,7 @@ pub const Type = extern union {...@@ -732,6 +839,7 @@ pub const Type = extern union {
732 .fn_void_no_args,839 .fn_void_no_args,
733 .fn_naked_noreturn_no_args,840 .fn_naked_noreturn_no_args,
734 .fn_ccc_void_no_args,841 .fn_ccc_void_no_args,
842 .function,
735 .single_const_pointer,843 .single_const_pointer,
736 .single_const_pointer_to_comptime_int,844 .single_const_pointer_to_comptime_int,
737 .const_slice_u8,845 .const_slice_u8,
...@@ -766,6 +874,7 @@ pub const Type = extern union {...@@ -766,6 +874,7 @@ pub const Type = extern union {
766 .fn_void_no_args,874 .fn_void_no_args,
767 .fn_naked_noreturn_no_args,875 .fn_naked_noreturn_no_args,
768 .fn_ccc_void_no_args,876 .fn_ccc_void_no_args,
877 .function,
769 .array,878 .array,
770 .single_const_pointer,879 .single_const_pointer,
771 .single_const_pointer_to_comptime_int,880 .single_const_pointer_to_comptime_int,
...@@ -778,6 +887,9 @@ pub const Type = extern union {...@@ -778,6 +887,9 @@ pub const Type = extern union {
778 .c_uint,887 .c_uint,
779 .c_ulong,888 .c_ulong,
780 .c_ulonglong,889 .c_ulonglong,
890 .u16,
891 .u32,
892 .u64,
781 => false,893 => false,
782894
783 .int_signed,895 .int_signed,
...@@ -787,11 +899,14 @@ pub const Type = extern union {...@@ -787,11 +899,14 @@ pub const Type = extern union {
787 .c_int,899 .c_int,
788 .c_long,900 .c_long,
789 .c_longlong,901 .c_longlong,
902 .i16,
903 .i32,
904 .i64,
790 => true,905 => true,
791 };906 };
792 }907 }
793908
794 /// Asserts the type is a fixed-width integer.909 /// Asserts the type is an integer.
795 pub fn intInfo(self: Type, target: Target) struct { signed: bool, bits: u16 } {910 pub fn intInfo(self: Type, target: Target) struct { signed: bool, bits: u16 } {
796 return switch (self.tag()) {911 return switch (self.tag()) {
797 .f16,912 .f16,
...@@ -813,6 +928,7 @@ pub const Type = extern union {...@@ -813,6 +928,7 @@ pub const Type = extern union {
813 .fn_void_no_args,928 .fn_void_no_args,
814 .fn_naked_noreturn_no_args,929 .fn_naked_noreturn_no_args,
815 .fn_ccc_void_no_args,930 .fn_ccc_void_no_args,
931 .function,
816 .array,932 .array,
817 .single_const_pointer,933 .single_const_pointer,
818 .single_const_pointer_to_comptime_int,934 .single_const_pointer_to_comptime_int,
...@@ -824,6 +940,12 @@ pub const Type = extern union {...@@ -824,6 +940,12 @@ pub const Type = extern union {
824 .int_signed => .{ .signed = true, .bits = self.cast(Payload.IntSigned).?.bits },940 .int_signed => .{ .signed = true, .bits = self.cast(Payload.IntSigned).?.bits },
825 .u8 => .{ .signed = false, .bits = 8 },941 .u8 => .{ .signed = false, .bits = 8 },
826 .i8 => .{ .signed = true, .bits = 8 },942 .i8 => .{ .signed = true, .bits = 8 },
943 .u16 => .{ .signed = false, .bits = 16 },
944 .i16 => .{ .signed = true, .bits = 16 },
945 .u32 => .{ .signed = false, .bits = 32 },
946 .i32 => .{ .signed = true, .bits = 32 },
947 .u64 => .{ .signed = false, .bits = 64 },
948 .i64 => .{ .signed = true, .bits = 64 },
827 .usize => .{ .signed = false, .bits = target.cpu.arch.ptrBitWidth() },949 .usize => .{ .signed = false, .bits = target.cpu.arch.ptrBitWidth() },
828 .isize => .{ .signed = true, .bits = target.cpu.arch.ptrBitWidth() },950 .isize => .{ .signed = true, .bits = target.cpu.arch.ptrBitWidth() },
829 .c_short => .{ .signed = true, .bits = CType.short.sizeInBits(target) },951 .c_short => .{ .signed = true, .bits = CType.short.sizeInBits(target) },
...@@ -837,6 +959,59 @@ pub const Type = extern union {...@@ -837,6 +959,59 @@ pub const Type = extern union {
837 };959 };
838 }960 }
839961
962 pub fn isNamedInt(self: Type) bool {
963 return switch (self.tag()) {
964 .f16,
965 .f32,
966 .f64,
967 .f128,
968 .c_longdouble,
969 .c_void,
970 .bool,
971 .void,
972 .type,
973 .anyerror,
974 .comptime_int,
975 .comptime_float,
976 .noreturn,
977 .@"null",
978 .@"undefined",
979 .fn_noreturn_no_args,
980 .fn_void_no_args,
981 .fn_naked_noreturn_no_args,
982 .fn_ccc_void_no_args,
983 .function,
984 .array,
985 .single_const_pointer,
986 .single_const_pointer_to_comptime_int,
987 .array_u8_sentinel_0,
988 .const_slice_u8,
989 .int_unsigned,
990 .int_signed,
991 .u8,
992 .i8,
993 .u16,
994 .i16,
995 .u32,
996 .i32,
997 .u64,
998 .i64,
999 => false,
1000
1001 .usize,
1002 .isize,
1003 .c_short,
1004 .c_ushort,
1005 .c_int,
1006 .c_uint,
1007 .c_long,
1008 .c_ulong,
1009 .c_longlong,
1010 .c_ulonglong,
1011 => true,
1012 };
1013 }
1014
840 pub fn isFloat(self: Type) bool {1015 pub fn isFloat(self: Type) bool {
841 return switch (self.tag()) {1016 return switch (self.tag()) {
842 .f16,1017 .f16,
...@@ -870,6 +1045,7 @@ pub const Type = extern union {...@@ -870,6 +1045,7 @@ pub const Type = extern union {
870 .fn_void_no_args => 0,1045 .fn_void_no_args => 0,
871 .fn_naked_noreturn_no_args => 0,1046 .fn_naked_noreturn_no_args => 0,
872 .fn_ccc_void_no_args => 0,1047 .fn_ccc_void_no_args => 0,
1048 .function => @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise).param_types.len,
8731049
874 .f16,1050 .f16,
875 .f32,1051 .f32,
...@@ -893,6 +1069,12 @@ pub const Type = extern union {...@@ -893,6 +1069,12 @@ pub const Type = extern union {
893 .const_slice_u8,1069 .const_slice_u8,
894 .u8,1070 .u8,
895 .i8,1071 .i8,
1072 .u16,
1073 .i16,
1074 .u32,
1075 .i32,
1076 .u64,
1077 .i64,
896 .usize,1078 .usize,
897 .isize,1079 .isize,
898 .c_short,1080 .c_short,
...@@ -917,6 +1099,10 @@ pub const Type = extern union {...@@ -917,6 +1099,10 @@ pub const Type = extern union {
917 .fn_void_no_args => return,1099 .fn_void_no_args => return,
918 .fn_naked_noreturn_no_args => return,1100 .fn_naked_noreturn_no_args => return,
919 .fn_ccc_void_no_args => return,1101 .fn_ccc_void_no_args => return,
1102 .function => {
1103 const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise);
1104 std.mem.copy(Type, types, payload.param_types);
1105 },
9201106
921 .f16,1107 .f16,
922 .f32,1108 .f32,
...@@ -940,6 +1126,68 @@ pub const Type = extern union {...@@ -940,6 +1126,68 @@ pub const Type = extern union {
940 .const_slice_u8,1126 .const_slice_u8,
941 .u8,1127 .u8,
942 .i8,1128 .i8,
1129 .u16,
1130 .i16,
1131 .u32,
1132 .i32,
1133 .u64,
1134 .i64,
1135 .usize,
1136 .isize,
1137 .c_short,
1138 .c_ushort,
1139 .c_int,
1140 .c_uint,
1141 .c_long,
1142 .c_ulong,
1143 .c_longlong,
1144 .c_ulonglong,
1145 .int_unsigned,
1146 .int_signed,
1147 => unreachable,
1148 }
1149 }
1150
1151 /// Asserts the type is a function.
1152 pub fn fnParamType(self: Type, index: usize) Type {
1153 switch (self.tag()) {
1154 .function => {
1155 const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise);
1156 return payload.param_types[index];
1157 },
1158
1159 .fn_noreturn_no_args,
1160 .fn_void_no_args,
1161 .fn_naked_noreturn_no_args,
1162 .fn_ccc_void_no_args,
1163 .f16,
1164 .f32,
1165 .f64,
1166 .f128,
1167 .c_longdouble,
1168 .c_void,
1169 .bool,
1170 .void,
1171 .type,
1172 .anyerror,
1173 .comptime_int,
1174 .comptime_float,
1175 .noreturn,
1176 .@"null",
1177 .@"undefined",
1178 .array,
1179 .single_const_pointer,
1180 .single_const_pointer_to_comptime_int,
1181 .array_u8_sentinel_0,
1182 .const_slice_u8,
1183 .u8,
1184 .i8,
1185 .u16,
1186 .i16,
1187 .u32,
1188 .i32,
1189 .u64,
1190 .i64,
943 .usize,1191 .usize,
944 .isize,1192 .isize,
945 .c_short,1193 .c_short,
...@@ -966,6 +1214,8 @@ pub const Type = extern union {...@@ -966,6 +1214,8 @@ pub const Type = extern union {
966 .fn_ccc_void_no_args,1214 .fn_ccc_void_no_args,
967 => Type.initTag(.void),1215 => Type.initTag(.void),
9681216
1217 .function => @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise).return_type,
1218
969 .f16,1219 .f16,
970 .f32,1220 .f32,
971 .f64,1221 .f64,
...@@ -988,6 +1238,12 @@ pub const Type = extern union {...@@ -988,6 +1238,12 @@ pub const Type = extern union {
988 .const_slice_u8,1238 .const_slice_u8,
989 .u8,1239 .u8,
990 .i8,1240 .i8,
1241 .u16,
1242 .i16,
1243 .u32,
1244 .i32,
1245 .u64,
1246 .i64,
991 .usize,1247 .usize,
992 .isize,1248 .isize,
993 .c_short,1249 .c_short,
...@@ -1011,6 +1267,7 @@ pub const Type = extern union {...@@ -1011,6 +1267,7 @@ pub const Type = extern union {
1011 .fn_void_no_args => .Unspecified,1267 .fn_void_no_args => .Unspecified,
1012 .fn_naked_noreturn_no_args => .Naked,1268 .fn_naked_noreturn_no_args => .Naked,
1013 .fn_ccc_void_no_args => .C,1269 .fn_ccc_void_no_args => .C,
1270 .function => @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise).cc,
10141271
1015 .f16,1272 .f16,
1016 .f32,1273 .f32,
...@@ -1034,6 +1291,12 @@ pub const Type = extern union {...@@ -1034,6 +1291,12 @@ pub const Type = extern union {
1034 .const_slice_u8,1291 .const_slice_u8,
1035 .u8,1292 .u8,
1036 .i8,1293 .i8,
1294 .u16,
1295 .i16,
1296 .u32,
1297 .i32,
1298 .u64,
1299 .i64,
1037 .usize,1300 .usize,
1038 .isize,1301 .isize,
1039 .c_short,1302 .c_short,
...@@ -1057,6 +1320,7 @@ pub const Type = extern union {...@@ -1057,6 +1320,7 @@ pub const Type = extern union {
1057 .fn_void_no_args => false,1320 .fn_void_no_args => false,
1058 .fn_naked_noreturn_no_args => false,1321 .fn_naked_noreturn_no_args => false,
1059 .fn_ccc_void_no_args => false,1322 .fn_ccc_void_no_args => false,
1323 .function => false,
10601324
1061 .f16,1325 .f16,
1062 .f32,1326 .f32,
...@@ -1080,6 +1344,12 @@ pub const Type = extern union {...@@ -1080,6 +1344,12 @@ pub const Type = extern union {
1080 .const_slice_u8,1344 .const_slice_u8,
1081 .u8,1345 .u8,
1082 .i8,1346 .i8,
1347 .u16,
1348 .i16,
1349 .u32,
1350 .i32,
1351 .u64,
1352 .i64,
1083 .usize,1353 .usize,
1084 .isize,1354 .isize,
1085 .c_short,1355 .c_short,
...@@ -1107,6 +1377,12 @@ pub const Type = extern union {...@@ -1107,6 +1377,12 @@ pub const Type = extern union {
1107 .comptime_float,1377 .comptime_float,
1108 .u8,1378 .u8,
1109 .i8,1379 .i8,
1380 .u16,
1381 .i16,
1382 .u32,
1383 .i32,
1384 .u64,
1385 .i64,
1110 .usize,1386 .usize,
1111 .isize,1387 .isize,
1112 .c_short,1388 .c_short,
...@@ -1133,6 +1409,7 @@ pub const Type = extern union {...@@ -1133,6 +1409,7 @@ pub const Type = extern union {
1133 .fn_void_no_args,1409 .fn_void_no_args,
1134 .fn_naked_noreturn_no_args,1410 .fn_naked_noreturn_no_args,
1135 .fn_ccc_void_no_args,1411 .fn_ccc_void_no_args,
1412 .function,
1136 .array,1413 .array,
1137 .single_const_pointer,1414 .single_const_pointer,
1138 .single_const_pointer_to_comptime_int,1415 .single_const_pointer_to_comptime_int,
...@@ -1154,6 +1431,12 @@ pub const Type = extern union {...@@ -1154,6 +1431,12 @@ pub const Type = extern union {
1154 .comptime_float,1431 .comptime_float,
1155 .u8,1432 .u8,
1156 .i8,1433 .i8,
1434 .u16,
1435 .i16,
1436 .u32,
1437 .i32,
1438 .u64,
1439 .i64,
1157 .usize,1440 .usize,
1158 .isize,1441 .isize,
1159 .c_short,1442 .c_short,
...@@ -1171,6 +1454,7 @@ pub const Type = extern union {...@@ -1171,6 +1454,7 @@ pub const Type = extern union {
1171 .fn_void_no_args,1454 .fn_void_no_args,
1172 .fn_naked_noreturn_no_args,1455 .fn_naked_noreturn_no_args,
1173 .fn_ccc_void_no_args,1456 .fn_ccc_void_no_args,
1457 .function,
1174 .single_const_pointer_to_comptime_int,1458 .single_const_pointer_to_comptime_int,
1175 .array_u8_sentinel_0,1459 .array_u8_sentinel_0,
1176 .const_slice_u8,1460 .const_slice_u8,
...@@ -1211,6 +1495,12 @@ pub const Type = extern union {...@@ -1211,6 +1495,12 @@ pub const Type = extern union {
1211 .comptime_float,1495 .comptime_float,
1212 .u8,1496 .u8,
1213 .i8,1497 .i8,
1498 .u16,
1499 .i16,
1500 .u32,
1501 .i32,
1502 .u64,
1503 .i64,
1214 .usize,1504 .usize,
1215 .isize,1505 .isize,
1216 .c_short,1506 .c_short,
...@@ -1228,6 +1518,7 @@ pub const Type = extern union {...@@ -1228,6 +1518,7 @@ pub const Type = extern union {
1228 .fn_void_no_args,1518 .fn_void_no_args,
1229 .fn_naked_noreturn_no_args,1519 .fn_naked_noreturn_no_args,
1230 .fn_ccc_void_no_args,1520 .fn_ccc_void_no_args,
1521 .function,
1231 .single_const_pointer_to_comptime_int,1522 .single_const_pointer_to_comptime_int,
1232 .array_u8_sentinel_0,1523 .array_u8_sentinel_0,
1233 .const_slice_u8,1524 .const_slice_u8,
...@@ -1254,8 +1545,14 @@ pub const Type = extern union {...@@ -1254,8 +1545,14 @@ pub const Type = extern union {
1254 // The first section of this enum are tags that require no payload.1545 // The first section of this enum are tags that require no payload.
1255 u8,1546 u8,
1256 i8,1547 i8,
1257 isize,1548 u16,
1549 i16,
1550 u32,
1551 i32,
1552 u64,
1553 i64,
1258 usize,1554 usize,
1555 isize,
1259 c_short,1556 c_short,
1260 c_ushort,1557 c_ushort,
1261 c_int,1558 c_int,
...@@ -1292,6 +1589,7 @@ pub const Type = extern union {...@@ -1292,6 +1589,7 @@ pub const Type = extern union {
1292 single_const_pointer,1589 single_const_pointer,
1293 int_signed,1590 int_signed,
1294 int_unsigned,1591 int_unsigned,
1592 function,
12951593
1296 pub const last_no_payload_tag = Tag.const_slice_u8;1594 pub const last_no_payload_tag = Tag.const_slice_u8;
1297 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;1595 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
...@@ -1330,6 +1628,14 @@ pub const Type = extern union {...@@ -1330,6 +1628,14 @@ pub const Type = extern union {
13301628
1331 bits: u16,1629 bits: u16,
1332 };1630 };
1631
1632 pub const Function = struct {
1633 base: Payload = Payload{ .tag = .function },
1634
1635 param_types: []Type,
1636 return_type: Type,
1637 cc: std.builtin.CallingConvention,
1638 };
1333 };1639 };
1334};1640};
13351641
src-self-hosted/value.zig+90-12
...@@ -23,8 +23,14 @@ pub const Value = extern union {...@@ -23,8 +23,14 @@ pub const Value = extern union {
23 // The first section of this enum are tags that require no payload.23 // The first section of this enum are tags that require no payload.
24 u8_type,24 u8_type,
25 i8_type,25 i8_type,
26 isize_type,26 u16_type,
27 i16_type,
28 u32_type,
29 i32_type,
30 u64_type,
31 i64_type,
27 usize_type,32 usize_type,
33 isize_type,
28 c_short_type,34 c_short_type,
29 c_ushort_type,35 c_ushort_type,
30 c_int_type,36 c_int_type,
...@@ -114,8 +120,14 @@ pub const Value = extern union {...@@ -114,8 +120,14 @@ pub const Value = extern union {
114 } else switch (self.ptr_otherwise.tag) {120 } else switch (self.ptr_otherwise.tag) {
115 .u8_type,121 .u8_type,
116 .i8_type,122 .i8_type,
117 .isize_type,123 .u16_type,
124 .i16_type,
125 .u32_type,
126 .i32_type,
127 .u64_type,
128 .i64_type,
118 .usize_type,129 .usize_type,
130 .isize_type,
119 .c_short_type,131 .c_short_type,
120 .c_ushort_type,132 .c_ushort_type,
121 .c_int_type,133 .c_int_type,
...@@ -222,6 +234,12 @@ pub const Value = extern union {...@@ -222,6 +234,12 @@ pub const Value = extern union {
222 while (true) switch (val.tag()) {234 while (true) switch (val.tag()) {
223 .u8_type => return out_stream.writeAll("u8"),235 .u8_type => return out_stream.writeAll("u8"),
224 .i8_type => return out_stream.writeAll("i8"),236 .i8_type => return out_stream.writeAll("i8"),
237 .u16_type => return out_stream.writeAll("u16"),
238 .i16_type => return out_stream.writeAll("i16"),
239 .u32_type => return out_stream.writeAll("u32"),
240 .i32_type => return out_stream.writeAll("i32"),
241 .u64_type => return out_stream.writeAll("u64"),
242 .i64_type => return out_stream.writeAll("i64"),
225 .isize_type => return out_stream.writeAll("isize"),243 .isize_type => return out_stream.writeAll("isize"),
226 .usize_type => return out_stream.writeAll("usize"),244 .usize_type => return out_stream.writeAll("usize"),
227 .c_short_type => return out_stream.writeAll("c_short"),245 .c_short_type => return out_stream.writeAll("c_short"),
...@@ -308,8 +326,14 @@ pub const Value = extern union {...@@ -308,8 +326,14 @@ pub const Value = extern union {
308326
309 .u8_type => Type.initTag(.u8),327 .u8_type => Type.initTag(.u8),
310 .i8_type => Type.initTag(.i8),328 .i8_type => Type.initTag(.i8),
311 .isize_type => Type.initTag(.isize),329 .u16_type => Type.initTag(.u16),
330 .i16_type => Type.initTag(.i16),
331 .u32_type => Type.initTag(.u32),
332 .i32_type => Type.initTag(.i32),
333 .u64_type => Type.initTag(.u64),
334 .i64_type => Type.initTag(.i64),
312 .usize_type => Type.initTag(.usize),335 .usize_type => Type.initTag(.usize),
336 .isize_type => Type.initTag(.isize),
313 .c_short_type => Type.initTag(.c_short),337 .c_short_type => Type.initTag(.c_short),
314 .c_ushort_type => Type.initTag(.c_ushort),338 .c_ushort_type => Type.initTag(.c_ushort),
315 .c_int_type => Type.initTag(.c_int),339 .c_int_type => Type.initTag(.c_int),
...@@ -366,8 +390,14 @@ pub const Value = extern union {...@@ -366,8 +390,14 @@ pub const Value = extern union {
366 .ty,390 .ty,
367 .u8_type,391 .u8_type,
368 .i8_type,392 .i8_type,
369 .isize_type,393 .u16_type,
394 .i16_type,
395 .u32_type,
396 .i32_type,
397 .u64_type,
398 .i64_type,
370 .usize_type,399 .usize_type,
400 .isize_type,
371 .c_short_type,401 .c_short_type,
372 .c_ushort_type,402 .c_ushort_type,
373 .c_int_type,403 .c_int_type,
...@@ -426,8 +456,14 @@ pub const Value = extern union {...@@ -426,8 +456,14 @@ pub const Value = extern union {
426 .ty,456 .ty,
427 .u8_type,457 .u8_type,
428 .i8_type,458 .i8_type,
429 .isize_type,459 .u16_type,
460 .i16_type,
461 .u32_type,
462 .i32_type,
463 .u64_type,
464 .i64_type,
430 .usize_type,465 .usize_type,
466 .isize_type,
431 .c_short_type,467 .c_short_type,
432 .c_ushort_type,468 .c_ushort_type,
433 .c_int_type,469 .c_int_type,
...@@ -487,8 +523,14 @@ pub const Value = extern union {...@@ -487,8 +523,14 @@ pub const Value = extern union {
487 .ty,523 .ty,
488 .u8_type,524 .u8_type,
489 .i8_type,525 .i8_type,
490 .isize_type,526 .u16_type,
527 .i16_type,
528 .u32_type,
529 .i32_type,
530 .u64_type,
531 .i64_type,
491 .usize_type,532 .usize_type,
533 .isize_type,
492 .c_short_type,534 .c_short_type,
493 .c_ushort_type,535 .c_ushort_type,
494 .c_int_type,536 .c_int_type,
...@@ -553,8 +595,14 @@ pub const Value = extern union {...@@ -553,8 +595,14 @@ pub const Value = extern union {
553 .ty,595 .ty,
554 .u8_type,596 .u8_type,
555 .i8_type,597 .i8_type,
556 .isize_type,598 .u16_type,
599 .i16_type,
600 .u32_type,
601 .i32_type,
602 .u64_type,
603 .i64_type,
557 .usize_type,604 .usize_type,
605 .isize_type,
558 .c_short_type,606 .c_short_type,
559 .c_ushort_type,607 .c_ushort_type,
560 .c_int_type,608 .c_int_type,
...@@ -648,8 +696,14 @@ pub const Value = extern union {...@@ -648,8 +696,14 @@ pub const Value = extern union {
648 .ty,696 .ty,
649 .u8_type,697 .u8_type,
650 .i8_type,698 .i8_type,
651 .isize_type,699 .u16_type,
700 .i16_type,
701 .u32_type,
702 .i32_type,
703 .u64_type,
704 .i64_type,
652 .usize_type,705 .usize_type,
706 .isize_type,
653 .c_short_type,707 .c_short_type,
654 .c_ushort_type,708 .c_ushort_type,
655 .c_int_type,709 .c_int_type,
...@@ -705,8 +759,14 @@ pub const Value = extern union {...@@ -705,8 +759,14 @@ pub const Value = extern union {
705 .ty,759 .ty,
706 .u8_type,760 .u8_type,
707 .i8_type,761 .i8_type,
708 .isize_type,762 .u16_type,
763 .i16_type,
764 .u32_type,
765 .i32_type,
766 .u64_type,
767 .i64_type,
709 .usize_type,768 .usize_type,
769 .isize_type,
710 .c_short_type,770 .c_short_type,
711 .c_ushort_type,771 .c_ushort_type,
712 .c_int_type,772 .c_int_type,
...@@ -807,8 +867,14 @@ pub const Value = extern union {...@@ -807,8 +867,14 @@ pub const Value = extern union {
807 .ty,867 .ty,
808 .u8_type,868 .u8_type,
809 .i8_type,869 .i8_type,
810 .isize_type,870 .u16_type,
871 .i16_type,
872 .u32_type,
873 .i32_type,
874 .u64_type,
875 .i64_type,
811 .usize_type,876 .usize_type,
877 .isize_type,
812 .c_short_type,878 .c_short_type,
813 .c_ushort_type,879 .c_ushort_type,
814 .c_int_type,880 .c_int_type,
...@@ -870,8 +936,14 @@ pub const Value = extern union {...@@ -870,8 +936,14 @@ pub const Value = extern union {
870 .ty,936 .ty,
871 .u8_type,937 .u8_type,
872 .i8_type,938 .i8_type,
873 .isize_type,939 .u16_type,
940 .i16_type,
941 .u32_type,
942 .i32_type,
943 .u64_type,
944 .i64_type,
874 .usize_type,945 .usize_type,
946 .isize_type,
875 .c_short_type,947 .c_short_type,
876 .c_ushort_type,948 .c_ushort_type,
877 .c_int_type,949 .c_int_type,
...@@ -950,8 +1022,14 @@ pub const Value = extern union {...@@ -950,8 +1022,14 @@ pub const Value = extern union {
950 .ty,1022 .ty,
951 .u8_type,1023 .u8_type,
952 .i8_type,1024 .i8_type,
953 .isize_type,1025 .u16_type,
1026 .i16_type,
1027 .u32_type,
1028 .i32_type,
1029 .u64_type,
1030 .i64_type,
954 .usize_type,1031 .usize_type,
1032 .isize_type,
955 .c_short_type,1033 .c_short_type,
956 .c_ushort_type,1034 .c_ushort_type,
957 .c_int_type,1035 .c_int_type,
src-self-hosted/zir.zig+139-19
...@@ -34,7 +34,13 @@ pub const Inst = struct {...@@ -34,7 +34,13 @@ pub const Inst = struct {
3434
35 /// These names are used directly as the instruction names in the text format.35 /// These names are used directly as the instruction names in the text format.
36 pub const Tag = enum {36 pub const Tag = enum {
37 /// Function parameter value.
38 arg,
39 /// A labeled block of code, which can return a value.
40 block,
37 breakpoint,41 breakpoint,
42 /// Same as `break` but without an operand; the operand is assumed to be the void value.
43 breakvoid,
38 call,44 call,
39 compileerror,45 compileerror,
40 /// Special case, has no textual representation.46 /// Special case, has no textual representation.
...@@ -75,7 +81,10 @@ pub const Inst = struct {...@@ -75,7 +81,10 @@ pub const Inst = struct {
7581
76 pub fn TagToType(tag: Tag) type {82 pub fn TagToType(tag: Tag) type {
77 return switch (tag) {83 return switch (tag) {
84 .arg => Arg,
85 .block => Block,
78 .breakpoint => Breakpoint,86 .breakpoint => Breakpoint,
87 .breakvoid => BreakVoid,
79 .call => Call,88 .call => Call,
80 .declref => DeclRef,89 .declref => DeclRef,
81 .declref_str => DeclRefStr,90 .declref_str => DeclRefStr,
...@@ -115,6 +124,27 @@ pub const Inst = struct {...@@ -115,6 +124,27 @@ pub const Inst = struct {
115 return @fieldParentPtr(T, "base", base);124 return @fieldParentPtr(T, "base", base);
116 }125 }
117126
127 pub const Arg = struct {
128 pub const base_tag = Tag.arg;
129 base: Inst,
130
131 positionals: struct {
132 index: usize,
133 },
134 kw_args: struct {},
135 };
136
137 pub const Block = struct {
138 pub const base_tag = Tag.block;
139 base: Inst,
140
141 positionals: struct {
142 label: []const u8,
143 body: Module.Body,
144 },
145 kw_args: struct {},
146 };
147
118 pub const Breakpoint = struct {148 pub const Breakpoint = struct {
119 pub const base_tag = Tag.breakpoint;149 pub const base_tag = Tag.breakpoint;
120 base: Inst,150 base: Inst,
...@@ -123,6 +153,16 @@ pub const Inst = struct {...@@ -123,6 +153,16 @@ pub const Inst = struct {
123 kw_args: struct {},153 kw_args: struct {},
124 };154 };
125155
156 pub const BreakVoid = struct {
157 pub const base_tag = Tag.breakvoid;
158 base: Inst,
159
160 positionals: struct {
161 label: []const u8,
162 },
163 kw_args: struct {},
164 };
165
126 pub const Call = struct {166 pub const Call = struct {
127 pub const base_tag = Tag.call;167 pub const base_tag = Tag.call;
128 base: Inst,168 base: Inst,
...@@ -347,6 +387,14 @@ pub const Inst = struct {...@@ -347,6 +387,14 @@ pub const Inst = struct {
347 kw_args: struct {},387 kw_args: struct {},
348388
349 pub const Builtin = enum {389 pub const Builtin = enum {
390 i8,
391 u8,
392 i16,
393 u16,
394 i32,
395 u32,
396 i64,
397 u64,
350 isize,398 isize,
351 usize,399 usize,
352 c_short,400 c_short,
...@@ -378,6 +426,14 @@ pub const Inst = struct {...@@ -378,6 +426,14 @@ pub const Inst = struct {
378426
379 pub fn toTypedValue(self: Builtin) TypedValue {427 pub fn toTypedValue(self: Builtin) TypedValue {
380 return switch (self) {428 return switch (self) {
429 .i8 => .{ .ty = Type.initTag(.type), .val = Value.initTag(.i8_type) },
430 .u8 => .{ .ty = Type.initTag(.type), .val = Value.initTag(.u8_type) },
431 .i16 => .{ .ty = Type.initTag(.type), .val = Value.initTag(.i16_type) },
432 .u16 => .{ .ty = Type.initTag(.type), .val = Value.initTag(.u16_type) },
433 .i32 => .{ .ty = Type.initTag(.type), .val = Value.initTag(.i32_type) },
434 .u32 => .{ .ty = Type.initTag(.type), .val = Value.initTag(.u32_type) },
435 .i64 => .{ .ty = Type.initTag(.type), .val = Value.initTag(.i64_type) },
436 .u64 => .{ .ty = Type.initTag(.type), .val = Value.initTag(.u64_type) },
381 .isize => .{ .ty = Type.initTag(.type), .val = Value.initTag(.isize_type) },437 .isize => .{ .ty = Type.initTag(.type), .val = Value.initTag(.isize_type) },
382 .usize => .{ .ty = Type.initTag(.type), .val = Value.initTag(.usize_type) },438 .usize => .{ .ty = Type.initTag(.type), .val = Value.initTag(.usize_type) },
383 .c_short => .{ .ty = Type.initTag(.type), .val = Value.initTag(.c_short_type) },439 .c_short => .{ .ty = Type.initTag(.type), .val = Value.initTag(.c_short_type) },
...@@ -591,7 +647,10 @@ pub const Module = struct {...@@ -591,7 +647,10 @@ pub const Module = struct {
591 ) @TypeOf(stream).Error!void {647 ) @TypeOf(stream).Error!void {
592 // TODO I tried implementing this with an inline for loop and hit a compiler bug648 // TODO I tried implementing this with an inline for loop and hit a compiler bug
593 switch (inst.tag) {649 switch (inst.tag) {
650 .arg => return self.writeInstToStreamGeneric(stream, .arg, inst, inst_table),
651 .block => return self.writeInstToStreamGeneric(stream, .block, inst, inst_table),
594 .breakpoint => return self.writeInstToStreamGeneric(stream, .breakpoint, inst, inst_table),652 .breakpoint => return self.writeInstToStreamGeneric(stream, .breakpoint, inst, inst_table),
653 .breakvoid => return self.writeInstToStreamGeneric(stream, .breakvoid, inst, inst_table),
595 .call => return self.writeInstToStreamGeneric(stream, .call, inst, inst_table),654 .call => return self.writeInstToStreamGeneric(stream, .call, inst, inst_table),
596 .declref => return self.writeInstToStreamGeneric(stream, .declref, inst, inst_table),655 .declref => return self.writeInstToStreamGeneric(stream, .declref, inst, inst_table),
597 .declref_str => return self.writeInstToStreamGeneric(stream, .declref_str, inst, inst_table),656 .declref_str => return self.writeInstToStreamGeneric(stream, .declref_str, inst, inst_table),
...@@ -691,7 +750,7 @@ pub const Module = struct {...@@ -691,7 +750,7 @@ pub const Module = struct {
691 },750 },
692 bool => return stream.writeByte("01"[@boolToInt(param)]),751 bool => return stream.writeByte("01"[@boolToInt(param)]),
693 []u8, []const u8 => return std.zig.renderStringLiteral(param, stream),752 []u8, []const u8 => return std.zig.renderStringLiteral(param, stream),
694 BigIntConst => return stream.print("{}", .{param}),753 BigIntConst, usize => return stream.print("{}", .{param}),
695 TypedValue => unreachable, // this is a special case754 TypedValue => unreachable, // this is a special case
696 *IrModule.Decl => unreachable, // this is a special case755 *IrModule.Decl => unreachable, // this is a special case
697 else => |T| @compileError("unimplemented: rendering parameter of type " ++ @typeName(T)),756 else => |T| @compileError("unimplemented: rendering parameter of type " ++ @typeName(T)),
...@@ -718,7 +777,7 @@ pub const Module = struct {...@@ -718,7 +777,7 @@ pub const Module = struct {
718};777};
719778
720pub fn parse(allocator: *Allocator, source: [:0]const u8) Allocator.Error!Module {779pub fn parse(allocator: *Allocator, source: [:0]const u8) Allocator.Error!Module {
721 var global_name_map = std.StringHashMap(usize).init(allocator);780 var global_name_map = std.StringHashMap(*Inst).init(allocator);
722 defer global_name_map.deinit();781 defer global_name_map.deinit();
723782
724 var parser: Parser = .{783 var parser: Parser = .{
...@@ -752,22 +811,24 @@ const Parser = struct {...@@ -752,22 +811,24 @@ const Parser = struct {
752 i: usize,811 i: usize,
753 source: [:0]const u8,812 source: [:0]const u8,
754 decls: std.ArrayListUnmanaged(*Decl),813 decls: std.ArrayListUnmanaged(*Decl),
755 global_name_map: *std.StringHashMap(usize),814 global_name_map: *std.StringHashMap(*Inst),
756 error_msg: ?ErrorMsg = null,815 error_msg: ?ErrorMsg = null,
757 unnamed_index: usize,816 unnamed_index: usize,
758817
759 const Body = struct {818 const Body = struct {
760 instructions: std.ArrayList(*Inst),819 instructions: std.ArrayList(*Inst),
761 name_map: std.StringHashMap(usize),820 name_map: *std.StringHashMap(*Inst),
762 };821 };
763822
764 fn parseBody(self: *Parser) !Module.Body {823 fn parseBody(self: *Parser, body_ctx: ?*Body) !Module.Body {
824 var name_map = std.StringHashMap(*Inst).init(self.allocator);
825 defer name_map.deinit();
826
765 var body_context = Body{827 var body_context = Body{
766 .instructions = std.ArrayList(*Inst).init(self.allocator),828 .instructions = std.ArrayList(*Inst).init(self.allocator),
767 .name_map = std.StringHashMap(usize).init(self.allocator),829 .name_map = if (body_ctx) |bctx| bctx.name_map else &name_map,
768 };830 };
769 defer body_context.instructions.deinit();831 defer body_context.instructions.deinit();
770 defer body_context.name_map.deinit();
771832
772 try requireEatBytes(self, "{");833 try requireEatBytes(self, "{");
773 skipSpace(self);834 skipSpace(self);
...@@ -782,7 +843,7 @@ const Parser = struct {...@@ -782,7 +843,7 @@ const Parser = struct {
782 skipSpace(self);843 skipSpace(self);
783 const decl = try parseInstruction(self, &body_context, ident);844 const decl = try parseInstruction(self, &body_context, ident);
784 const ident_index = body_context.instructions.items.len;845 const ident_index = body_context.instructions.items.len;
785 if (try body_context.name_map.put(ident, ident_index)) |_| {846 if (try body_context.name_map.put(ident, decl.inst)) |_| {
786 return self.fail("redefinition of identifier '{}'", .{ident});847 return self.fail("redefinition of identifier '{}'", .{ident});
787 }848 }
788 try body_context.instructions.append(decl.inst);849 try body_context.instructions.append(decl.inst);
...@@ -866,12 +927,12 @@ const Parser = struct {...@@ -866,12 +927,12 @@ const Parser = struct {
866 skipSpace(self);927 skipSpace(self);
867 try requireEatBytes(self, "=");928 try requireEatBytes(self, "=");
868 skipSpace(self);929 skipSpace(self);
869 const inst = try parseInstruction(self, null, ident);930 const decl = try parseInstruction(self, null, ident);
870 const ident_index = self.decls.items.len;931 const ident_index = self.decls.items.len;
871 if (try self.global_name_map.put(ident, ident_index)) |_| {932 if (try self.global_name_map.put(ident, decl.inst)) |_| {
872 return self.fail("redefinition of identifier '{}'", .{ident});933 return self.fail("redefinition of identifier '{}'", .{ident});
873 }934 }
874 try self.decls.append(self.allocator, inst);935 try self.decls.append(self.allocator, decl);
875 },936 },
876 ' ', '\n' => self.i += 1,937 ' ', '\n' => self.i += 1,
877 0 => break,938 0 => break,
...@@ -1032,7 +1093,7 @@ const Parser = struct {...@@ -1032,7 +1093,7 @@ const Parser = struct {
1032 };1093 };
1033 }1094 }
1034 switch (T) {1095 switch (T) {
1035 Module.Body => return parseBody(self),1096 Module.Body => return parseBody(self, body_ctx),
1036 bool => {1097 bool => {
1037 const bool_value = switch (self.source[self.i]) {1098 const bool_value = switch (self.source[self.i]) {
1038 '0' => false,1099 '0' => false,
...@@ -1060,6 +1121,10 @@ const Parser = struct {...@@ -1060,6 +1121,10 @@ const Parser = struct {
1060 *Inst => return parseParameterInst(self, body_ctx),1121 *Inst => return parseParameterInst(self, body_ctx),
1061 []u8, []const u8 => return self.parseStringLiteral(),1122 []u8, []const u8 => return self.parseStringLiteral(),
1062 BigIntConst => return self.parseIntegerLiteral(),1123 BigIntConst => return self.parseIntegerLiteral(),
1124 usize => {
1125 const big_int = try self.parseIntegerLiteral();
1126 return big_int.to(usize) catch |err| return self.fail("integer literal: {}", .{@errorName(err)});
1127 },
1063 TypedValue => return self.fail("'const' is a special instruction; not legal in ZIR text", .{}),1128 TypedValue => return self.fail("'const' is a special instruction; not legal in ZIR text", .{}),
1064 *IrModule.Decl => return self.fail("'declval_in_module' is a special instruction; not legal in ZIR text", .{}),1129 *IrModule.Decl => return self.fail("'declval_in_module' is a special instruction; not legal in ZIR text", .{}),
1065 else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),1130 else => @compileError("Unimplemented: ir parseParameterGeneric for type " ++ @typeName(T)),
...@@ -1075,7 +1140,7 @@ const Parser = struct {...@@ -1075,7 +1140,7 @@ const Parser = struct {
1075 };1140 };
1076 const map = if (local_ref)1141 const map = if (local_ref)
1077 if (body_ctx) |bc|1142 if (body_ctx) |bc|
1078 &bc.name_map1143 bc.name_map
1079 else1144 else
1080 return self.fail("referencing a % instruction in global scope", .{})1145 return self.fail("referencing a % instruction in global scope", .{})
1081 else1146 else
...@@ -1107,11 +1172,7 @@ const Parser = struct {...@@ -1107,11 +1172,7 @@ const Parser = struct {
1107 return &declval.base;1172 return &declval.base;
1108 }1173 }
1109 };1174 };
1110 if (local_ref) {1175 return kv.value;
1111 return body_ctx.?.instructions.items[kv.value];
1112 } else {
1113 return self.decls.items[kv.value].inst;
1114 }
1115 }1176 }
11161177
1117 fn generateName(self: *Parser) ![]u8 {1178 fn generateName(self: *Parser) ![]u8 {
...@@ -1456,7 +1517,7 @@ const EmitZIR = struct {...@@ -1456,7 +1517,7 @@ const EmitZIR = struct {
14561517
1457 fn emitBody(1518 fn emitBody(
1458 self: *EmitZIR,1519 self: *EmitZIR,
1459 body: IrModule.Body,1520 body: ir.Body,
1460 inst_table: *std.AutoHashMap(*ir.Inst, *Inst),1521 inst_table: *std.AutoHashMap(*ir.Inst, *Inst),
1461 instructions: *std.ArrayList(*Inst),1522 instructions: *std.ArrayList(*Inst),
1462 ) Allocator.Error!void {1523 ) Allocator.Error!void {
...@@ -1466,6 +1527,57 @@ const EmitZIR = struct {...@@ -1466,6 +1527,57 @@ const EmitZIR = struct {
1466 };1527 };
1467 for (body.instructions) |inst| {1528 for (body.instructions) |inst| {
1468 const new_inst = switch (inst.tag) {1529 const new_inst = switch (inst.tag) {
1530 .add => blk: {
1531 const old_inst = inst.cast(ir.Inst.Add).?;
1532 const new_inst = try self.arena.allocator.create(Inst.Add);
1533 new_inst.* = .{
1534 .base = .{
1535 .src = inst.src,
1536 .tag = Inst.Add.base_tag,
1537 },
1538 .positionals = .{
1539 .lhs = try self.resolveInst(new_body, old_inst.args.lhs),
1540 .rhs = try self.resolveInst(new_body, old_inst.args.rhs),
1541 },
1542 .kw_args = .{},
1543 };
1544 break :blk &new_inst.base;
1545 },
1546 .arg => blk: {
1547 const old_inst = inst.cast(ir.Inst.Arg).?;
1548 const new_inst = try self.arena.allocator.create(Inst.Arg);
1549 new_inst.* = .{
1550 .base = .{
1551 .src = inst.src,
1552 .tag = Inst.Arg.base_tag,
1553 },
1554 .positionals = .{ .index = old_inst.args.index },
1555 .kw_args = .{},
1556 };
1557 break :blk &new_inst.base;
1558 },
1559 .block => blk: {
1560 const old_inst = inst.cast(ir.Inst.Block).?;
1561 const new_inst = try self.arena.allocator.create(Inst.Block);
1562
1563 var block_body = std.ArrayList(*Inst).init(self.allocator);
1564 defer block_body.deinit();
1565
1566 try self.emitBody(old_inst.args.body, inst_table, &block_body);
1567
1568 new_inst.* = .{
1569 .base = .{
1570 .src = inst.src,
1571 .tag = Inst.Block.base_tag,
1572 },
1573 .positionals = .{
1574 .label = try self.autoName(),
1575 .body = .{ .instructions = block_body.toOwnedSlice() },
1576 },
1577 .kw_args = .{},
1578 };
1579 break :blk &new_inst.base;
1580 },
1469 .breakpoint => try self.emitTrivial(inst.src, Inst.Breakpoint),1581 .breakpoint => try self.emitTrivial(inst.src, Inst.Breakpoint),
1470 .call => blk: {1582 .call => blk: {
1471 const old_inst = inst.cast(ir.Inst.Call).?;1583 const old_inst = inst.cast(ir.Inst.Call).?;
...@@ -1660,6 +1772,14 @@ const EmitZIR = struct {...@@ -1660,6 +1772,14 @@ const EmitZIR = struct {
16601772
1661 fn emitType(self: *EmitZIR, src: usize, ty: Type) Allocator.Error!*Decl {1773 fn emitType(self: *EmitZIR, src: usize, ty: Type) Allocator.Error!*Decl {
1662 switch (ty.tag()) {1774 switch (ty.tag()) {
1775 .i8 => return self.emitPrimitive(src, .i8),
1776 .u8 => return self.emitPrimitive(src, .u8),
1777 .i16 => return self.emitPrimitive(src, .i16),
1778 .u16 => return self.emitPrimitive(src, .u16),
1779 .i32 => return self.emitPrimitive(src, .i32),
1780 .u32 => return self.emitPrimitive(src, .u32),
1781 .i64 => return self.emitPrimitive(src, .i64),
1782 .u64 => return self.emitPrimitive(src, .u64),
1663 .isize => return self.emitPrimitive(src, .isize),1783 .isize => return self.emitPrimitive(src, .isize),
1664 .usize => return self.emitPrimitive(src, .usize),1784 .usize => return self.emitPrimitive(src, .usize),
1665 .c_short => return self.emitPrimitive(src, .c_short),1785 .c_short => return self.emitPrimitive(src, .c_short),