| author | |
| committer | |
| log | 130c7fd23b9f23aa5afad2eb1744ffab9e193715 |
| tree | b39e5cf093a901c7713009d4c4448e0702d4ead7 |
| parent | e820678ca1c1a66b561e760fb6aae4df4babf8ba |
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"); |
| 15 | const zir = @import("zir.zig"); | 15 | const zir = @import("zir.zig"); |
| 16 | const Module = @This(); | 16 | const Module = @This(); |
| 17 | const Inst = ir.Inst; | 17 | const Inst = ir.Inst; |
| 18 | const Body = ir.Body; | ||
| 18 | const ast = std.zig.ast; | 19 | const ast = std.zig.ast; |
| 19 | const trace = @import("tracy.zig").trace; | 20 | const trace = @import("tracy.zig").trace; |
| 20 | 21 | ||
| ... | @@ -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 DeclAnalysis | 657 | /// 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 | }; |
| 658 | 667 | ||
| 659 | /// This is a temporary structure, references to it are valid only | 668 | /// 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 | }; |
| 678 | 687 | ||
| 679 | pub const Body = struct { | ||
| 680 | instructions: []*Inst, | ||
| 681 | }; | ||
| 682 | |||
| 683 | pub const AllErrors = struct { | 688 | pub 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 { |
| 1139 | 1144 | ||
| 1140 | const body_node = fn_proto.body_node orelse | 1145 | 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 }, .{}); |
| 1180 | 1188 | ||
| ... | @@ -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); |
| 1185 | 1193 | ||
| 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 | } |
| 1308 | 1318 | ||
| 1319 | fn 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 | |||
| 1309 | fn astGenControlFlowExpression( | 1333 | fn 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 | } |
| 1357 | 1392 | ||
| ... | @@ -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) |
| 1494 | 1529 | ||
| 1495 | fn astGenCall(self: *Module, scope: *Scope, call: *ast.Node.Call) InnerError!*zir.Inst { | 1530 | fn 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); | ||
| 1497 | 1533 | ||
| 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); | ||
| 1502 | 1539 | ||
| 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 | } |
| 1509 | 1546 | ||
| ... | @@ -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 |
| 2323 | 2361 | ||
| 2324 | fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Inst { | 2362 | fn 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 | } |
| 2438 | 2479 | ||
| 2480 | fn 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 | |||
| 2496 | fn 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 | |||
| 2439 | fn analyzeInstBreakpoint(self: *Module, scope: *Scope, inst: *zir.Inst.Breakpoint) InnerError!*Inst { | 2556 | fn 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 | } |
| 2443 | 2560 | ||
| 2561 | fn 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 | |||
| 2444 | fn analyzeInstDeclRefStr(self: *Module, scope: *Scope, inst: *zir.Inst.DeclRefStr) InnerError!*Inst { | 2579 | fn 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 |
| 2602 | fn analyzeInstFnType(self: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst { | 2737 | fn 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); |
| 2604 | 2739 | ||
| 2605 | if (return_type.zigTypeTag() == .NoReturn and | 2740 | // Hot path for some common function types. |
| 2606 | fntype.positionals.param_types.len == 0 and | 2741 | 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 | } | ||
| 2611 | 2745 | ||
| 2612 | if (return_type.zigTypeTag() == .Void and | 2746 | if (return_type.zigTypeTag() == .Void and fntype.kw_args.cc == .Unspecified) { |
| 2613 | fntype.positionals.param_types.len == 0 and | 2747 | 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 | } | ||
| 2618 | 2749 | ||
| 2619 | if (return_type.zigTypeTag() == .NoReturn and | 2750 | if (return_type.zigTypeTag() == .NoReturn and fntype.kw_args.cc == .Naked) { |
| 2620 | fntype.positionals.param_types.len == 0 and | 2751 | 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 | } |
| 2625 | 2758 | ||
| 2626 | if (return_type.zigTypeTag() == .Void and | 2759 | const arena = scope.arena(); |
| 2627 | fntype.positionals.param_types.len == 0 and | 2760 | 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 | } |
| 2632 | 2764 | ||
| 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 | } |
| 2635 | 2773 | ||
| 2636 | fn analyzeInstPrimitive(self: *Module, scope: *Scope, primitive: *zir.Inst.Primitive) InnerError!*Inst { | 2774 | fn 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 | } |
| 2758 | 2896 | ||
| 2759 | fn analyzeInstAdd(self: *Module, scope: *Scope, inst: *zir.Inst.Add) InnerError!*Inst { | 2897 | fn 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); |
| 2762 | 2903 | ||
| 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 without | 2911 | // 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]; |
| 2779 | 2924 | ||
| 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 | } |
| 2801 | 2948 | ||
| 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); |
| 2937 | 3084 | ||
| 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); |
| 2946 | 3094 | ||
| 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); |
| 3180 | 3329 | ||
| 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 | } |
| 3199 | 3348 | ||
| 3349 | fn 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 | |||
| 3200 | fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst { | 3355 | fn 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 { |
| 174 | 174 | ||
| 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 | } |
| 192 | 195 | ||
| 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 | } |
| 304 | 320 | ||
| 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 function | 328 | // 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, |
| 16 | 16 | ||
| 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 | }; |
| 32 | 62 | ||
| 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 | } |
| 52 | 82 | ||
| 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 | }; |
| 75 | 124 | ||
| 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 | }; |
| 112 | 169 | ||
| ... | @@ -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 | |||
| 225 | pub 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, | ||
| 60 | 67 | ||
| 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 | } |
| 236 | 268 | ||
| ... | @@ -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 | }, | ||
| 291 | 339 | ||
| 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 pointer | 478 | .fn_void_no_args, // represents machine code; not a pointer |
| 418 | .fn_naked_noreturn_no_args, // represents machine code; not a pointer | 479 | .fn_naked_noreturn_no_args, // represents machine code; not a pointer |
| 419 | .fn_ccc_void_no_args, // represents machine code; not a pointer | 480 | .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, |
| 422 | 484 | ||
| 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, |
| 782 | 894 | ||
| 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 | } |
| 793 | 908 | ||
| 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 | } |
| 839 | 961 | ||
| 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, | ||
| 873 | 1049 | ||
| 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 | }, | ||
| 920 | 1106 | ||
| 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), |
| 968 | 1216 | ||
| 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, | ||
| 1014 | 1271 | ||
| 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, | ||
| 1060 | 1324 | ||
| 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, | ||
| 1295 | 1593 | ||
| 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 { |
| 1330 | 1628 | ||
| 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 | }; |
| 1335 | 1641 |
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 { |
| 308 | 326 | ||
| 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 { |
| 34 | 34 | ||
| 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 { |
| 75 | 81 | ||
| 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 | } |
| 117 | 126 | ||
| 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 | }; |
| 125 | 155 | ||
| 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 {}, |
| 348 | 388 | ||
| 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 { |
| 378 | 426 | ||
| 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 bug | 648 | // 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 case | 754 | TypedValue => unreachable, // this is a special case |
| 696 | *IrModule.Decl => unreachable, // this is a special case | 755 | *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 | }; |
| 719 | 778 | ||
| 720 | pub fn parse(allocator: *Allocator, source: [:0]const u8) Allocator.Error!Module { | 779 | pub 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(); |
| 723 | 782 | ||
| 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, |
| 758 | 817 | ||
| 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 | }; |
| 763 | 822 | ||
| 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(); | ||
| 771 | 832 | ||
| 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_map | 1143 | bc.name_map |
| 1079 | else | 1144 | else |
| 1080 | return self.fail("referencing a % instruction in global scope", .{}) | 1145 | return self.fail("referencing a % instruction in global scope", .{}) |
| 1081 | else | 1146 | 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 | } |
| 1116 | 1177 | ||
| 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 { |
| 1456 | 1517 | ||
| 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 { |
| 1660 | 1772 | ||
| 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), |